1、 继注册窗体类、创建窗体往下讲。 我们用Visual Studio创建一个win32项目上会自动生成一个消息处理函数。如下: [cpp] view plaincopyprint?// // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回
2、// // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM
3、ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意绘图代码... End
4、Paint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND- 处理应用程序菜单 //
5、WM_PAINT- 绘制主窗口 // WM_DESTROY- 发送退出消息并返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam);
6、 // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPa
7、int(hWnd, &ps); // TODO: 在此添加任意绘图代码... EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }先看概念: 1)基于消息的事件驱动机制 c++中的Windows应用是基于消息的事件驱动的,它不是由事件的顺序来控制,而是由事件的发生来控制,而事件的
8、发生是随机的,不确定的,并没有预定的顺序,这样就允许程序的用户用各种合理的顺序来安排程序的流程。事件驱动围绕这消息的产生与处理展开,一条消息是关于发生的事件的消息,事件驱动是靠消息循环机制来实现的。因此,也有这种说法:c++是消息驱动的,Java和C#是事件驱动的。但其本质的一样的,应为消息是一种报告有关事件发生的通知。 Windows应用程序的消息来源有以下四种: (1)输入消息:包括键盘和鼠标的输入。者一类消息先放在系统消息队列中,然后由Windows将他们送入应用程序的消息队列中,有应用程序开处理消息。 (2)控制消息:用来与windows的控制对象(如列表框、按钮、复
9、选框等)进行双向通信。这类消息一般不经过应用程序消息队列,而是直接发到控制对象上去。 (3)系统消息:对程序化的事件和系统时钟中断等做出反应。 (4)用户消息:程序员自己定义并在应用程序中主动发出的,一般由应用程序的某一部分内部处理。 2)MSG结构类型 在Windows应用中,为了实现消息机制,定义了新的结构类型MSG,表示消息类型,如下: typedef struct { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt;
10、 } MSG,*PMSG; 该结构包含六个域,其中: hWnd为接受消息的窗口句柄。 message是特定的消息代码。它用一个32为整形值来表示不同的消息,这些消息在windows.h文件中用常量宏名进行定义。 wParam和lParam是与消息连在一起的两个32为福建消息。 time和pt分别表示消息投递到消息队列中的时间和鼠标的当前位置。 3)消息循环 什么是消息队列?Windows是一个面向对象的系统,即系统内的所有信息交换都是靠传送和接受消息进行的。消息队列”是在消息的传输过程中保存消息的容器。消息队列管理器在将消息从它的源中继到它的目标时
11、充当中间人。队列的主要目的是提供路由并保证消息的传递;如果发送消息时接收者不可用,消息队列会保留消息,直到可以成功地传递它。 Windows由两种消息队列,一种是整个系统的消息队列,另一种是为每个线程提供的线程消息队列。 队列被看一个循环缓冲区,当一个程序装入内存后,Windows操作系统为每个线程分配一个消息队列。每个程序必须通过向消息队列发送消息,有系统决定是否马上响应这些请求的消息,并通过回调窗口函数来完成窗口中的某些功能。 在消息循环中,首先,调用GetMessage函数,从消息队列中获取一个消息,并把它放在msg这个消息结构变量中。GetMessage函数的原型如下
12、 BOOL GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax) 参数: lpMsg:指向MSG结构的指针,该结构从线程的消息队列里接收消息信息。 hWnd:取得其消息的窗口的句柄。当其值取NULL时,GetMessage为任何属于调用线程的窗口检索消息,线程消息通过PostThreadMessage寄送给调用线程。 wMsgFilterMin:指定被检索的最小消息值的整数。 wMsgFilterMax:指定被检索的最大消息值的整数。 返回值:如果函数取得WM_
13、QUIT之外的其他消息,返回非零值。如果函数取得WM_QUIT消息,返回值是零。如果出现了错误,返回值是-1。例如,当hWnd是无效的窗口句柄或lpMsg是无效的指针时。 在循环体内,对获取的消息调用TranslateAccelerator函数先进行处理,该函数的功能是处理菜单中的快捷键消息。Win32框架自动生成的代码,它带有一些基本处理,如TranslateAccelerator函数,应为一般的函数都要用到菜单和快件键。 再来看代码: (1)首先是对于LRESULT的理解 LRESULT是一个数据类型: 指的是从窗口程序或者回调函数返回的32位值 在winnt.h中typedef long LONG; 在windef.h中typedef LONG LRESULT; 所以LRESULT就是long,也就是长整形 之所以取名类LRESULT,L=>long 。 result表示结果,说明这个函数的返回值是某个结果。 (2)对于CALLBACK的理解: #define CALLBACK __stdcall 由此可以看出这儿的CALLBACK指的函数调用规范。 可以看出该函数的作用就是通过catch来对不同的消息进行相应的处理






