2020-06-01

關(guān)于WM_QUIT消息的牛刀解釋

yuanhubilie?2013-01-30 12:21:09?

?3201??收藏

展開(kāi)

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

這是我看到的對(duì)windows 進(jìn)程退出跷叉,對(duì)WM_QUIT消息講的最詳細(xì)的了吨枉。

 首先感謝 gz81 對(duì)牛刀 ○六八 講教程的錯(cuò)誤提出调塌。

  經(jīng)管理員確認(rèn),牛刀竟然也有送經(jīng)驗(yàn)送分的權(quán)力惩阶,哈哈匈辱。

  可要注意嘍寺擂,牛刀不但能送正分,還能送負(fù)分喲砾医,呵呵拿撩。9 e( o9 \/ G- p9 D- d9 |

$ J; @+ Y/ h4 j/ R1 j' J

  所以說(shuō),請(qǐng)大家以后盡量不要打著牛刀的旗號(hào)要分要經(jīng)驗(yàn)如蚜,估計(jì)送刀如果送負(fù)分的話绷雏,其他人也不會(huì)送正分給你吧,哼哼2劳ぁO严浴!

  說(shuō)句玩笑話兴猩,不過(guò)既然有這權(quán)力期吓,牛刀就要用,以后對(duì)牛刀教材中的錯(cuò)誤倾芝,進(jìn)行提出并通過(guò)牛刀確認(rèn)的話讨勤,牛刀一律給分,當(dāng)然如下幾種情況不給分(甚至可能給負(fù)分晨另,哼哼)潭千。

·惡意灌水(注:這一點(diǎn)牛刀不容易出現(xiàn),牛刀的教程還能夠受到絕大多數(shù)朋友們的尊重借尿,到目前為止刨晴,惡意灌水的寥寥無(wú)幾。# v# k/ ^1 Y; G??z

·別字(牛刀的錯(cuò)筆字不屬送分范圍路翻,當(dāng)然可以提出狈癞,當(dāng)然其實(shí)有時(shí)候,牛刀自己都發(fā)現(xiàn)筆字茂契,說(shuō)實(shí)話蝶桶,懶得改,呵呵掉冶,大家順著讀吧真竖,呵呵。注:牛刀用的是五筆厌小,屬于字型碼恢共,所以有些東西真容易打錯(cuò)的,例如有些地方字典打成“字曲”召锈,這些都屬于手誤旁振,不屬送分范圍)! ]* \. u) \, o: Q8 ^; j4 ]

·語(yǔ)句不通(有些語(yǔ)句就是不通获询,或者說(shuō)有意不通涨岁,也就是說(shuō)拐袜,語(yǔ)法上的東東,不屬于送分范圍)! m( H% f( a' t2 O8 @" p+ k

·文字偏差(有些屬于前期論壇的代碼問(wèn)題梢薪,如果“[i]”蹬铺,在以前的論壇上就都是斜體,不過(guò)牛刀不改了秉撇,為什么甜攀,因?yàn)椴桓哪憔筒荒苡谩皬?fù)制/粘貼”大法,呵呵琐馆,牛刀的教材是實(shí)踐教材规阀,所以對(duì)于一切文字上的偏差,也不在送分范圍)

·未經(jīng)確認(rèn)(其他情況瘦麸,牛刀感覺(jué)不值得送分的谁撼,牛刀也不會(huì)送分,當(dāng)然滋饲,直接要分的厉碟,牛刀不但不會(huì)送分甚至可能扣分,所以切忌要分)屠缭。5 m# ^- i9 B/ p! s5 ]) L9 }) L( g4 y

8 Y* G' G, c6 ], t6 Q" I: r' C

  說(shuō)實(shí)話箍鼓,能夠發(fā)現(xiàn)牛刀教程中的錯(cuò)誤,證明你上機(jī)了呵曹,實(shí)踐了款咖,否則,是絕對(duì)不可能發(fā)現(xiàn)一些質(zhì)的錯(cuò)誤的奄喂。* o4 p1 x4 e, h* o

  對(duì)了之剧,這位朋友提出的是 牛刀使用了一個(gè)系統(tǒng)沒(méi)有的消息 WM_EXIT 這個(gè)消息系統(tǒng)沒(méi)有,后進(jìn)管理員確認(rèn)砍聊,牛刀也確認(rèn)沒(méi)有背稼,于是,管理員經(jīng)過(guò)查找資料玻蝌,提出了一個(gè)問(wèn)題 WM_QUIT 是不是屬于消息蟹肘。

  有些資料上對(duì)此不認(rèn)為是一個(gè)消息,而這個(gè)功能就是設(shè)定某些標(biāo)志位俯树,于是帘腹,牛刀就去做了一些程序——

#include

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

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,7 f??w9 b% D' ~0 }

PSTR szCmdLine, int iCmdShow)) I: F; g4 N5 k1 h/ [

{

static TCHAR szAppName[] = TEXT ("TestWin") ;: e4 [. C- [" n* Q( t% X% @??u

HWND? ? ? ? hwnd ;

MSG? ? ? ? msg ;

WNDCLASS? ? ? ? wndclass ;. _4 W2 }5 C??h6 a

wndclass.style? ? ? ? ? ? ? ?? ?= CS_HREDRAW | CS_VREDRAW ;

wndclass.lpfnWndProc??= WndProc ;* c, B% D9 e- c' s4 j9 b

wndclass.cbClsExtra? ? ? ?? ?= 0 ;

wndclass.cbWndExtra? ? ? ?? ?= 0 ;

wndclass.hInstance? ? ? ?? ?= hInstance ;

wndclass.hIcon? ? ? ? ? ? ? ?? ?= LoadIcon (NULL, IDI_APPLICATION) ;

wndclass.hCursor? ? ? ?? ?= LoadCursor (NULL, IDC_ARROW) ;& z7 m6 x$ j, S, p

wndclass.hbrBackground? ? ? ? = (HBRUSH) GetStockObject (WHITE_BRUSH) ;

wndclass.lpszMenuName? ? ? ? = NULL;' r% x* K3 Q+ K/ H+ T??D

wndclass.lpszClassName? ? ? ? = szAppName ;3 p, S5 _9 |5 `! w

if (!RegisterClass (&wndclass))

{

MessageBox (? ? ? ? NULL, TEXT ("This program requires Windows NT!"),

szAppName, MB_ICONERROR) ;

return 0 ;7 C4 z, Z. A" v. d

}2 [9 s; x9 Y6 u( Z3 |1 _: ?' T6 S

hwnd = CreateWindow( szAppName,TEXT ("牛刀WM_QUIT測(cè)試"),WS_OVERLAPPEDWINDOW,& O2 U+ G% S3 ^& s& g4 f

CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,% o( G3 i1 I! z

NULL,NULL,hInstance,NULL) ;

' U0 Y/ g/ }5 C3 H- X# C

ShowWindow (hwnd, iCmdShow) ;??L) [6 W3 N: P8 a: M' s4 C% a

UpdateWindow (hwnd) ;. Z; t# F2 V% k; |# q

while (GetMessage (&msg, NULL, 0, 0))( }% ~% f( a. J! L

{7 T3 r/ h% Q2 x; n2 Q

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;+ j1 D0 Y3 g7 Q

}/ U% ^3 T! S/ O- V2 t

return msg.wParam ;

}

# n1 W- L; E8 E! X

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

{* c# v; [% \. v6 R" z. b: i" @( z

switch (message)" R7 h4 B# p# h* [& m: Y

{

case? ? ? ? WM_DESTROY:

PostQuitMessage (0) ;

return 0 ;

}

return DefWindowProc (hwnd, message, wParam, lParam) ;??c4 R, s) ^3 \5 L

}

復(fù)制代碼

上面的程序,我們可以運(yùn)行了许饿,并且只在 WM_DESTROY 發(fā)送了 WM_QUIT 消息阳欲,所以說(shuō),如果這一個(gè)消息不響應(yīng)的話,那么我們的程序就結(jié)束不了球化,以前我們?cè)?jīng)說(shuō)過(guò)秽晚,沒(méi)有 PostQuitMessage 消息的話,我們的程序是結(jié)束不了的筒愚。(什么赴蝇?你的程序結(jié)束了?你打開(kāi)任務(wù)管理器看看巢掺,真的結(jié)束了嗎句伶?只不過(guò)是窗口被銷(xiāo)毀了罷了,呵呵陆淀,所以說(shuō)考余,當(dāng) WM_DESTROY 消息響應(yīng)時(shí),我們的程序窗口已經(jīng)被銷(xiāo)毀轧苫。). l# _( x??_' D??l6 W6 @??\

  當(dāng)然 WM_CLOSE 消息被響應(yīng)時(shí)秃殉,窗口還沒(méi)有銷(xiāo)毀,當(dāng)然浸剩,那個(gè)消息中钾军,是可以執(zhí)行 DestroyWindow 函數(shù)去銷(xiāo)毀窗口的,而如果不執(zhí)行的話绢要,那么窗口就銷(xiāo)毀不了吏恭,也就是說(shuō),我們?nèi)绻憫?yīng)一個(gè)空消息的話——

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)" ^??I9 o: y. Y! C( a3 K7 ~( B

{0 j+ U2 t0 p???9 C

switch (message)

{2 R- _( k% l# ?% M/ ~??l

case WM_CLOSE:

return 0;

default:/ _* h* {+ g0 q9 \# R& j/ m, U

return DefWindowProc (hwnd, message, wParam, lParam) ;

}

}

復(fù)制代碼

我們的窗口是關(guān)不掉的重罪,所以說(shuō)樱哼,系統(tǒng)默認(rèn)函數(shù)在響應(yīng) WM_CLOSE 時(shí),是提供銷(xiāo)毀窗口的函數(shù)的剿配,然而搅幅,在銷(xiāo)毀窗口時(shí),卻沒(méi)有提供發(fā)送 WM_QUIT 消息的函數(shù)呼胚,所以我們的消息處理中茄唐,至少響應(yīng)如下消息:

! J) H3 v' _" ~; z3 C

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)" G5 G/ F; C: P4 a( }" j

{, r) l1 X??@9 U& x) {. p

switch (message)

{: U2 W, E" u% x2 L- T/ g

case WM_DESTROY:

PostQuitMessage (0) ;

return 0 ;

default:/ [3 b( s4 ^7 G7 L# w& M

return DefWindowProc (hwnd, message, wParam, lParam);

}1 K) K( H0 B# @% L; K' ~, r4 L8 j

}! x& d6 g7 D- [7 l* r??J

復(fù)制代碼

那好,一個(gè)問(wèn)題蝇更,我們的函數(shù)能夠響應(yīng)WM_QUIT 消息嗎沪编?如果按照某些材料上說(shuō)的,我們就不能響應(yīng)這個(gè)消息了年扩,去做一個(gè)程序試試——

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

{

switch (message)

{

case WM_DESTROY:

PostQuitMessage (0) ;9 r??x2 p: Z??k5 V) ~

break;

case WM_QUIT:

MessageBox(hwnd,"消息測(cè)試","WM_QUIT消息測(cè)試",MB_OK);

break;

}- k??n# n, B5 b7 X0 N) ?

return DefWindowProc (hwnd, message, wParam, lParam);

}

復(fù)制代碼

果然不假蚁廓,上面的一些理論得到了證實(shí),可是牛刀不服厨幻,既然沒(méi)有用相嵌,那么要這個(gè)消息干嘛腿时?牛刀不服,換了一個(gè)地方打劫——

) p3 s2 X" v! A! j

while (GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg) ;, g( R! t0 I5 G- N

DispatchMessage (&msg) ;

}* }1 ]. p+ E" j' X4 R4 J. |

if(WM_QUIT==msg.message)MessageBox(NULL,"消息測(cè)試","WM_QUIT消息測(cè)試",MB_OK);

復(fù)制代碼

這一次饭宾,這個(gè)消息被我們打劫到了批糟,并且順利地執(zhí)行,那么為什么我們?cè)凇ndProc 函數(shù)中捏雌,得不到消息呢?我們來(lái)看看我們消息的執(zhí)行過(guò)程)——

- n9 \, X- R% g% I6 r8 E

while (GetMessage (&msg, NULL, 0, 0))??//得到消息笆搓,請(qǐng)注意性湿,如果消息是 WM_QUIT,那么這個(gè)函數(shù)就返回 0 满败,下面的程序就執(zhí)行不到了肤频。8 L0 q& U4 x- L* i

{1 ?% k, y- t2 ^. T& c2 B, m) o

TranslateMessage (&msg) ;??//翻譯程序植袍,翻譯消息# b??u$ h. U/ d) A

DispatchMessage (&msg) ;? ?//執(zhí)行消息饲漾,是這一句將消息隊(duì)列中的消息傳遞給 WndProc 函數(shù)肤京,所以一旦有了 WM_QUIT 消息稠茂,這一句就執(zhí)行不到艾岂,于是隙畜,我們的消息在 WndProc 函數(shù)中就捕捉不到了蒜埋。

}" f5 N9 C6 q2 u1 q; o% o

復(fù)制代碼

明白了上面的道理玖详,那么我們?nèi)绻朐谙⑻幚砗瘮?shù)中捕捉到這個(gè)消息挖藏,那么我們?cè)趺崔k呢暑刃?可以改一下下程序嘛,呵呵膜眠,看——

6 O9 |4 |+ ^3 y

int MsgRet;. i+ Q2 b" a3 i0 _/ v; y1 w

do4 g6 o2 P??F' \+ u

{? ? ? ? MsgRet=GetMessage (&msg, NULL, 0, 0);' V; s9 b2 n9 h' P# O/ j( B

TranslateMessage (&msg) ;! U! }$ k* ?* L& v" p2 H

DispatchMessage (&msg) ;

}while(MsgRet);? ? ? ? //我們改了成 do-while 結(jié)構(gòu)岩臣,這樣上面的消息就每條消息都有機(jī)會(huì)送到 WinProc 函數(shù)嘍

復(fù)制代碼

程序理論講完了,很可惜的是宵膨,我們的程序架谎, WndProc 中的 WM_QUIT 消息仍舊沒(méi)有被執(zhí)行,這是什么原因辟躏?谷扣??: i* O2 x8 _% C; U* q

  很顯然捎琐,肯定被系統(tǒng)的 DispatchMessage (&msg) ; 函數(shù)給過(guò)濾掉了抑钟,不知牛刀考慮的有沒(méi)有道理,大家可以各抒己見(jiàn)野哭。

: P, k7 E2 Z: T

  結(jié)論:WM_QUIT 是一個(gè)消息在塔,但這個(gè)消息不能在 WndProc 消息函數(shù)中被捕獲,如果要響應(yīng)拨黔,也只能在消息循環(huán)地位置攔截蛔溃,但我們一般不需要這樣做。

原文:"注意到WM_QUIT消息讓消息循環(huán)終止歸根結(jié)底是讓GetMessage返回為0,而GetMessage函數(shù)是從消息對(duì)列里取一條消息贺待,然后再返回徽曲,只能當(dāng)消息為WM_QUIT時(shí)才返回0結(jié)束消息循環(huán)。再仔細(xì)看一下SendMessage的注釋發(fā)現(xiàn)麸塞,SendMessage直接發(fā)送到窗口秃臣,并調(diào)用窗口處理程序,完成消息響應(yīng)哪工,即SendMessage 根本就沒(méi)有將消息發(fā)到消息對(duì)列中奥此,因此GetMessage無(wú)法從消息對(duì)列中收到WM_QUIT的消息。而PostMessage卻直接發(fā)送消息到消息對(duì)列中雁比,然后立即返回稚虎,這一點(diǎn)點(diǎn)的區(qū)別就解決了我們上面的問(wèn)題。陸解了這一點(diǎn)偎捎,就不難理解上面注釋中說(shuō)的為什么不讓直接使用PostMessage來(lái)發(fā)送WM_QUIT消息來(lái)終止程序了蠢终。"

 GetMessage 是收到了 WM_QUIT 消息的,但牛刀的結(jié)論是:被 DispatchMessage 函數(shù)給過(guò)濾掉了茴她。( F' P8 F" m8 i: r

  也就是說(shuō)寻拂,WM_QUIT 消息發(fā)送給窗口是無(wú)效的,所以使用 SendMessage 向窗口發(fā)送 WM_QUIT 消息則無(wú)效丈牢。6 c. T# _+ [/ ]0 Q# q

  為了驗(yàn)證這個(gè)想法兜喻,牛刀去做了一個(gè)測(cè)試——

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

{" L. T, v5 @. A% j. w& X

switch (message). K% }" W. Z5 T" `) q

{

case WM_LBUTTONDOWN:6 O* b??Z, C% w0 D

SendMessage(hwnd,WM_QUIT,0,0);# c! }$ H% g" f% j??^5 B. g

break;

case WM_DESTROY:

PostQuitMessage (0) ;

break;

case WM_QUIT:

MessageBox(hwnd,"消息測(cè)試","WM_QUIT消息測(cè)試",MB_OK);/ r6 x* ]" h; E+ ^$ W! l6 g

break;

}

return DefWindowProc (hwnd, message, wParam, lParam);' \4 s! Z4 Y; w6 A5 Q! o0 j

}

