原文链接:http://www.krnl.info/thread-1844-1-1.html

这是我看到的对windows 进程退出,对WM_QUIT消息讲的最详细的了。

 首先感谢 gz81 对牛刀 ○六八 讲教程的错误提出。

  经管理员确认,牛刀竟然也有送经验送分的权力,哈哈。
  可要注意喽,牛刀不但能送正分,还能送负分哟,呵呵。 9 e( o9 \/ G- p9 D- d9 |
$ J; @+ Y/ h4 j/ R1 j' J
  所以说,请大家以后尽量不要打着牛刀的旗号要分要经验,估计送刀如果送负分的话,其他人也不会送正分给你吧,哼哼!!!

  说句玩笑话,不过既然有这权力,牛刀就要用,以后对牛刀教材中的错误,进行提出并通过牛刀确认的话,牛刀一律给分,当然如下几种情况不给分(甚至可能给负分,哼哼)。
·恶意灌水(注:这一点牛刀不容易出现,牛刀的教程还能够受到绝大多数朋友们的尊重,到目前为止,恶意灌水的寥寥无几。 # v# k/ ^1 Y; G  z
·别字(牛刀的错笔字不属送分范围,当然可以提出,当然其实有时候,牛刀自己都发现笔字,说实话,懒得改,呵呵,大家顺着读吧,呵呵。注:牛刀用的是五笔,属于字型码,所以有些东西真容易打错的,例如有些地方字典打成“字曲”,这些都属于手误,不属送分范围) ! ]* \. u) \, o: Q8 ^; j4 ]
·语句不通(有些语句就是不通,或者说有意不通,也就是说,语法上的东东,不属于送分范围) ! m( H% f( a' t2 O8 @" p+ k
·文字偏差(有些属于前期论坛的代码问题,如果“[i]”,在以前的论坛上就都是斜体,不过牛刀不改了,为什么,因为不改你就不能用“复制/粘贴”大法,呵呵,牛刀的教材是实践教材,所以对于一切文字上的偏差,也不在送分范围)
·未经确认(其他情况,牛刀感觉不值得送分的,牛刀也不会送分,当然,直接要分的,牛刀不但不会送分甚至可能扣分,所以切忌要分)。 5 m# ^- i9 B/ p! s5 ]) L9 }) L( g4 y
8 Y* G' G, c6 ], t6 Q" I: r' C
  说实话,能够发现牛刀教程中的错误,证明你上机了,实践了,否则,是绝对不可能发现一些质的错误的。 * o4 p1 x4 e, h* o

  对了,这位朋友提出的是 牛刀使用了一个系统没有的消息 WM_EXIT 这个消息系统没有,后进管理员确认,牛刀也确认没有,于是,管理员经过查找资料,提出了一个问题 WM_QUIT 是不是属于消息。

  有些资料上对此不认为是一个消息,而这个功能就是设定某些标志位,于是,牛刀就去做了一些程序——

  1. #include <windows.h>
  2. LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
  3. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,7 f  w9 b% D' ~0 }
  4. PSTR szCmdLine, int iCmdShow)) I: F; g4 N5 k1 h/ [
  5. {
  6. static TCHAR szAppName[] = TEXT ("TestWin") ;: e4 [. C- [" n* Q( t% X% @  u
  7. HWND        hwnd ;
  8. MSG        msg ;
  9. WNDCLASS        wndclass ;. _4 W2 }5 C  h6 a
  10. wndclass.style                  = CS_HREDRAW | CS_VREDRAW ;
  11. wndclass.lpfnWndProc  = WndProc ;* c, B% D9 e- c' s4 j9 b
  12. wndclass.cbClsExtra          = 0 ;
  13. wndclass.cbWndExtra          = 0 ;
  14. wndclass.hInstance          = hInstance ;
  15. wndclass.hIcon                  = LoadIcon (NULL, IDI_APPLICATION) ;
  16. wndclass.hCursor          = LoadCursor (NULL, IDC_ARROW) ;& z7 m6 x$ j, S, p
  17. wndclass.hbrBackground        = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  18. wndclass.lpszMenuName        = NULL;' r% x* K3 Q+ K/ H+ T  D
  19. wndclass.lpszClassName        = szAppName ;3 p, S5 _9 |5 `! w
  20. if (!RegisterClass (&wndclass))
  21. {
  22. MessageBox (        NULL, TEXT ("This program requires Windows NT!"),
  23. szAppName, MB_ICONERROR) ;
  24. return 0 ;7 C4 z, Z. A" v. d
  25. }2 [9 s; x9 Y6 u( Z3 |1 _: ?' T6 S
  26. hwnd = CreateWindow( szAppName,TEXT ("牛刀WM_QUIT测试"),WS_OVERLAPPEDWINDOW,& O2 U+ G% S3 ^& s& g4 f
  27. CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,% o( G3 i1 I! z
  28. NULL,NULL,hInstance,NULL) ;
  29. ' U0 Y/ g/ }5 C3 H- X# C
  30. ShowWindow (hwnd, iCmdShow) ;  L) [6 W3 N: P8 a: M' s4 C% a
  31. UpdateWindow (hwnd) ;. Z; t# F2 V% k; |# q
  32. while (GetMessage (&msg, NULL, 0, 0))( }% ~% f( a. J! L
  33. {7 T3 r/ h% Q2 x; n2 Q
  34. TranslateMessage (&msg) ;
  35. DispatchMessage (&msg) ;+ j1 D0 Y3 g7 Q
  36. }/ U% ^3 T! S/ O- V2 t
  37. return msg.wParam ;
  38. }
  39. # n1 W- L; E8 E! X
  40. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  41. {* c# v; [% \. v6 R" z. b: i" @( z
  42. switch (message)" R7 h4 B# p# h* [& m: Y
  43. {
  44. case        WM_DESTROY:
  45. PostQuitMessage (0) ;
  46. return 0 ;
  47. }
  48. return DefWindowProc (hwnd, message, wParam, lParam) ;  c4 R, s) ^3 \5 L
  49. }

复制代码

上面的程序,我们可以运行了,并且只在 WM_DESTROY 发送了 WM_QUIT 消息,所以说,如果这一个消息不响应的话,那么我们的程序就结束不了,以前我们曾经说过,没有 PostQuitMessage 消息的话,我们的程序是结束不了的。(什么?你的程序结束了?你打开任务管理器看看,真的结束了吗?只不过是窗口被销毁了罢了,呵呵,所以说,当 WM_DESTROY 消息响应时,我们的程序窗口已经被销毁。) . l# _( x  _' D  l6 W6 @  \
  当然 WM_CLOSE 消息被响应时,窗口还没有销毁,当然,那个消息中,是可以执行 DestroyWindow 函数去销毁窗口的,而如果不执行的话,那么窗口就销毁不了,也就是说,我们如果响应一个空消息的话——

  1. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)" ^  I9 o: y. Y! C( a3 K7 ~( B
  2. {0 j+ U2 t0 p  ?9 C
  3. switch (message)
  4. {2 R- _( k% l# ?% M/ ~  l
  5. case WM_CLOSE:
  6. return 0;
  7. default:/ _* h* {+ g0 q9 \# R& j/ m, U
  8. return DefWindowProc (hwnd, message, wParam, lParam) ;
  9. }
  10. }

复制代码

我们的窗口是关不掉的,所以说,系统默认函数在响应 WM_CLOSE 时,是提供销毁窗口的函数的,然而,在销毁窗口时,却没有提供发送 WM_QUIT 消息的函数,所以我们的消息处理中,至少响应如下消息:

  1. ! J) H3 v' _" ~; z3 C
  2. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)" G5 G/ F; C: P4 a( }" j
  3. {, r) l1 X  @9 U& x) {. p
  4. switch (message)
  5. {: U2 W, E" u% x2 L- T/ g
  6. case WM_DESTROY:
  7. PostQuitMessage (0) ;
  8. return 0 ;
  9. default:/ [3 b( s4 ^7 G7 L# w& M
  10. return DefWindowProc (hwnd, message, wParam, lParam);
  11. }1 K) K( H0 B# @% L; K' ~, r4 L8 j
  12. }! x& d6 g7 D- [7 l* r  J

复制代码

那好,一个问题,我们的函数能够响应WM_QUIT 消息吗?如果按照某些材料上说的,我们就不能响应这个消息了,去做一个程序试试——

  1. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3. switch (message)
  4. {
  5. case WM_DESTROY:
  6. PostQuitMessage (0) ;9 r  x2 p: Z  k5 V) ~
  7. break;
  8. case WM_QUIT:
  9. MessageBox(hwnd,"消息测试","WM_QUIT消息测试",MB_OK);
  10. break;
  11. }- k  n# n, B5 b7 X0 N) ?
  12. return DefWindowProc (hwnd, message, wParam, lParam);
  13. }

复制代码

果然不假,上面的一些理论得到了证实,可是牛刀不服,既然没有用,那么要这个消息干嘛?牛刀不服,换了一个地方打劫——

  1. ) p3 s2 X" v! A! j
  2. while (GetMessage (&msg, NULL, 0, 0))
  3. {
  4. TranslateMessage (&msg) ;, g( R! t0 I5 G- N
  5. DispatchMessage (&msg) ;
  6. }* }1 ]. p+ E" j' X4 R4 J. |
  7. if(WM_QUIT==msg.message)MessageBox(NULL,"消息测试","WM_QUIT消息测试",MB_OK);

复制代码

这一次,这个消息被我们打劫到了,并且顺利地执行,那么为什么我们在 WndProc 函数中,得不到消息呢?我们来看看我们消息的执行过程)——

  1. - n9 \, X- R% g% I6 r8 E
  2. while (GetMessage (&msg, NULL, 0, 0))  //得到消息,请注意,如果消息是 WM_QUIT,那么这个函数就返回 0 ,下面的程序就执行不到了。8 L0 q& U4 x- L* i
  3. {1 ?% k, y- t2 ^. T& c2 B, m) o
  4. TranslateMessage (&msg) ;  //翻译程序,翻译消息# b  u$ h. U/ d) A
  5. DispatchMessage (&msg) ;   //执行消息,是这一句将消息队列中的消息传递给 WndProc 函数,所以一旦有了 WM_QUIT 消息,这一句就执行不到,于是,我们的消息在 WndProc 函数中就捕捉不到了。
  6. }" f5 N9 C6 q2 u1 q; o% o

复制代码

明白了上面的道理,那么我们如果想在消息处理函数中捕捉到这个消息,那么我们怎么办呢?可以改一下下程序嘛,呵呵,看——

  1. 6 O9 |4 |+ ^3 y
  2. int MsgRet;. i+ Q2 b" a3 i0 _/ v; y1 w
  3. do4 g6 o2 P  F' \+ u
  4. {        MsgRet=GetMessage (&msg, NULL, 0, 0);' V; s9 b2 n9 h' P# O/ j( B
  5. TranslateMessage (&msg) ;! U! }$ k* ?* L& v" p2 H
  6. DispatchMessage (&msg) ;
  7. }while(MsgRet);        //我们改了成 do-while 结构,这样上面的消息就每条消息都有机会送到 WinProc 函数喽

复制代码

程序理论讲完了,很可惜的是,我们的程序, WndProc 中的 WM_QUIT 消息仍旧没有被执行,这是什么原因??? : i* O2 x8 _% C; U* q

  很显然,肯定被系统的 DispatchMessage (&msg) ; 函数给过滤掉了,不知牛刀考虑的有没有道理,大家可以各抒己见。
: P, k7 E2 Z: T
  结论:WM_QUIT 是一个消息,但这个消息不能在 WndProc 消息函数中被捕获,如果要响应,也只能在消息循环地位置拦截,但我们一般不需要这样做。

原文:"注意到WM_QUIT消息让消息循环终止归根结底是让GetMessage返回为0,而GetMessage函数是从消息对列里取一条消息,然后再返回,只能当消息为WM_QUIT时才返回0结束消息循环。再仔细看一下SendMessage的注释发现,SendMessage直接发送到窗口,并调用窗口处理程序,完成消息响应,即SendMessage 根本就没有将消息发到消息对列中,因此GetMessage无法从消息对列中收到WM_QUIT的消息。而PostMessage却直接发送消息到消息对列中,然后立即返回,这一点点的区别就解决了我们上面的问题。陆解了这一点,就不难理解上面注释中说的为什么不让直接使用PostMessage来发送WM_QUIT消息来终止程序了。"

 GetMessage 是收到了 WM_QUIT 消息的,但牛刀的结论是:被 DispatchMessage 函数给过滤掉了。( F' P8 F" m8 i: r
  也就是说,WM_QUIT 消息发送给窗口是无效的,所以使用 SendMessage 向窗口发送 WM_QUIT 消息则无效。6 c. T# _+ [/ ]0 Q# q

  为了验证这个想法,牛刀去做了一个测试——

  1. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {" L. T, v5 @. A% j. w& X
  3. switch (message). K% }" W. Z5 T" `) q
  4. {
  5. case WM_LBUTTONDOWN:6 O* b  Z, C% w0 D
  6. SendMessage(hwnd,WM_QUIT,0,0);# c! }$ H% g" f% j  ^5 B. g
  7. break;
  8. case WM_DESTROY:
  9. PostQuitMessage (0) ;
  10. break;
  11. case WM_QUIT:
  12. MessageBox(hwnd,"消息测试","WM_QUIT消息测试",MB_OK);/ r6 x* ]" h; E+ ^$ W! l6 g
  13. break;
  14. }
  15. return DefWindowProc (hwnd, message, wParam, lParam);' \4 s! Z4 Y; w6 A5 Q! o0 j
  16. }

