现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

Win32 关键点总结(1):窗口和消息

2012-09-10 12:16 工业·编程 ⁄ 共 4595字 ⁄ 字号 评论 1 条

一 窗口和消息

1 WPARAM和LPARAM的意义

   在Windows是一种16位系统时,WndProc的第三个参数被定义为WORD,是一个16位的无符号整数,而第四个参数被定义为一个LONG,是一个32位有符号整数,所以导致对单词PARAM(参数)加前缀W和L。

    但在32位Windows中,WPARAM被定义为一个UINT,而LPARAM被定义为一个LONG,因此窗口过程的这两个参数都是32位的值。

2 前缀

前缀

全称

释义

CS

class style

类风格选项

CW

create windows

创建窗口选项

DT

draw text

绘制文本选项

IDI

Icon ID

图标ID

IDC

Cursor ID

光标ID

MB

Message Box

消息框选项

SND

Sound

声音选项

WM

Windows Message

窗口消息

WS

Windows Style

窗口风格


3 新的函数类型

WndProc函数返回一个类型为LRESULT的值,该值是一个LONG型,32位有符号。

WndProc函数被指定为CALLBACK类型,WinMain函数被指定为WINAPI类型。这些类型指在Windows本身和用户的应用程序之间发生的函数调用的特殊调用序列。

4 窗口类结构WNDCLASS

有10个域。分别是:

① style:类风格,用于在什么时候发出窗口变化消息

② cbClsExtra:在类结构保存的窗口结构中预留一些额外空间

       ③ cbWndExtra:在Windows内部保存的窗口结构中预留一些额外空间

       ④ hbrBackground:指定基于这个类创建的窗口背景颜色

       ⑤ hCursor:读取光标

       ⑥ hIcon:读取图标

       ⑦ hInstance:程序的实例句柄

       ⑧ lpfnWndProc:指定处理基于这个窗口类创建的所有窗口的窗口过程

       ⑨ lpszClassName:指定类名

       ⑩ lpszMenuName:指定窗口类菜单

5 注册窗口类RegisterClass

一般在Windows XP及以后都可以很顺利的注册成功。

所以可以只写RegisterClass(&wndclass);

6 创建窗口CreateWindow

    窗口类定义了窗口的一般特征,调用CreateWindow可以指定有关窗口的更详细的信息。

hwnd = CreateWindow (szAppName,          // 指定一个窗口类,基于该窗口类创建窗口

                   TEXT ("Hello Win"),    // 这个字符串会出现在标题栏中

                   WS_OVERLAPPEDWINDOW, // 本窗口风格

                   CW_USEDEFAULT,         //窗口左上角的X坐标

                   CW_USEDEFAULT,         //窗口左上角的Y坐标

                   CW_USEDEFAULT,         //窗口的宽度

                   CW_USEDEFAULT,         //窗口的高度

                   NULL,                    //窗口对象的父窗口句柄

                   NULL,                    //窗口对象的菜单句柄或者子窗口编号

                   hInstance,                  //当前进程的实例句柄

                   NULL) ;                   //窗口对象的参数指针句柄

创建窗口返回的是窗口句柄。

7 显示窗口

窗口创建成功后,系统将在内存中为其分配一块内存,但是此时窗口并未显示在显示器上,所以需要使用两个调用。

① ShowWindow(窗口句柄,iCmdShow);

其中的第二个参数用于确定如何儿子屏幕上显示窗口,是最小化还是常规还是最大化。

② UpdateWindow(窗口句柄)

调用上句将导致客户区被绘制。它通过给窗口过程发送一个WM_PAINT消息来做到这一点。

8 消息循环

调用UpdateWindow之后,窗口就出现在显示器上。

Windows为当前运行的每个Windows程序维护一个“消息队列”。在发生事件的时候,Windows将事件转换为一个“消息”,并将消息放入程序的消息队列中。

程序通过执行一个叫做“消息循环”的代码从消息队列中取出消息。

while (GetMessage(&msg, NULL, 0, 0))

           {

                  TranslateMessage(&msg);

                  DispatchMessage(&msg);

           }

其中msg是一个类型为MSG的结构,MSG结构在WINUSER.H中定义如下:

typedef struct tagMSG {

    HWND       hwnd;

    UINT         message;

    WPARAM     wParam;

    LPARAM      lParam;

    DWORD      time;

    POINT        pt;

} MSG, *PMSG

其中,hwnd 是消息发向的窗口句柄。

      message 是消息标识符,以WM_开头。

      wParam 一个32位的消息参数。

      lParam 一个32位的消息参数。

      time 消息放入消息队列的时间。

      pt 消息放入消息队列时鼠标的坐标。

消息循环以GetMessage调用开始,它从消息队列中取出一个消息,GetMessage(&msg, NULL, 0, 0)这一调用传给Windows一个指向名为msg的MSG结构的指针。其余三个参数设置为NULL或0,表示程序接收自己创建的所有窗口的所有消息。

只要从消息队列中取出的消息的message域不为WM_QUIT,GetMessage就返回一个非0值,while循环就可以继续。

