「Windows平台高级工程师」基础入门:win窗口原理
liebian365 2024-10-26 12:59 6 浏览 0 评论
1、Windows程序开发流程:
Windows 程序分为「程序代码」和「UI资源」两大部分,通过RC编译器整合为一个完整的EXE 文件。
所谓UI 资源是指功能菜单、对话框外貌、程序图标、光标形状等等东西。
这些UI 资源的实际内容(二进制代码)系借助各种工具产生,并以各种扩展名存在,如.ico、.bmp、.cur 等等。程序员必须在一个所谓的资源描述档(.rc)中描述它们。
RC 编译器(RC.EXE)读取RC 档的描述后将所有UI资源档集中制作出一个.RES 档,再与程序代码结合在一起,这才是一个完整的Windows可执行文件。
2、Windows程序与操作系统之间的关系
Windows 程序的进行系依靠外部发生的事件来驱动。换句话说,程序不断等待(利用一个while 回路),等待任何可能的输入,然后做判断,然后再做适当的处理。上述的「输入」是由操作系统捕捉到之后,以消息形式(一种数据结构)进入程序之中。
3、Windows窗口生命周期如下:
1.程序初始化过程中调用CreateWindow,为程序建立了一个窗口,作为程序的屏幕舞台。CreateWindow产生窗口之后会送出 wM_CREATE直接给窗口函数,后者于是可以在此时做些初始化操作(例如配置内存、打开文件、读初始数据……)。
2在程序活着的过程中,不断以 GetMessage从消息队列中抓取消息。如果这个消息是WM_oUIT,GetMessage会传回0而结束while循环,进而结束整个程序。
3.DispatchMessage通过Windows USER模块的协助与监督,把消息分派至窗口函数。消息将在该处被判别并处理。
4.程序不断进行第2步和第3步的操作。
5.当使用者按下系统菜单中的Close命令项时,系统送出WM_CLOSE。通常程序的窗口函数不拦截此消息,于是 DefWindowProc处理它。
6.DefWindowProc收到 WM_CLOSE后,调用 DestroyWindow把窗口清除。Destroy Window本身又会送出WM_DESTROY。
7.程序对WM_DESTROY的标准反应是调用PostQuitMessage。
8.PostQuitMessage没什么其它操作,就只送出 WM_QUIT 消息,准备让消息循环中的GetMessage取得,如步骤2,结束消息循环。
3.Windows窗体原理
Windows的三大核心系统:负责窗口对象产生和消息分发的USER模块,负责图像显示绘制的GDI模块,负责内存、进程、IO管理的KERNEL模块。
试想象一下如何在一个像素阵列上产生窗口对象,其实就是使用GDI绘制窗口,不停的以一定的频率刷新显示在屏幕上,这就是图形界面,如果由在DOS或Windows DOS模拟器下编写图形界面的经验这个比较好理解。所以说其实USER模块中的窗口产生是依靠GDI模块的(包括菜单、滚动条等都是使用GDI来绘制的)。
那么,下面我们就从USER模块和GDI模块来说说Windows 的窗体原理。
如果接触过Win32 SDK编程的知道一个标准Windows窗体的产生过程:
- 设计窗口类、
- 注册窗口类、
- 创建窗口、
- 显示窗口、
- 启动消息循环泵循环获取消息分发到窗体过程函数处理。
贴上一个标准Windows窗体的产生代码:
#include <windows.h>
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("窗口类名称");
HWND hwnd;
MSG msg;
WNDCLASSEX wndclassex = {0};
//设计窗口类
wndclassex.cbSize = sizeof(WNDCLASSEX);
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
wndclassex.lpfnWndProc = WndProc;
wndclassex.cbClsExtra = 0;
wndclassex.cbWndExtra = 0;
wndclassex.hInstance = hInstance;
wndclassex.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclassex.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wndclassex.lpszMenuName = NULL;
wndclassex.lpszClassName = szAppName;
wndclassex.hIconSm = wndclassex.hIcon;
//注册窗口类
if (!RegisterClassEx (&wndclassex))
{
MessageBox (NULL, TEXT ("RegisterClassEx failed!"), szAppName, MB_ICONERROR);
return 0;
}
//产生窗口
hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW,
szAppName,
TEXT ("窗口名称"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
//显示窗口
ShowWindow (hwnd, iCmdShow);
UpdateWindow (hwnd);
//启动消息循环泵循环获取消息分配到窗体过程函数处理
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
//窗体过程函数
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch (message)
{
case WM_CREATE:
return (0);
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
EndPaint (hwnd, &ps);
return (0);
case WM_DESTROY:
PostQuitMessage (0);
return (0);
}
return DefWindowProc (hwnd, message, wParam, lParam);
}
需要明白的是,所有Windows的窗体及控件归根结底都是使用CreateWindow或CreateWindowEx来创建的,他们都需要标准Windows窗体的产生过程。
普通的窗体好理解,主要需要弄清楚是对话框及控件的产生和消息分派处理流程。
对话框及其子控件的管理依靠Windows内建的对话框管理器,对话框管理器的工作包括:
1.根据我们在资源设计器中设计的对话框及子控件产生的.rc文件来自动生成对话框和子控件(如果有手动编写.rc文件的经历的话,知道编写RC文件其实就是指定窗口和子控件大小、类型、样式等参数,对话框管理器将这些参数传入CreateWindow函数产生窗体)
2.模态对话框直接显示窗体,非模态对话框消息指明WS_VISIBLE属性的话,需要调用ShowWindow来显示窗体。
3.维护一个消息循环泵,对于模态对话框来说这个消息泵的消息不经过父窗口,所以表现为模态;对于非模态对话框这个消息泵消息经过主窗口,必须由主窗口传给非模态对话框,表现为非模态。
4.维护一个内建的窗体过程函数,对于对话框来说会处理对话框的关闭打开及子窗口的焦点、tab等,对于子控件也是一样,每个子控件会有自己类型的窗体过程函数,窗体过程函数处理子控件的获得或失去焦点、按下或弹起、创建等表现样式和行为。
对于对话框来说,他会开放一个对话框过程函数,让部分消息先通过对话框管理函数处理,如果对话框过程函数不处理才交给默认的内建过程函数处理,对于子控件来说,他们并没有开放过程函数,而是由内建窗体函数将要处理的消息发给父窗口处理。
那么对话框管理器完成了标准Windows窗体的产生中后半部分工作,至于设计窗口类和注册窗口类这是由Windows自己预先做好了的,如常见的“button”、“listbox”、“edit”类等等。
那么既然所有的窗体(包括对话框和控件)产生过程一样,那么我们就可以将对话框管理器的部分工作替换掉:
1.不使用对话框读取.rc模板的方式,直接将参数传递给CreateWindow函数来创建对话框和控件,这就是常见的动态创建控件原理。
2.设置控件自绘制如BS_OWNDRAW属性,开放控件的WM_DRAWITEM消息给父窗口,由父窗口来绘制按钮样式,这就是常见的控件重绘原理。
3.替换内建的窗体函数,将消息传到自定义的窗体过程函数处理,这就是常见的控件子类化原理。
需要Windows操作系统和开发工具的小伙伴,可以点击下方了解更多免费领取噢~
下一节讲:MFC对话框原理
相关推荐
- 快递查询教程,批量查询物流,一键管理快递
-
作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...
- 一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递
-
对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...
- 快递查询单号查询,怎么查物流到哪了
-
输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...
- 3分钟查询物流,教你一键批量查询全部物流信息
-
很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...
- 快递单号查询,一次性查询全部物流信息
-
现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...
- 快递查询工具,批量查询多个快递快递单号的物流状态、签收时间
-
最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...
- 快递查询软件,自动识别查询快递单号查询方法
-
当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...
- 教你怎样查询快递查询单号并保存物流信息
-
商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...
- 简单几步骤查询所有快递物流信息
-
在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...
- 物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号
-
最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...
- 连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息
-
快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...
- 快递查询教程,快递单号查询,筛选更新量为1的单号
-
最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...
- 掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析
-
在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...
- 从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息
-
在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...
- 物流单号查询,在哪里查询快递
-
如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)