您的位置:首页 > 其它

Windows程序设计--窗口与消息

2015-09-09 14:43 447 查看
进行Windows程序设计时,其实就是在进行一种面向对象的编程。在面向对象中,对象是代码和数据的组合,一个窗口也是一个对象。

在用户眼中,窗口是屏幕上的对象,并可借助键盘或鼠标直接与之进行交互。

用户对窗口的输入以“消息”的形式传递给窗口,而窗口也借助消息来与其他窗口进行通信。

窗口创建看似容易,调用CreateWindow函数即可。

但是在创建窗口之前,需要注册一个窗口类。而窗口类又确定了处理窗口消息的窗口过程。

多个窗口可以同时基于某一窗口类来创建。注册窗口类必须调用RegisterClass函数。该函数只有一个参数,即一个指向WNDCLASS类型的结构的指针。下面我们看看这个结构:

首先是ASCII版本:

typedef struct tagWNDCLASSA{ 
    UINT       style; 
    WNDPROC    lpfnWndProc; 
    int        cbClsExtra; 
    int        cbWndExtra; 
    HINSTANCE  hInstance; 
    HICON      hIcon; 
    HCURSOR    hCursor; 
    HBRUSH     hbrBackground; 
    LPCSTR    lpszMenuName; 
    LPCSTR    lpszClassName; 
} WNDCLASS, *PWNDCLASS;


其次是Unicode版本:

typedef struct tagWNDCLASSW{ 
    UINT       style; 
    WNDPROC    lpfnWndProc; 
    int        cbClsExtra; 
    int        cbWndExtra; 
    HINSTANCE  hInstance; 
    HICON      hIcon; 
    HCURSOR    hCursor; 
    HBRUSH     hbrBackground; 
    LPCWSTR    lpszMenuName; 
    LPCWSTR    lpszClassName; 
} WNDCLASS, *PWNDCLASS;


可以看到只有最后两个字段不同,Unicode被定义为宽字符的常量字符串。

在WNDCLASS中最重要的两个字段是第二个lpfnWndProc和最后一个lpszClassName。

第二个字段是基于该窗口类的所有窗口的窗口过程的地址。

最后一个字段是窗口类的名称。

接下来该是创建了:

hwnd = CreateWindow(szAppName,                 //窗口类的名称
                    TEXT("The Hello Program"), //窗口标题
                    WS_OVERLAPPEDWINDOW,       //窗口风格
                    CW_USEDEFAULT,             //初始x坐标
                    CW_USEDEFAULT,             //初始y坐标
                    CW_USEDEFAULT,             //初始x方向尺寸
                    CW_USEDEFAULT,             //初始y方向尺寸
                    NULL,                      //父窗口句柄
                    NULL,                      //窗口菜单句柄
                    hInstance,                 //程序实例句柄
                    NULL);                     //创建参数


创建之后,就该是窗口的显示了。即函数ShowWindow(hwnd, iCmdShow);

第一个参数就是CreateWindow所创建的窗口的句柄。

第二个参数就是WinMain函数所接受的iCmdShow值。

然后调用UpdateWindow(hwnd)进行窗口客户区重绘。

在UpdateWindow后,新建的窗口在屏幕中便完全可见了。

此时,该程序必须能够接收来自用户的键盘输入和鼠标输入。是如何做到的呢?

Windows为当前在其中运行的每一个Windows程序都维护了一个“消息队列”。当输入时间发生后,Windows会自动将这些事件转换为“消息”,并将其放置在应用程序的消息队列中。

应用程序通过如下代码循环:

while(GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);//用于从消息队列中对消息进行检索
    DispatchMessage(&msg);//将msg结构返还给Windows以进行某些键盘消息的转换
}


其中msg是一个结构变量,定义如下:

typedef struct tagMSG {
  HWND   hwnd; 
  UINT   message; 
  WPARAM wParam; 
  LPARAM lParam; 
  DWORD  time; 
  POINT  pt; 
} MSG, *PMSG;


上诉结构中的POINT是另一种结构:

typedef struct tagPOINT { 
  LONG x; 
  LONG y; 
} POINT, *PPOINT;


下面介绍真正有意思的事情–窗口过程

一个windows程序可以包含多个窗口过程,但一个窗口过程总是与一个通过调用RegisterClass注册的特定窗口类相关联。

窗口过程总是按照如下定义:

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)


窗口过程函数的四个参数与MSG结构的4个字段一一对应。

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

第二个参数:消息标识符

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

最后就是消息处理了:

switch(message)
{
case WM_CREATE:
     [处理WM_CREATE消息]
     return 0;
case WM_PAINT:
     [处理WM_PAINT消息]
     return 0;

 case WM_DESTROY:
     [处理WM_DESTROY消息]
     return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: