yidabu 2007-5-10 14:31
D语言GUI入门4 GetMessage和PeekMessage消息循环
D语言GUI入门4 GetMessage和PeekMessage消息循环知识若不分享 实在没有意义 http://www.d-programming-language-china.org 20070509点击下面网址查看原文:http://www.d-programming-language-china.org by: 孙鑫 D语言论坛 http://www.d-programming-language-china.org 增加D语言相关说明tag:windows api编程,api函数详解,getMessage消息GetMessage消息循环 在创建窗口、显示窗口、更新窗口后,我们需要编写一个消息循环,不断地从消息队列中取出消息,并进行响应。要从消息队列中取出消息,我们需要调用GetMessage()函数,该函数的原型声明如下: http://msdn2.microsoft.com/en-us/library/ms644936.aspx QUOTE: BOOL GetMessage( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax ); 参数lpMsg指向一个消息(MSG)结构体,GetMessage从线程的消息队列中取出的消息信息将保存在该结构体对象中。 参数hWnd指定接收属于哪一个窗口的消息。通常我们将其设置为NULL,用于接收属于调用线程的所有窗口的窗口消息。 参数wMsgFilterMin指定要获取的消息的最小值,通常设置为0。 参数wMsgFilterMax指定要获取的消息的最大值。如果wMsgFilterMin和wMsgFilter Max都设置为0,则接收所有消息。 GetMessage函数接收到除WM_QUIT外的消息均返回非零值。对于WM_QUIT消息,该函数返回零。如果出现了错误,该函数返回-1,例如,当参数hWnd是无效的窗口句柄或lpMsg是无效的指针时。( 本文出处: http://www.d-programming-language-china.org ) 通常我们编写的消息循环代码如下: QUOTE: MSG msg; while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } 关于MSG结构体,参考MSDN: http://msdn2.microsoft.com/en-us/library/ms644958.aspx 原型: QUOTE: typedef struct { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG, *PMSG; hwnd Handle to the window whose window procedure receives the message. hwnd is NULL when the message is a thread message. message Specifies the message identifier. Applications can only use the low word; the high word is reserved by the system. wParam Specifies additional information about the message. The exact meaning depends on the value of the message member. lParam Specifies additional information about the message. The exact meaning depends on the value of the message member. time Specifies the time at which the message was posted. pt Specifies the cursor position, in screen coordinates, when the message was posted. 前面已经介绍了,GetMessage函数只有在接收到WM_QUIT消息时,才返回0。此时while语句判断的条件为假,循环退出,程序才有可能结束运行。在没有接收到WM_QUIT消息时,Windows应用程序就通过这个while循环来保证程序始终处于运行状态。 TranslateMessage函数用于将虚拟键消息转换为字符消息。字符消息被投递到调用线程的消息队列中,当下一次调用GetMessage函数时被取出。当我们敲击键盘上的某个字符键时,系统将产生WM_KEYDOWN和WM_KEYUP消息。这两个消息的附加参数(wParam和lParam)包含的是虚拟键代码和扫描码等信息,而我们在程序中往往需要得到某个字符的ASCII码,TranslateMessage这个函数就可以将WM_KEYDOWN和WM_ KEYUP消息的组合转换为一条WM_CHAR消息(该消息的wParam附加参数包含了字符的ASCII码),并将转换后的新消息投递到调用线程的消息队列中。注意,TranslateMessage函数并不会修改原有的消息,它只是产生新的消息并投递到消息队列中。( 本文出处: http://www.d-programming-language-china.org ) DispatchMessage函数分派一个消息到窗口过程,由窗口过程函数对消息进行处理。DispachMessage实际上是将消息回传给操作系统,由操作系统调用窗口过程函数对消息进行处理(响应)。 Windows应用程序的消息处理机制: (1)操作系统接收到应用程序的窗口消息,将消息投递到该应用程序的消息队列中。 (2)应用程序在消息循环中调用GetMessage函数从消息队列中取出一条一条的消息。取出消息后,应用程序可以对消息进行一些预处理,例如,放弃对某些消息的响应,或者调用TranslateMessage产生新的消息。 (3)应用程序调用DispatchMessage,将消息回传给操作系统。消息是由MSG结构体对象来表示的,其中就包含了接收消息的窗口的句柄。因此,DispatchMessage函数总能进行正确的传递。( 本文出处: http://www.d-programming-language-china.org ) (4)系统利用WNDCLASS结构体的lpfnWndProc成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理(即“系统给应用程序发送了消息”)。 以上就是Windows应用程序的消息处理过程。PeekMessage消息函数,SendMessage消息函数,PostMessage消息函数 从消息队列中获取消息还可以调用PeekMessage函数,该函数的原型声明如下所示: QUOTE: BOOL PeekMessage( LPMSG lpMsg, // message information HWND hWnd, // handle to window UINT wMsgFilterMin, // first message UINT wMsgFilterMax, // last message UINT wRemoveMsg // removal options ); 前4个参数和GetMessage函数的4个参数的作用相同。最后1个参数指定消息获取的方式,如果设为PM_NOREMOVE,那么消息将不会从消息队列中被移除;如果设为PM_REMOVE,那么消息将从消息队列中被移除(与GetMessage函数的行为一致)。关于PeekMessage函数的更多信息,请参见MSDN。 发送消息可以使用SendMessage和PostMessage函数。SendMessage将消息直接发送给窗口,并调用该窗口的窗口过程进行处理。在窗口过程对消息处理完毕后,该函数才返回(SendMessage发送的消息为不进队消息)。PostMessage函数将消息放入与创建窗口的线程相关联的消息队列后立即返回。除了这两个函数外,还有一个PostThreadMessage函数,用于向线程发送消息,对于线程消息,MSG结构体中的hwnd成员为NULL。 D语言论坛职http://www.d-programming-language-china.org 按: 到现在为止全部D语言代码如下:( 本文出处: http://www.d-programming-language-china.org ) [Copy to clipboard] [ - ]CODE: import std.utf; import win32.api; extern(C) void gc_init(); extern(C) void gc_term(); extern(C) void _minit(); extern(C) void _moduleCtor(); extern(C) void _moduleDtor(); extern(C) void _moduleUnitTests(); const char[] ClassName = "http://www.d-programming-language-china.org"; extern(Windows) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow) { int result; gc_init(); _minit(); try { _moduleCtor(); _moduleUnitTests(); result = myWinMain(hInstance,hPrevInstance,lpCmdLine,nCmdShow); _moduleDtor(); } catch(Exception e) { printf("catch %.*s\n",e.msg); result = 0; } finally { } gc_term(); return result; } int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow) { WNDCLASSEX wc; MSG msg; HWND hWnd; wc.cbSize = WNDCLASSEX.sizeof; wc.style = CS_HREDRAW | CS_VREDRAW ; wc.lpfnWndProc = &WindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; //bbs.d-programming-language-china.org注: D语言标准库的windows.d主要服务于ascii字符集的windows api,IDI_APPLICATION被定义为CHAR*,所以这里要转换成wchar* //如果IDI_APPLICATION来定义是CHAR,就可以用toUTF16z来转换 wc.hIcon = LoadIcon (cast(HINSTANCE)null,cast(wchar*)IDI_APPLICATION); wc.hIcon = LoadIcon (hInstance,toUTF16z("IDI_MYICON")); wc.hCursor = LoadCursor(cast(HINSTANCE)null,cast(wchar*)IDC_ARROW); wc.hbrBackground = cast(HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = null; //转换类名到以0结尾的宽字符集 wc.lpszClassName = toUTF16z(ClassName); wc.hIconSm = LoadIcon(hInstance,std.utf.toUTF16z("IDI_MYICON")); if ( !RegisterClassEx (&wc) ) return 0; hWnd = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_WINDOWEDGE | WS_EX_TOPMOST, toUTF16z(ClassName), std.utf.toUTF16z("我的第一个程序"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT,800,600, HWND_DESKTOP, cast(HMENU) null, hInstance, null); if (hWnd == null) { MessageBoxEx(null,toUTF16z("欢迎来到 http://bbs.d-programming-language-china.org "),toUTF16z("error"),MB_ICONERROR | MB_HELP,0); return -2; } //显示和更新窗体 ShowWindow(hWnd, SW_SHOWNORMAL); UpdateWindow(hWnd); while (GetMessageW(&msg, cast(HWND)null, 0, 0)) { TranslateMessage(&msg); DispatchMessageW(&msg); } return msg.wParam; } extern(Windows) LRESULT WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: { PostQuitMessage(0); break; } default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } ( lastupdate:20070510 最新文章请访问http://www.d-programming-language-china.org )关于一大步成功社区:yidabu提倡在交流中学习,在分享中提高收集感兴趣的知识,写下心得,通过网络与别人一起分享理解一点就实践一步,收获什么就分享什么,成功就是这样一点点一步步累积起来的网络只是一个工具,只有自己身心提高才是实实在在的。d-programming-language-china.org为大家提供一个学习交流各种知识的平台