復(fù)制代碼

8 T??H" E- @7 y' @. W

2 C& E+ D5 y3 ]# Q( {( ]- {

  牛刀驚奇地發(fā)現(xiàn),牛刀上面的 SendMessage 發(fā)送消息無(wú)效的結(jié)論是不正確的赡麦。窗口函數(shù)的確響應(yīng)的 WM_QUIT 消息朴皆,但由于這個(gè)消息沒(méi)有被 GetMessage 捕獲,所以程序根本沒(méi)有退出泛粹,也就是說(shuō)遂铡,使用 SendMessage 發(fā)送這個(gè)消息時(shí),是不經(jīng)過(guò)消息隊(duì)列的晶姊,也就是說(shuō)是不經(jīng)過(guò)——

while(GetMessage (&msg, NULL, 0, 0))7 }5 G% t0 i1 r( l# _

{

TranslateMessage (&msg) ;# B( y/ i1 I. s/ u# Z

DispatchMessage (&msg) ;5 ?+ N0 O9 a/ C8 R6 E6 [5 q

}

復(fù)制代碼

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

  這個(gè)消息循環(huán)的扒接,所以不能使得 GetMessage 返回 0 值。

  于是们衙,牛刀又去測(cè)試了 PostMessage 消息:: w??C; B2 x% s" g7 @

% K4 _+ q3 ?7 T/ ?4 t6 \3 w! Q2 f

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

{

switch (message)# b' n& m, Z" e( [' H

{5 h; Y3 f3 J( }" B% e

case WM_LBUTTONDOWN:

PostMessage(hwnd,WM_QUIT,0,0);

break;

case WM_DESTROY:5 R2 w- b2 k- d1 {/ t

PostQuitMessage (0) ;??h& H/ c' C) q3 C; U9 b

break;

case WM_QUIT:) B* v4 v1 P1 V) h! Z1 C4 u$ e

MessageBox(hwnd,"消息測(cè)試","WM_QUIT消息測(cè)試",MB_OK);

break;

}

return DefWindowProc (hwnd, message, wParam, lParam);& C$ |??W8 P2 Q; R/ @0 S# s$ r. t" Q

}

復(fù)制代碼

& q% Z! H: y5 d

  由于消息這次是發(fā)進(jìn)了消息隊(duì)列钾怔,所以我們?cè)凇ndProc 函數(shù)中就又不能響應(yīng)消息了。8 y. Y) Q( r2 j* y??G' g0 N( U

. L2 A, \$ ~% \- u

  綜上所述:

·WM_QUIT 的確是一條消息蒙挑,并且這個(gè)消息是可以發(fā)送到消息隊(duì)列中(使用PostMessage)宗侦,亦可以發(fā)送到窗口(使用SendMessage),但是忆蚀,我們是不能通過(guò)消息隊(duì)列將消息發(fā)送到窗口中的矾利,因?yàn)槲覀兊年?duì)列中的消息被 DispatchMessage 給過(guò)濾掉了姑裂。2 O, ]5 P9 x3 I! z# q" |

  通過(guò)上面的一些討論與測(cè)試,我們基本可以估計(jì)出 DispatchMessage 的函數(shù)應(yīng)該是這樣或近似這樣的程序——