复制代码

8 T  H" E- @7 y' @. W
2 C& E+ D5 y3 ]# Q( {( ]- {
  牛刀惊奇地发现,牛刀上面的 SendMessage 发送消息无效的结论是不正确的。窗口函数的确响应的 WM_QUIT 消息,但由于这个消息没有被 GetMessage 捕获,所以程序根本没有退出,也就是说,使用 SendMessage 发送这个消息时,是不经过消息队列的,也就是说是不经过——

  1. while(GetMessage (&msg, NULL, 0, 0))7 }5 G% t0 i1 r( l# _
  2. {
  3. TranslateMessage (&msg) ;# B( y/ i1 I. s/ u# Z
  4. DispatchMessage (&msg) ;5 ?+ N0 O9 a/ C8 R6 E6 [5 q
  5. }

复制代码

4 M" b  T, L% q$ @" @' q* N" z

  这个消息循环的,所以不能使得 GetMessage 返回 0 值。

  于是,牛刀又去测试了 PostMessage 消息: : w  C; B2 x% s" g7 @

  1. % K4 _+ q3 ?7 T/ ?4 t6 \3 w! Q2 f
  2. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  3. {
  4. switch (message)# b' n& m, Z" e( [' H
  5. {5 h; Y3 f3 J( }" B% e
  6. case WM_LBUTTONDOWN:
  7. PostMessage(hwnd,WM_QUIT,0,0);
  8. break;
  9. case WM_DESTROY:5 R2 w- b2 k- d1 {/ t
  10. PostQuitMessage (0) ;  h& H/ c' C) q3 C; U9 b
  11. break;
  12. case WM_QUIT:) B* v4 v1 P1 V) h! Z1 C4 u$ e
  13. MessageBox(hwnd,"消息测试","WM_QUIT消息测试",MB_OK);
  14. break;
  15. }
  16. return DefWindowProc (hwnd, message, wParam, lParam);& C$ |  W8 P2 Q; R/ @0 S# s$ r. t" Q
  17. }

复制代码

& q% Z! H: y5 d

  由于消息这次是发进了消息队列,所以我们在 WndProc 函数中就又不能响应消息了。 8 y. Y) Q( r2 j* y  G' g0 N( U
. L2 A, \$ ~% \- u
  综上所述:
·WM_QUIT 的确是一条消息,并且这个消息是可以发送到消息队列中(使用PostMessage),亦可以发送到窗口(使用SendMessage),但是,我们是不能通过消息队列将消息发送到窗口中的,因为我们的队列中的消息被 DispatchMessage 给过滤掉了。 2 O, ]5 P9 x3 I! z# q" |

  通过上面的一些讨论与测试,我们基本可以估计出 DispatchMessage 的函数应该是这样或近似这样的程序——

  1. void DispatchMessage(MSG msg)
  2. {
  3. if(WM_QUIT!=msg.message)
  4. {
  5. SendMessage(msg.hwnd,msg.message,msg.wParam,msg.lParam);
  6. }
  7. }* i0 ]0 p# d  N3 m7 Z6 J

