以HELLOWIN为例剖析Windows的一般消息结构

HELLOWIN为例剖析Windows的一般消息结构

// HELLOWIN.cpp

// 时间:2012-10-27

#include <windows.h>

解析:所有的基于windows程序,windows.h的头文件是必须的,是几乎所有用C语言编写的windows程序中都有的预处理器(precocessor)指令,在#include<windows.h>又包含了如#include <windef.h> 基本数据类型定义、#include<winNT.h>支持Unicode的类型定义、#include<winbase.h>内核函数、#include<winuser.h> 用户界面函数、#include<windgdi.h> 图形设备接口函数等等一系列的头文件

 

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

解析:窗口过程函数的声明,窗口过程总是按照如上方式进行定义,参数1. 表示接收消息的窗口的句柄,是CreateWindow函数返回的句柄;参数2. 是MSG结构的message字段,是标识消息的数字,参数3,4,表示两个32位的“消息参数”,参数的含义和取值取决于具体的消息。

 

int WINAPI WinMain(    HINSTANCE hInstance,   // 程序当前实例句柄

                       HINSTANCEhPrevInstance,// 当前实例前一个句柄(在Win32下总为NULL)

                       PSTRszCmdLine,        //以空终止的字符串

                       int iCmdShow           // iCmdShow由程序的调用者(即操作系统)决定

                       )

  解析:正像main是C程序的入口函数一样,Windows程序的入口函数是WinMain, 它总是如上形式出现,其中WINAPI标示符是一种函数调用约定,在#include <windef.h>中有如定义#define  WINAPI  _stdcall

参数3以空终止的字符串,用来运行程序的命令行,有些Windows程序启动是用它来将文件装入内存,如在D盘下有一个hello.txt得文件,当我们用鼠标双击这个文件时记事本启动程序notepad.ext将D:\hello.txt做为命令行参数传给notepad.exe的WinMain函数,notepad.ext程序得到这个文件全路径名后就在窗口显示该文件的内容。具体操作百度。

参数4.指定程序的窗口如何显示,如最大化,最小化,隐藏等,这个参数由程序调用者所指定,我们编写应用程序通常不予理会

{

     // 设计一个窗口类

     static TCHAR szAppName[] = TEXT("HEllOWin");

     WNDCLASSwndclass;    //定义一个WNDCLASS窗口类的结构

     wndclass.style              =CS_HREDRAW | CS_VREDRAW;// 类风格(水平和竖直尺寸被改变)

     wndclass.lpfnWndProc        = WndProc;    // 指定窗口过程函数

     wndclass.cbClsExtra         = 0;          // 类结构预留空间

     wndclass.cbWndExtra         = 0;          // 窗口结构预留空间

     wndclass.hInstance          = hInstance;  // 应用程序的实例

     wndclass.hIcon              = LoadIcon(NULL, IDI_APPLICATION);// 为窗口类的窗口设定一个图标

     wndclass.hCursor            = LoadCursor(NULL, IDC_ARROW);// 载入预定义的鼠标指针形状

     wndclass.hbrBackground      = (HBRUSH) GetStockObject(WHITE_BRUSH); // 窗口客户区的背景色

     wndclass.lpszMenuName       = NULL;       // 窗口类的菜单(不带菜单为NULL

     wndclass.lpszClassName      = szAppName;  // 窗口类的名字

解析:窗口类的设计就是定义一个窗口的基本属性(一般特征属性),多个窗口可以同时基于某一窗口类,而某一窗口的特有属性。可以在CreateWindow函数中予以指定。

参数6. wndclass.hIcon指定窗口类的图标句柄,如果为NULL,则系统将提供一个默认的图标,LoadIcon函数加载一个图标资源,返回系统分配给该资源的句柄,LoadIcon如果加载系统的标准图标,则第一个参数为NULL

常数7.wndclass.hCursor指定窗口类的光标句柄,如果为NULL.那么无论何时鼠标进入到应用程序窗口中,应用程序都必须明确的设置光标的形状。LoadIcon用法同参数6.

参数8.指定窗口类的背景画刷句柄,窗口重绘是系统使用此画刷插除窗口背景

 

     // 注册窗口类

     if (!RegisterClass(&wndclass)) 

     {

         MessageBox(NULL,TEXT("This Program require windows NT!"),

                      szAppName, MB_ICONERROR);

         return 0;

     }

解析:RegisterClass函数对窗口类进行注册,参数为窗口类对象的指针。注册成功后才能够创建窗口

 

     // 创建窗口

     HWND  hwnd;

     // CreateWindow函数返回指向所建窗口的句柄

     hwnd = CreateWindow(   szAppName,                  // 窗口类的名称(wndclass.lpszClassName)

                            TEXT("The Hello Program"),  // 窗口标题(显示在窗口上)

                            WS_OVERLAPPEDWINDOW,        // 窗口风格(多种窗口类型的组合)

                            CW_USEDEFAULT,              // 初始X坐标

                            CW_USEDEFAULT,              // 初始Y坐标

                            CW_USEDEFAULT,              // 初始X方向尺寸

                            CW_USEDEFAULT,              // 初始Y方向的尺寸

                            NULL,                       //父窗口句柄

                            NULL,                       //窗口菜单句柄(NULL表示无菜单)

                            hInstance,                  //程序实例句柄

                            NULL                        //创建参数

                            );

解析:CreateWindow的参数1,指定了窗口类的名称,以便于我们创建的窗口与窗口类相关联,参数2指定窗口的样式,这里我们窗口的样式是重叠的,有最大化,最小化,关闭按钮的形式,参数11(即最后一个),作为WM_CREATE消息的附加参数传入的数据指针,多数窗口为NULL。

 

     // 显示及刷新窗口

     ShowWindow(hwnd,iCmdShow);      //将窗口显示在屏幕中

     UpdateWindow(hwnd);              // 刷新窗口(发送WM_PAINT消息)

解析:CreateWindow调用返回时,窗口已在Windows内部创建,Windows为其分配了一块内存保存CreateWindow调用指定的窗口信息及其他一些信息,那么ShowWindow就是将窗口显示出来。UpdateWindow函数调用重绘刷新窗口,至此,新建窗口完全显示出来,那么接下来就是新建窗口接收来自鼠标和键盘的消息(即下面的消息循环)。

 

     // 定义消息结构体,开始消息循环

     MSG  msg;

     while (GetMessage(&msg, NULL, 0, 0))  // 参数3为NULL表示接收调用线程的所有窗口消息

     {

         TranslateMessage(&msg);     // 虚拟键消息转换为字符消息并将字符消息投递到消息队列

         DispatchMessage(&msg);      // 将消息回传给操作系统,由操作系统调用窗口过程函数

                                     //对消息进行处理(响应)

     }

     return msg.wParam; // 收到WM_QUIT消息后,while返回0,退出循环,执行该语句

解析:当输入事件发生后,Windows会自动将这些事件转换为消息,并将其放置在消息队列中,上面消息循环不断的从消息队列中取出消息,并进行响应。GetMessage函数用于从消息队列中对消息进行检索,该调用将msg得消息结构体变量的指针传给Windows。第二,第三和第四个参数分别设为NULL或0,表示希望获取该程序创建的所有窗口的消息。GetMessage函数只有在接收到WM_QUIT消息时才返回0

returnmsg.wParam;返回语句中msg.wParam字段是传递给PoseQuitMessage函数的参数值(通常情况下位0),

该语句将从WinMain中退出并将程序结束。

 

}

 