void DispatchMessage(MSG msg)

{

if(WM_QUIT!=msg.message)

{

SendMessage(msg.hwnd,msg.message,msg.wParam,msg.lParam);

}

}* i0 ]0 p# d??N3 m7 Z6 J

復(fù)制代碼

, @) s/ s, \( q! j

  附:為什么不建議直接用 PostMessage 來(lái)發(fā) WM_QIUT 消息的牛刀解釋男旗。" q6 a/ x0 @??N+ U; A/ _

  首先一點(diǎn)的就是舶斧,可以使用 PostMessage 來(lái)發(fā)送 WM_QUIT 消息,并且一點(diǎn)殘留都沒(méi)有(注:任務(wù)管理器中一點(diǎn)殘余都沒(méi)有)察皇。* J( d" o, {: b% `8 V1 W+ ?

  當(dāng)然茴厉,窗口也沒(méi)有了,程序結(jié)束了什荣,但會(huì)有一個(gè)問(wèn)題矾缓,那就是,我們的窗口并沒(méi)有被銷(xiāo)毀溃睹,因?yàn)闆](méi)有來(lái)得及響應(yīng) WM_DESTROY 消息而账,為了驗(yàn)證胰坟,牛刀做了以下的程序——

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

{

switch (message)7 A- O* z* B- H* T0 ~

{; \2 e( o4 i9 B! Z# m3 I

case WM_LBUTTONDOWN:* A: H. ]# x' n

PostMessage(hwnd,WM_QUIT,0,0);

break;1 ?" x" E8 t, D( T3 N9 k

case WM_DESTROY:

MessageBox(hwnd,"消息測(cè)試","WM_DESTROY消息測(cè)試",MB_OK);2 s" W- o1 p" }1 D) G, O

break;8 r9 d2 g2 ?5 y+ G??|( K* r7 L

case WM_QUIT:

MessageBox(hwnd,"消息測(cè)試","WM_QUIT消息測(cè)試",MB_OK);

break;1 x8 A& u% X0 z& C

}7 Z: N6 L2 C! O

return DefWindowProc (hwnd, message, wParam, lParam);& M8 }% t5 i- w

}