TranslateMessage(&msg);将msg结构传给Windows,进行一些键盘转换。

DispatchMessage(&msg);将msg结构传给Windows,然后Windows将里面的消息发给相应的窗口过程进行处理。处理后,WndProc返回到Windows,Windows返回到程序,程序继续下一个while循环。

9 窗口过程WndProc

实际的动作发生在窗口过程中。窗口过程确定了在窗口的客户区显示什么,以及怎么处理用户输入。

窗口过程是命名为WndProc的函数。(也可以其他不冲突的名字)

一个Windows程序可以包含多个窗口过程。

一个窗口过程总是与调用RegisterClass注册的特定窗口类相关联。

CreateWindow函数根据特定的窗口类创建一个窗口,返回该窗口的句柄。

但是基于一个窗口类可以创建多个窗口。

1程序     包括   n个窗口过程

1窗口过程 关联   1窗口类

1窗口类   创建   n个窗口

CreateWindows根据窗口类创建一个窗口。

窗口过程总是声明成如下形式:

LRESULT CALLBACK  WndProc(HWND, UINT, WPARAM, LPARAM);

这4个参数跟MSG结构的前4个域是相同的。

第一个参数:接收消息的窗口句柄。

第二个参数:消息类型,标识消息的数字

最后两个参数:32位的消息参数。

程序通常不直接调用窗口过程,而是由Windows调用窗口过程。

10 窗口过程处理消息

窗口过程接收的每个消息均是用一个数值来标识的,也就是传给窗口过程的message参数。

窗口过程处理消息时,必须返回0.

窗口过程不予处理的所有消息应该被传给名为DefWindowsProc的Windows函数。

用switch语句来处理不同消息,消息以WM_开头。

11 WM_CREATE消息

当Windows在处理CreateWindow函数时,窗口过程就会接收到WM_CREATE消息。

通常,窗口过程在WM_CREATE处理期间进行一次窗口初始化。

12 WM_PAINT消息

当窗口客户区域的一部分或全部变成“无效”时,必须进行刷新,WM_PAINT将通知程序。

在最初创建窗口的时候,整个客户区都是无效的,因为程序还没有在窗口上画任何东西。在调用UpdateWindow时,通常会触发第一个WM_PAINT消息,指示窗口过程在客户区域上画一些东西。

在改变程序窗口大小后,客户区也会变得无效,至于怎么变得无效由CS_引导的类风格选项确定。

对WM_PAINT的处理几乎总是从一个BeginPaint调用开始,以一个EndPaint结束。

hdc = BeginPaint(hwnd, &pt);

do something;(如GetClientRect(hwnd, &rect);)

EndPaint(hwnd, &pt);

hwnd是要刷新的窗口的窗口句柄。

pt是指向类型为PAINTSTRUCT的结构指针。

在BeginPaint调用中,如果客户区域的背景还未被擦除,就由Windows来擦除。然后使用注册窗口类的WNDCLASS结构中的hbrBackground域中第一的刷子来删除背景。

BeginPaint调用使整个客户区有效,并返回一个“设备描述表句柄”。设备描述表是指物理输出设备及其驱动程序。可以利用该“设备描述表句柄”在客户区域显示文本和图形。

EndPaint调用释放设备描述表句柄。

GetClientRect(hwnd, &rect);

第一个参数:程序的窗口句柄;

第二个参数:指向RECT类型的rectangle结构。该结构有4个LONG域,标识客户区域的尺寸。

当改变窗口大小时,WndProc通过调用GetClientRect来获取变化后的窗口大小,重新绘制客户区。

13 WM_DESTROY消息

    当用户点击关闭按钮时发生。

程序可以通过调用PostQuitMessage以标准方式响应WM_DESTROY消息;

PostQuitMessage(0);

该函数在程序的消息队列插入一个WM_QUIT消息。

GetMessage对于除了WM_QUIT消息之外的从消息队列中取出的所有消息都返回非0值。而当GetMessage取到一个WM_QUIT消息时,返回0.

14 关闭程序时的消息传递

① 用户点击关闭按钮

② 产生WM_SYSCOMMAND消息;

③ 产生WM_CLOSE消息响应WM_SYSCOMMAND;

④ 产生WM_DESTROY消息响应WM_CLOSE;

⑤ 产生WM_QUIT消息响应WM_DESTROY。

15 进队消息和不进队消息

消息能够分为:进队消息和不进队消息。

进队消息是由Windows放入程序消息队列中的。在程序的消息循环中,重新返回并分配给窗口过程。

不进队消息在Windows调用窗口时直接发送给窗口过程。

也就是说,进队消息发送给消息队列,不进队消息发送给窗口过程。

在任何情况下,窗口过程都将获得窗口所有的消息。窗口过程是窗口的消息中心。

进队消息基本上是用户输入的结果,还包括时钟消息、刷新消息、退出消息。

不进队消息基本上是来自调用特定的Windows函数。

目前有 1 条留言    访客:0 条, 博主:0 条 ,引用: 1 条

    外部的引用: 1 条

    • Win32 关键点总结(2):输出文本 « 求索阁

    给我留言

    留言无头像?