// 窗口过程处理函数

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

{

     HDC        hdc;

     PAINTSTRUCT ps;

     RECT     rect;

 

     switch(message)

     {

     case WM_CREATE:

         PlaySound(TEXT("Hellowin.wav"), NULL, SND_FILENAME |SND_ASYNC);

         return 0;

 

     case WM_PAINT:

         hdc =BeginPaint(hwnd, &ps);

 

         GetClientRect(hwnd,&rect);

 

         DrawText(hdc,TEXT("Hello, window 7!"), -1,&rect,

              DT_SINGLELINE| DT_CENTER | DT_VCENTER);

        EndPaint(hwnd, &ps);

        return 0;

 

    case WM_DESTROY:

         PostQuitMessage(0);   // 0为消息WM_QUIT的wParam参数

         return0;

     }

     returnDefWindowProc(hwnd, message, wParam, lParam);

}

解析:当用户点击窗口上的关闭按钮时,系统会给应用程序发送一条WM_CLOSE消息,可以在这条消息中调用DestroyWindow函数销毁窗口(如果没有相应WM_CLOSE消息,则系统将把这条消息传给DefWindowProc函数,而DefWindowProc函数则调用DestroyWindows函数来销毁窗口)。DestroyWindows函数在销毁窗口之后会向窗口过程发送一条WM_DESTROY消息,我们在该消息的响应代码中调用PostQuitMessage函数,PostQuitMessge函数则向应用程序的消息队列中投递一条WM_QUIT消息并返回。此时GetMessage函数收到WM_QUIT消息后返回0,结束消息循环,程序正常退出。

注:传递给PostQuiteMessage函数的参数值通常是WM_QUIT消息的wParam参数,这个值通常用作WinMain函数的返回值,如return msg.wParam;

 

注:在处理CreateWindows函数的过程中,Windows对WndProc函数进行调用,响应WM_CREATE消息,这是整个窗口过程接到的第一条消息。

注:第一条WM_PAIT消息是在调用WinMain中的UpdatWindow时出现的,指示窗口过程在窗口客户区进行绘制。

 

//窗口过程处理函数的另一种写法

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

{                                             

      HDC          hdc;

      PAINTSTRUCTps;

      RECT       rect;

 

      switch(message)

      {

      case WM_CREATE:

           PlaySound(TEXT("Hellowin.wav"), NULL, SND_FILENAME |SND_ASYNC);

           break;

 

      case WM_PAINT:

           hdc =BeginPaint(hwnd, &ps);

 

           GetClientRect(hwnd,&rect);

 

           DrawText(hdc,TEXT("Hello, window 7!"), -1,&rect,

                 DT_SINGLELINE| DT_CENTER | DT_VCENTER);

           EndPaint(hwnd,&ps);

           break;

 

      case WM_DESTROY:

           PostQuitMessage(0);   // 0为消息WM_QUIT的wParam参数

           break;

     default:

         returnDefWindowProc(hwnd, message, wParam, lParam);

}

return 0;

}

注:改变的地方如红色标示的地方. break退出该层循环或switch ,而return退出函数


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值