窗口破坏过程与Windows消息循环

来源:互联网 发布:国际淘宝什么意思 编辑:程序博客网 时间:2024/05/18 14:14

 从用户单击关闭按钮(标题栏最右边)或者用鼠标或鍵盘选择系统菜单的“关闭”选项,直到窗口消失,应用程序结束。这期间到底发生了什么呢?这曾经是我百思不得其解的问题,我想也会有很多人和我一样会碰到这个问题。所以我要把我的一些学习心得写出来,与大家共享:
1、首先会产生一个WM_SYSCOMMAND消息,如果程序员没有对此消息进行拦截,则由缺省的窗口函数DefWindowProc进行处理,如果表达式(LOWORD(wParam)&0xFFF0)==SC_CLOSE 成立,DefWindowProc发出一个WM_CLOSE消息。
2、同样,如果程序员没有对WM_CLOSE消息进行拦截,则还是由DefWindowProc进行处理,这次,她只简单的调用DestroyWindow函数,DestroyWindow先把窗口破坏掉,使用户看不到窗口。但是窗口破坏后,应用程序并没有结束,于是DestroyWindow再接再励,送出了一个WM_DESTROY消息。
3、这一次,WM_DESTROY被载获了,通常是会有这样的句子:
case WM_DESTROY:
PostQuitMessage(0);
...
这里PostQuitMessage函数很简单的发送一个WM_QUIT消息来响应WM_DESTROY
4、WM_QUIT消息非常特殊,她使GetMessage函数返回0,从而结束了消息循环,
应用程序从此结束。
下面我给出完整的证明程序,请大家一试:

 

  1. #include <Windows.h> 
  2. #include <TCHAR.h> 
  3. LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); 
  4. int WINAPI WinMain(HINSTANCE hInstance, 
  5. HINSTANCE hPrevInst, 
  6. LPSTR lpszCmdLine, 
  7. int nCmdShow) 
  8. HWND hwnd; 
  9. MSG Msg; 
  10. WNDCLASS wndclass; 
  11. char lpszClassName[]="窗口"
  12. char lpszTitle[]="窗口示例"
  13. wndclass.style=CS_HREDRAW | CS_VREDRAW; 
  14. wndclass.lpfnWndProc =WndProc; 
  15. wndclass.cbWndExtra=0; 
  16. wndclass.cbClsExtra =0; 
  17. wndclass.hInstance=hInstance; 
  18. wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); 
  19. wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); 
  20. wndclass.hbrBackground = (HBRUSH)(GetStockObject(WHITE_BRUSH)); 
  21. wndclass.lpszMenuName=NULL; 
  22. wndclass.lpszClassName=lpszClassName; 
  23. if(!RegisterClass(&wndclass)) 
  24. MessageBeep(0); 
  25. return FALSE; 
  26. hwnd=CreateWindow(lpszClassName, 
  27. lpszTitle, 
  28. WS_OVERLAPPEDWINDOW, 
  29. CW_USEDEFAULT, 
  30. CW_USEDEFAULT, 
  31. CW_USEDEFAULT, 
  32. CW_USEDEFAULT, 
  33. NULL, 
  34. NULL, 
  35. hInstance, 
  36. NULL); 
  37. ShowWindow(hwnd,nCmdShow); 
  38. UpdateWindow(hwnd); 
  39. while(1) 
  40. GetMessage(&Msg,NULL,0,0); 
  41. if(Msg.message==WM_QUIT) 
  42. MessageBox(NULL,_T("收到WM_QUIT,即将跳出消息循环"),_T("注意了"),MB_OK); 
  43. break
  44. TranslateMessage(&Msg); 
  45. DispatchMessage(&Msg); 
  46. MessageBox(NULL,_T("已经跳出消息循环,应用程序即将结束!"),_T("注意了"),MB_OK); 
  47. return Msg.wParam; 
  48. LRESULT CALLBACK WndProc( 
  49. HWND hwnd, 
  50. UINT message, 
  51. WPARAM wParam, 
  52. LPARAM lParam) 
  53. switch(message) 
  54. case WM_CLOSE: 
  55. MessageBox(NULL,_T("收到WM_CLOSE消息,即将调用 DestroyWindow(hwnd);"),_T("注意了"),MB_OK); 
  56. DestroyWindow(hwnd); 
  57. break
  58. case WM_DESTROY: 
  59. MessageBox(NULL,_T("已调用过DestroyWindow(hwnd),看不到窗口了吧;"),_T("注意了"),MB_OK); 
  60. MessageBox(NULL,_T("以下处理WM_DESTROY"),_T("注意了"),MB_OK); 
  61. PostQuitMessage(0); 
  62. break
  63. case WM_SYSCOMMAND: 
  64. if((LOWORD(wParam)&0xFFF0)==SC_CLOSE) 
  65. MessageBox(NULL,_T("你关闭了窗口,即将发送WM_CLOSE消息!"),_T("注意了"),MB_OK); 
  66. SendMessage(hwnd,WM_CLOSE,0,0); 
  67. //不要添加 break,否则不能响应其它WM_SYSCOMMAND消息 
  68. default
  69. return DefWindowProc(hwnd,message,wParam,lParam); 
  70. return(0); 
  71. -------------------------------------------------------------------------------- 
  72. 窗口破坏过程与Windows消息循环的补充,增加了对WM_NCDESTROY的处理 
  73. /** 
  74. * File Name : MessageTest.cpp 
  75. * Version : 1.1 
  76. * Project Name : MessageTest 
  77. * Project Type : Win32 
  78. * Author : netcoder 
  79. * Addition : 此版本增加了对WM_NCDESTROY的处理, 感谢 lily311 的补充 
  80. */ 
  81. #include <windows.h> 
  82. #include <tchar.h> 
  83. LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); 
  84. int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInst,LPSTR lpszCmdLine,int nCmdShow) 
  85. HWND hwnd; 
  86. MSG Msg; 
  87. WNDCLASS wndclass; 
  88. char lpszClassName[]="窗口"
  89. char lpszTitle[]="窗口示例"
  90. wndclass.style=CS_HREDRAW | CS_VREDRAW; 
  91. wndclass.lpfnWndProc =WndProc; 
  92. wndclass.cbWndExtra=0; 
  93. wndclass.cbClsExtra =0; 
  94. wndclass.hInstance=hInstance; 
  95. wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); 
  96. wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); 
  97. wndclass.hbrBackground = (HBRUSH)(GetStockObject(WHITE_BRUSH)); 
  98. wndclass.lpszMenuName=NULL; 
  99. wndclass.lpszClassName=lpszClassName; 
  100. if(!RegisterClass(&wndclass)) 
  101. MessageBeep(0); 
  102. return FALSE; 
  103. hwnd=CreateWindow(lpszClassName, 
  104. lpszTitle, 
  105. WS_OVERLAPPEDWINDOW, 
  106. CW_USEDEFAULT, 
  107. CW_USEDEFAULT, 
  108. CW_USEDEFAULT, 
  109. CW_USEDEFAULT, 
  110. NULL, 
  111. NULL, 
  112. hInstance, 
  113. NULL); 
  114. ShowWindow(hwnd,nCmdShow); 
  115. UpdateWindow(hwnd); 
  116. while(1) 
  117. GetMessage(&Msg,NULL,0,0); 
  118. if(Msg.message==WM_QUIT) 
  119. MessageBox(NULL,_T("收到WM_QUIT,即将跳出消息循环"),_T("注意了"),MB_OK); 
  120. break
  121. TranslateMessage(&Msg); 
  122. DispatchMessage(&Msg); 
  123. MessageBox(NULL,_T("已经跳出消息循环,应用程序即将结束!"),_T("注意了"),MB_OK); 
  124. return Msg.wParam; 
  125. LRESULT CALLBACK WndProc( 
  126. HWND hwnd, 
  127. UINT message, 
  128. WPARAM wParam, 
  129. LPARAM lParam) 
  130. switch(message) 
  131. case WM_CLOSE: 
  132. MessageBox(NULL,_T("收到WM_CLOSE消息,即将调用 DestroyWindow(hwnd);"),_T("注意了"),MB_OK); 
  133. DestroyWindow(hwnd); 
  134. break
  135. case WM_DESTROY: 
  136. MessageBox(NULL,_T("已收到WM_DESTROY,看不到窗口了吧!"),_T("注意了"),MB_OK); 
  137. break
  138. case WM_NCDESTROY: 
  139. MessageBox(NULL,_T("收到WM_NCDESTROY!"),_T("注意了"),MB_OK); 
  140. PostQuitMessage(0); 
  141. break
  142. case WM_SYSCOMMAND: 
  143. if((LOWORD(wParam)&0xFFF0)==SC_CLOSE) 
  144. MessageBox(NULL,_T("你关闭了窗口,即将发送WM_CLOSE消息!"),_T("注意了"),MB_OK); 
  145. SendMessage(hwnd,WM_CLOSE,0,0); 
  146. //不要添加 break,否则不能响应其它WM_SYSCOMMAND消息 
  147. default
  148. return DefWindowProc(hwnd,message,wParam,lParam); 
  149. return(0);