复制代码

, @) s/ s, \( q! j
  附:为什么不建议直接用 PostMessage 来发 WM_QIUT 消息的牛刀解释。 " q6 a/ x0 @  N+ U; A/ _

  首先一点的就是,可以使用 PostMessage 来发送 WM_QUIT 消息,并且一点残留都没有(注:任务管理器中一点残余都没有)。 * J( d" o, {: b% `8 V1 W+ ?
  当然,窗口也没有了,程序结束了,但会有一个问题,那就是,我们的窗口并没有被销毁,因为没有来得及响应 WM_DESTROY 消息,为了验证,牛刀做了以下的程序——

  1. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3. switch (message)7 A- O* z* B- H* T0 ~
  4. {; \2 e( o4 i9 B! Z# m3 I
  5. case WM_LBUTTONDOWN:* A: H. ]# x' n
  6. PostMessage(hwnd,WM_QUIT,0,0);
  7. break;1 ?" x" E8 t, D( T3 N9 k
  8. case WM_DESTROY:
  9. MessageBox(hwnd,"消息测试","WM_DESTROY消息测试",MB_OK);2 s" W- o1 p" }1 D) G, O
  10. break;8 r9 d2 g2 ?5 y+ G  |( K* r7 L
  11. case WM_QUIT:
  12. MessageBox(hwnd,"消息测试","WM_QUIT消息测试",MB_OK);
  13. break;1 x8 A& u% X0 z& C
  14. }7 Z: N6 L2 C! O
  15. return DefWindowProc (hwnd, message, wParam, lParam);& M8 }% t5 i- w
  16. }