復(fù)制代碼

  果然不假因篇,我們的銷(xiāo)毀窗口的消息并沒(méi)有接收到,我們的程序就退出了循環(huán)笔横,但是竞滓,窗口關(guān)閉了嗎?5 \' n( W- m6 H

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)" ^7 Y" I; Z' q- {) E

{

switch (message)/ @; z+ L- Y! D8 X

{

case WM_LBUTTONDOWN:) k- [* o* ?$ X

PostMessage(hwnd,WM_QUIT,0,0);2 @3 h: c, n$ r8 F7 F4 B

break;

case WM_CLOSE:( e" B% o( Y: r; F8 |: b8 ~

MessageBox(hwnd,"消息測(cè)試","WM_CLOSE消息測(cè)試",MB_OK);0 Z+ n% J/ `4 |' A" S/ ^# W9 U

break;" `4 B( B4 G* S+ }: E

case WM_DESTROY:

MessageBox(hwnd,"消息測(cè)試","WM_DESTROY消息測(cè)試",MB_OK);( k$ N( E, O4 [

break;

case WM_QUIT:

MessageBox(hwnd,"消息測(cè)試","WM_QUIT消息測(cè)試",MB_OK);

break;, [8 `" |( J) U# C/ i1 ]7 N2 k

}

return DefWindowProc (hwnd, message, wParam, lParam);; i! w) D4 @' {9 `4 B+ t% Z??L

}

復(fù)制代碼

# Z+ t' L6 C6 p- }

; o/ y4 ^1 ]5 u??@4 S

  奇怪的是吹缔,窗口也沒(méi)有被關(guān)閉商佑。& Y; H0 A4 y( b

6 Z" R" k3 ?1 V

  那么就有問(wèn)題了,窗口既沒(méi)有被銷(xiāo)毀厢塘,也沒(méi)有被關(guān)閉茶没,那么這個(gè)窗口我們也見(jiàn)不到了,那么這個(gè)窗口哪兒去了晚碾?[我們 C++ 中沒(méi)有像 Java 那樣的垃圾回收機(jī)制抓半,所以也不可能消失]

  唯一的解釋?zhuān)覀兊拇翱谶€在內(nèi)存中,當(dāng)然格嘁,牛刀沒(méi)當(dāng)過(guò)黑客笛求,如果當(dāng)過(guò)黑客的話,應(yīng)該通過(guò)黑客技術(shù)可以將這個(gè)窗口重新顯示出來(lái)糕簿,但可以想像探入,那時(shí)候的窗口即使顯示出來(lái),也是一個(gè)死窗口懂诗,什么功能也沒(méi)有蜂嗽,因?yàn)檫@個(gè)窗口已經(jīng)和我們的程序脫節(jié)了,當(dāng)然黑客技術(shù)可以通過(guò)一些手段去映射我們的窗口消息到其他的函數(shù)上殃恒,去滿足其他程序的一些需求徒爹,可能功能已經(jīng)不是原來(lái)的功能了——怎么像是在說(shuō)《聊齋》故事啊荚醒,呵呵,比較恐怖隆嗅,呵呵界阁,又感覺(jué)在討論黑客技術(shù)啊,呵呵胖喳。3 R$ J0 n" j) u8 y" c" e9 W! E

" B0 j" M, X% Z; I2 i+ M

  總之泡躯,窗口是有的,在內(nèi)存中丽焊,我們看不見(jiàn)了较剃,為什么上面像在搞黑客,也是這個(gè)原因技健,會(huì)出現(xiàn)內(nèi)存泄漏写穴,所以從建議的角度來(lái)說(shuō),是不建議用 PostMessage 來(lái)發(fā)送 WM_QUIT 消息的雌贱。1 K% p4 U??s( u

  但啊送,是可以用 SendMessage 來(lái)發(fā)送 WM_QUIT 消息了,但此時(shí)欣孤,這個(gè)消息已經(jīng)沒(méi)有退出程序的功能了馋没,如果有必要,我們完全可以當(dāng)自定義的消息來(lái)使用降传,這樣一來(lái)篷朵,我們?nèi)绻胱远ㄒ粋€(gè)消息,又怕麻煩婆排,那么我們就完全可以不用定義声旺,而直接借用 WM_QUIT 消息來(lái)響應(yīng)就好,唯一的缺點(diǎn)就是段只,那就不能使用 PostMessage 來(lái)發(fā)送用戶自定義消息啦腮猖,呵呵,這不能不說(shuō)是多線程任務(wù)的一個(gè)遺憾翼悴,但如果想將消息當(dāng)函數(shù)用缚够,那一點(diǎn)問(wèn)題都沒(méi)有。6 h4 X* e/ c4 o??r

1 N' q+ [& A* y1 e

  這就是牛刀對(duì) WM_QUIT 消息的一點(diǎn)粗淺的認(rèn)識(shí)鹦赎,希望對(duì)大家有所幫助谍椅。

我以為,SendMessage是立即調(diào)用窗口的回調(diào)函數(shù)古话,PostMessage是把消息排到消息隊(duì)列里面雏吭。?4樓

/ f# }/ o; Z1 o3 F3 a

WM_QUIT就是用來(lái)向系統(tǒng)聲明此消息隊(duì)列結(jié)束,不用繼續(xù)維持了陪踩。

重要更正:! M( n; T* |, p% E: r

  上面4樓的最后一個(gè)程序杖们,窗口是關(guān)閉了的悉抵,最后打字時(shí),手誤了摘完,呵呵姥饰,不好意思。

 ⌒⒅巍5樓的說(shuō)法是正確的列粪,但是 WM_QUIT 的確是可以通過(guò) SendMessage 發(fā)送到窗口中去,并且在窗口消息處理中響應(yīng)的谈飒,但程序結(jié)束不了岂座,所以正常情況下,我們是不這樣用的杭措,也沒(méi)有必要费什。

謝謝樓上的回貼,并不是牛刀想復(fù)雜了手素,而是牛刀在討論 WM_QUIT 消息的發(fā)送機(jī)理鸳址。

1 ^- }2 x% Q) g! \( m

  因?yàn)橛行┎牧仙险f(shuō) WM_QUIT 不是一個(gè)消息,只是設(shè)置一些標(biāo)志刑桑,而事實(shí)上在回調(diào)函數(shù)中也真的不能響應(yīng) WM_QUIT 消息氯质,所以牛刀寫(xiě)這篇文章募舟。0 E( o' }2 \0 u* x/ Q: ]# H

% z& \?????L& x( ]& D5 r5 k

  試驗(yàn)的結(jié)果是—— WM_QUIT 是一個(gè)消息祠斧,并且在 WndProc 中亦可以響應(yīng),但是必須直接向窗口發(fā)出一個(gè)消息拱礁,也就是說(shuō)使用 SendMessage 發(fā)送琢锋;而 GetMessage(&msg,NULL,0,0) 是可以捕捉到消息的,并且僅在捕捉到此消息時(shí)呢灶,返回值是 0 吴超,至于你說(shuō)的 WM_QUIT 不為零,不這奇怪鸯乃,可以想像鲸阻,必定是在 GetMessage 函數(shù)中有如下代碼——" o' E8 ?: S7 _' V' I4 V??}7 V3 o

if(WM_QUIT==message)return 0;

復(fù)制代碼

' \) V% I4 V+ D' U5 R

  并且事實(shí)上,WM_QUIT 消息在 DispatchMessage 函數(shù)中缨睡,也的確被過(guò)濾掉了鸟悴。因?yàn)槲覀兩厦娴拇a——4 o( N6 G??W3 b) y??f. u' g1 P

" W7 u% O# i9 _7 j

int MsgRet;

do

{& U1 k% q) O( n& ^- f

MsgRet=GetMessage (&msg, NULL, 0, 0);

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;, h5 v# A; B, N' s/ w/ Y

}while(MsgRet);0 H! |% {- O??G9 x

復(fù)制代碼

( ]; n3 F8 `# F& P0 j& i

  是允許 WM_QUIT 消息通過(guò) DispatchMessage 函數(shù)的,然而奖年,并沒(méi)有發(fā)送到窗體细诸,所以這個(gè)消息被過(guò)濾掉了,當(dāng)然陋守,有兩種可能震贵,一種是被 DispatchMessage 函數(shù)給過(guò)濾掉了利赋,另一種可能是被 TranslateMessage 給過(guò)濾掉了,那么是哪一種情況呢猩系?牛刀做了如下程序媚送,看看效果——

! i/ d$ z4 {' P2 l2 C9 f

int MsgRet;

do

{; U3 a1 g6 K- T3 `, j

MsgRet=GetMessage (&msg, NULL, 0, 0);- j2 y. Q: L( Y5 m, b# A# e??}

if(WM_QUIT==msg.message)MessageBox(NULL,"WM_QUIT消息在GetMessage函數(shù)后被捕獲","消息測(cè)試",MB_OK);: O4 U2 U) `, f$ f% e% O1 \

TranslateMessage (&msg) ;2 C??n4 w- t$ P, V! J* G5 m

if(WM_QUIT==msg.message)MessageBox(NULL,"WM_QUIT消息在TranslateMessage函數(shù)后被捕獲","消息測(cè)試",MB_OK);

DispatchMessage (&msg) ;0 X; l6 z$ ~+ D9 Y: ^; O

if(WM_QUIT==msg.message)MessageBox(NULL,"WM_QUIT消息在DispatchMessage函數(shù)后被捕獲","消息測(cè)試",MB_OK);

}while(MsgRet);

復(fù)制代碼

& G; W; T5 x( ~4 `

  三個(gè) Message 都能執(zhí)行,所以說(shuō)寇甸,TranslateMessage 并沒(méi)有改變消息季希, DispatchMessage 也根本沒(méi)有改變消息,所以消息必然是被 DispatchMessage 函數(shù)給過(guò)濾掉了幽纷。7 B+ s: Q+ z/ t! e$ z0 ]

2 w4 \8 n5 X- T3 E5 Z- ]+ ~

  注:你的那段函數(shù)——

while (GetMessage(&msg,NULL,0,0))2 S9 u+ n1 c3 C" z4 D; l

{

TranslateMessage(&msg);? ? // Translates virtual key codes.

DispatchMessage(&msg);? ???// Dispatches message to window.( l0 K4 Q3 _& t

}

return (msg.wParam);? ?? ?? ???// Returns the value from PostQuitMessage.) m' Z( d: E, ~" c9 {0 Q; x

復(fù)制代碼

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末式塌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子友浸,更是在濱河造成了極大的恐慌峰尝,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件收恢,死亡現(xiàn)場(chǎng)離奇詭異武学,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)伦意,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)火窒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人驮肉,你說(shuō)我怎么就攤上這事熏矿。” “怎么了离钝?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵票编,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我卵渴,道長(zhǎng)慧域,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任浪读,我火速辦了婚禮昔榴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘碘橘。我一直安慰自己互订,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布蛹屿。 她就那樣靜靜地躺著屁奏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪错负。 梳的紋絲不亂的頭發(fā)上坟瓢,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天勇边,我揣著相機(jī)與錄音,去河邊找鬼折联。 笑死粒褒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诚镰。 我是一名探鬼主播奕坟,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼清笨!你這毒婦竟也來(lái)了月杉?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤抠艾,失蹤者是張志新(化名)和其女友劉穎苛萎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體检号,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腌歉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了齐苛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翘盖。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖凹蜂,靈堂內(nèi)的尸體忽然破棺而出馍驯,到底是詐尸還是另有隱情,我是刑警寧澤炊甲,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布泥彤,位于F島的核電站欲芹,受9級(jí)特大地震影響卿啡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜菱父,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一颈娜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧浙宜,春花似錦官辽、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至裙品,卻和暖如春俗批,著一層夾襖步出監(jiān)牢的瞬間俗或,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工岁忘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辛慰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓干像,卻偏偏與公主長(zhǎng)得像帅腌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子麻汰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354