复制代码

  果然不假,我们的销毁窗口的消息并没有接收到,我们的程序就退出了循环,但是,窗口关闭了吗? 5 \' n( W- m6 H

  1. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)" ^7 Y" I; Z' q- {) E
  2. {
  3. switch (message)/ @; z+ L- Y! D8 X
  4. {
  5. case WM_LBUTTONDOWN:) k- [* o* ?$ X
  6. PostMessage(hwnd,WM_QUIT,0,0);2 @3 h: c, n$ r8 F7 F4 B
  7. break;
  8. case WM_CLOSE:( e" B% o( Y: r; F8 |: b8 ~
  9. MessageBox(hwnd,"消息测试","WM_CLOSE消息测试",MB_OK);0 Z+ n% J/ `4 |' A" S/ ^# W9 U
  10. break;" `4 B( B4 G* S+ }: E
  11. case WM_DESTROY:
  12. MessageBox(hwnd,"消息测试","WM_DESTROY消息测试",MB_OK);( k$ N( E, O4 [
  13. break;
  14. case WM_QUIT:
  15. MessageBox(hwnd,"消息测试","WM_QUIT消息测试",MB_OK);
  16. break;, [8 `" |( J) U# C/ i1 ]7 N2 k
  17. }
  18. return DefWindowProc (hwnd, message, wParam, lParam);; i! w) D4 @' {9 `4 B+ t% Z  L
  19. }

复制代码

# Z+ t' L6 C6 p- }
; o/ y4 ^1 ]5 u  @4 S
  奇怪的是,窗口也没有被关闭。 & Y; H0 A4 y( b
6 Z" R" k3 ?1 V
  那么就有问题了,窗口既没有被销毁,也没有被关闭,那么这个窗口我们也见不到了,那么这个窗口哪儿去了?[我们 C++ 中没有像 Java 那样的垃圾回收机制,所以也不可能消失]

  唯一的解释,我们的窗口还在内存中,当然,牛刀没当过黑客,如果当过黑客的话,应该通过黑客技术可以将这个窗口重新显示出来,但可以想像,那时候的窗口即使显示出来,也是一个死窗口,什么功能也没有,因为这个窗口已经和我们的程序脱节了,当然黑客技术可以通过一些手段去映射我们的窗口消息到其他的函数上,去满足其他程序的一些需求,可能功能已经不是原来的功能了——怎么像是在说《聊斋》故事啊,呵呵,比较恐怖,呵呵,又感觉在讨论黑客技术啊,呵呵。 3 R$ J0 n" j) u8 y" c" e9 W! E
" B0 j" M, X% Z; I2 i+ M
  总之,窗口是有的,在内存中,我们看不见了,为什么上面像在搞黑客,也是这个原因,会出现内存泄漏,所以从建议的角度来说,是不建议用 PostMessage 来发送 WM_QUIT 消息的。 1 K% p4 U  s( u

  但,是可以用 SendMessage 来发送 WM_QUIT 消息了,但此时,这个消息已经没有退出程序的功能了,如果有必要,我们完全可以当自定义的消息来使用,这样一来,我们如果想自定一个消息,又怕麻烦,那么我们就完全可以不用定义,而直接借用 WM_QUIT 消息来响应就好,唯一的缺点就是,那就不能使用 PostMessage 来发送用户自定义消息啦,呵呵,这不能不说是多线程任务的一个遗憾,但如果想将消息当函数用,那一点问题都没有。 6 h4 X* e/ c4 o  r
1 N' q+ [& A* y1 e
  这就是牛刀对 WM_QUIT 消息的一点粗浅的认识,希望对大家有所帮助。

我以为,SendMessage是立即调用窗口的回调函数,PostMessage是把消息排到消息队列里面。 4楼
/ f# }/ o; Z1 o3 F3 a
WM_QUIT就是用来向系统声明此消息队列结束,不用继续维持了。

重要更正:! M( n; T* |, p% E: r
  上面4楼的最后一个程序,窗口是关闭了的,最后打字时,手误了,呵呵,不好意思。

  5楼的说法是正确的,但是 WM_QUIT 的确是可以通过 SendMessage 发送到窗口中去,并且在窗口消息处理中响应的,但程序结束不了,所以正常情况下,我们是不这样用的,也没有必要。

谢谢楼上的回贴,并不是牛刀想复杂了,而是牛刀在讨论 WM_QUIT 消息的发送机理。
1 ^- }2 x% Q) g! \( m
  因为有些材料上说 WM_QUIT 不是一个消息,只是设置一些标志,而事实上在回调函数中也真的不能响应 WM_QUIT 消息,所以牛刀写这篇文章。0 E( o' }2 \0 u* x/ Q: ]# H
% z& \  ?  L& x( ]& D5 r5 k
  试验的结果是—— WM_QUIT 是一个消息,并且在 WndProc 中亦可以响应,但是必须直接向窗口发出一个消息,也就是说使用 SendMessage 发送;而 GetMessage(&msg,NULL,0,0) 是可以捕捉到消息的,并且仅在捕捉到此消息时,返回值是 0 ,至于你说的 WM_QUIT 不为零,不这奇怪,可以想像,必定是在 GetMessage 函数中有如下代码——" o' E8 ?: S7 _' V' I4 V  }7 V3 o

  1. if(WM_QUIT==message)return 0;

复制代码

' \) V% I4 V+ D' U5 R
  并且事实上,WM_QUIT 消息在 DispatchMessage 函数中,也的确被过滤掉了。因为我们上面的代码—— 4 o( N6 G  W3 b) y  f. u' g1 P

  1. " W7 u% O# i9 _7 j
  2. int MsgRet;
  3. do
  4. {& U1 k% q) O( n& ^- f
  5. MsgRet=GetMessage (&msg, NULL, 0, 0);
  6. TranslateMessage (&msg) ;
  7. DispatchMessage (&msg) ;, h5 v# A; B, N' s/ w/ Y
  8. }while(MsgRet);0 H! |% {- O  G9 x

复制代码

( ]; n3 F8 `# F& P0 j& i
  是允许 WM_QUIT 消息通过 DispatchMessage 函数的,然而,并没有发送到窗体,所以这个消息被过滤掉了,当然,有两种可能,一种是被 DispatchMessage 函数给过滤掉了,另一种可能是被 TranslateMessage 给过滤掉了,那么是哪一种情况呢?牛刀做了如下程序,看看效果——

  1. ! i/ d$ z4 {' P2 l2 C9 f
  2. int MsgRet;
  3. do
  4. {        ; U3 a1 g6 K- T3 `, j
  5. MsgRet=GetMessage (&msg, NULL, 0, 0);- j2 y. Q: L( Y5 m, b# A# e  }
  6. if(WM_QUIT==msg.message)MessageBox(NULL,"WM_QUIT消息在GetMessage函数后被捕获","消息测试",MB_OK);: O4 U2 U) `, f$ f% e% O1 \
  7. TranslateMessage (&msg) ;2 C  n4 w- t$ P, V! J* G5 m
  8. if(WM_QUIT==msg.message)MessageBox(NULL,"WM_QUIT消息在TranslateMessage函数后被捕获","消息测试",MB_OK);
  9. DispatchMessage (&msg) ;0 X; l6 z$ ~+ D9 Y: ^; O
  10. if(WM_QUIT==msg.message)MessageBox(NULL,"WM_QUIT消息在DispatchMessage函数后被捕获","消息测试",MB_OK);
  11. }while(MsgRet);

复制代码

& G; W; T5 x( ~4 `

  三个 Message 都能执行,所以说,TranslateMessage 并没有改变消息, DispatchMessage 也根本没有改变消息,所以消息必然是被 DispatchMessage 函数给过滤掉了。 7 B+ s: Q+ z/ t! e$ z0 ]
2 w4 \8 n5 X- T3 E5 Z- ]+ ~
  注:你的那段函数——

  1. while (GetMessage(&msg,NULL,0,0))2 S9 u+ n1 c3 C" z4 D; l
  2. {
  3. TranslateMessage(&msg);    // Translates virtual key codes.
  4. DispatchMessage(&msg);     // Dispatches message to window.( l0 K4 Q3 _& t
  5. }
  6. return (msg.wParam);           // Returns the value from PostQuitMessage.) m' Z( d: E, ~" c9 {0 Q; x

复制代码

$ f0 @0 q$ S3 E+ R% A, D& q2 |

  固然是正确的,但如果去研究这种消息之间的关系的话,特别是 WM_QUIT 消息,你这种常规写法就难以胜任喽。

关于WM_QUIT消息的牛刀解释相关推荐

  1. linux内核全局变量重定位,关于可重定位文件中全局变量的一个重定位疑惑,借各位牛刀一用^...

    /// 不需要牛刀,不需要阅读源码,如果只是为解决109的含义.楼主执行的查询命令readelf -S  test2.o [ 8] .symtab           SYMTAB           ...

  2. 牛刀:中国房价的买点还没有…

    原文地址:牛刀:中国房价的买点还没有出现作者:牛刀 牛刀:中国房价的买点还没有出现 其实在我的新书<穷人通胀富人通缩>当中,对住宅出现买点的主要特征已经表述的很清楚,用了很大的篇幅阐述买点 ...

  3. Python装饰器——四两拨千斤还是杀鸡用牛刀?

    一.引言 最近做了一个小小小项目,写了一些偏工程的代码.项目的目的看起来很简单,就是去组里的一个能显示调试信息网站上,根据我们提供的一堆查询,获取调试信息的response,然后离线的解析来完成后续实 ...

  4. 数据蒋堂 | Hadoop - 一把杀鸡用的牛刀

    作者:蒋步星 来源:数据蒋堂 本文共1800字,建议阅读6分钟. 通过本文为大家解读为什么Hadoop不适合小集群实现. Hadoop是个庞大的重型解决方案,它的设计目标本来就是大规模甚至超大规模的集 ...

  5. 使用牛刀云开发微信小程序(问题集锦)

    前不久,起步科技正式推出牛刀云1.0,我想这也应该是许多WeX5的忠诚追随者(我也算是其中之一吧)期望的结果了.使用牛刀云开发微信小程序,能够实现使用类似于WeX5的所见即所得组件积木搭建方式构建前端 ...

  6. Sublime Text 3 初试牛刀

    每次我在其他视频网站上看学习视频的时候,看着老师用的编辑器高大上档次,而我一般用Notepad,和Dreamweaver去编辑网页,需要每一行代码,打进去,效率低. 最近看到sublime编辑器,在网 ...

  7. 牛刀:开发商不差钱不等于房价不暴跌 (转载)

    转载自:http://qzone.qq.com/blog/348973589-1246641997 牛刀:开发商不差钱不等于房价不暴跌 现在降低了资本金比例,银行又大量发放贷款,开发商不差钱了,房价怎 ...

  8. 牛刀:房价泡沫的破灭只是人性的回归

    http://blog.sina.com.cn/s/blog_48ea108c0100h9zf.html 牛刀:房价泡沫的破灭只是人性的回归 为什么全球各国只要衍生了房价泡沫,那这个泡沫毫 无例外就一 ...

  9. 低代码之间到底有些什么区别?对比编译型平台“iVX 无远 牛刀”以及接口型平台“明道 宜搭 简道 轻流 氚云 ”

    跟踪研究了很长时间,写一篇文章来和大家分享. 首先,我想说的是,大家不要对"地代码""无代码"有什么偏见,这些都是技术发展的必然,我们只讨论发展的阶段和相关的技 ...

最新文章

  1. UITextView左边距为0
  2. python如何导入txt文件-python如何将数据写入本地txt文本文件
  3. 22行代码AC——习题5-6 对称轴(Symmetry,UVa1595)——解题报告
  4. 前端学习(1925)vue之电商管理系统电商系统之美化一层循环的UI结构
  5. 64位百度云 catia v6_福利缩水:百度网盘决定收回部分储存空间
  6. 电商项目实战项目需求以及技术选型
  7. python代码_抢球鞋?预测股市走势?淘宝秒杀?Python表示要啥有啥 - 街角的守望。...
  8. 今日恐慌与贪婪指数为74 等级转为贪婪
  9. 人生苦短,不光要用 Python,还要在 VSCode 里用 | 原力计划
  10. fancybox 无效 失效 直接打开页面, ajax 之后 fancybox对更新的数据无效,Jquery失效 无效...
  11. C++继承之菱形继承
  12. ping,python实现批量ping包工具--小案例v4优化版本
  13. IE8中动态改变伪元素样式不起作用BUG
  14. centos安装stress安装失败_Linux压力测试工具stress
  15. 史上最简SLAM零基础解读(7) - Jacobian matrix(雅可比矩阵) → 理论分析与应用详解(Bundle Adjustment)
  16. http://blog.csdn.net/LANGXINLEN/article/details/50421988
  17. 初生牛犊,希望早日变成大牛!
  18. Linux云计算运维之Shell
  19. 【大数据AI人工智能】图数据库的发展脉络与技术演进
  20. ubuntu backup

热门文章

  1. html的tabindex属性,让普通元素能够执行聚焦(foucs)和失焦(blur)事件
  2. 可视化+高大上一篇搞定
  3. Feign 的实现原理
  4. [Python]遇到黑底PDF怎么办?自动反色输出!
  5. Oracle 利用lead、lag函数查询已有记录的下一条、上一条记录
  6. python主成分分析代码_PCA主成分分析 原理讲解 python代码实现
  7. 2022年全球市场4D雷达总体规模、主要生产商、主要地区、产品和应用细分研究报告
  8. jq 中英文切换_如何用js实现网站中英文切换?HTML中想把一段js语言转换为jq语言?...
  9. 计算机毕业设计Java汽车租赁系统(源码+系统+mysql数据库+Lw文档)
  10. easyUI默认图标的使用