您的位置:首页 > 其它

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

2008-11-30 19:02 405 查看
从用户单击关闭按钮(标题栏最右边)或者用鼠标或鍵盘选择系统菜单的“关闭”选项,直到窗口消失,应用程序结束。这期间到底发生了什么呢?这曾经是我百思不得其解的问题,我想也会有很多人和我一样会碰到这个问题。所以我要把我的一些学习心得写出来,与大家共享:
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,从而结束了消息循环,
应用程序从此结束。
下面我给出完整的证明程序,请大家一试:

#include <Windows.h>

#include <TCHAR.h>

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

int WINAPI WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInst,

LPSTR lpszCmdLine,

int nCmdShow)

{

HWND hwnd;

MSG Msg;

WNDCLASS wndclass;

char lpszClassName[]="窗口";

char lpszTitle[]="窗口示例";

wndclass.style=CS_HREDRAW | CS_VREDRAW;

wndclass.lpfnWndProc =WndProc;

wndclass.cbWndExtra=0;

wndclass.cbClsExtra =0;

wndclass.hInstance=hInstance;

wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);

wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);

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

wndclass.lpszMenuName=NULL;

wndclass.lpszClassName=lpszClassName;

if(!RegisterClass(&wndclass))

{

MessageBeep(0);

return FALSE;

}

hwnd=CreateWindow(lpszClassName,

lpszTitle,

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT,

CW_USEDEFAULT,

CW_USEDEFAULT,

CW_USEDEFAULT,

NULL,

NULL,

hInstance,

NULL);

ShowWindow(hwnd,nCmdShow);

UpdateWindow(hwnd);

while(1)

{

GetMessage(&Msg,NULL,0,0);

if(Msg.message==WM_QUIT)

{

MessageBox(NULL,_T("收到WM_QUIT,即将跳出消息循环"),_T("注意了"),MB_OK);

break;

}

TranslateMessage(&Msg);

DispatchMessage(&Msg);

}

MessageBox(NULL,_T("已经跳出消息循环,应用程序即将结束!"),_T("注意了"),MB_OK);

return Msg.wParam;

}

LRESULT CALLBACK WndProc(

HWND hwnd,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

switch(message)

{

case WM_CLOSE:

MessageBox(NULL,_T("收到WM_CLOSE消息,即将调用 DestroyWindow(hwnd);"),_T("注意了"),MB_OK);

DestroyWindow(hwnd);

break;

case WM_DESTROY:

MessageBox(NULL,_T("已调用过DestroyWindow(hwnd),看不到窗口了吧;"),_T("注意了"),MB_OK);

MessageBox(NULL,_T("以下处理WM_DESTROY"),_T("注意了"),MB_OK);

PostQuitMessage(0);

break;

case WM_SYSCOMMAND:

if((LOWORD(wParam)&0xFFF0)==SC_CLOSE)

{

MessageBox(NULL,_T("你关闭了窗口,即将发送WM_CLOSE消息!"),_T("注意了"),MB_OK);

SendMessage(hwnd,WM_CLOSE,0,0);

}

//不要添加 break,否则不能响应其它WM_SYSCOMMAND消息

default:

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

}

return(0);

}

--------------------------------------------------------------------------------

窗口破坏过程与Windows消息循环的补充,增加了对WM_NCDESTROY的处理

/**

* File Name : MessageTest.cpp

* Version : 1.1

* Project Name : MessageTest

* Project Type : Win32

* Author : netcoder

* Addition : 此版本增加了对WM_NCDESTROY的处理, 感谢 lily311 的补充

*/

#include <windows.h>

#include <tchar.h>

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

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInst,LPSTR lpszCmdLine,int nCmdShow)

{

HWND hwnd;

MSG Msg;

WNDCLASS wndclass;

char lpszClassName[]="窗口";

char lpszTitle[]="窗口示例";

wndclass.style=CS_HREDRAW | CS_VREDRAW;

wndclass.lpfnWndProc =WndProc;

wndclass.cbWndExtra=0;

wndclass.cbClsExtra =0;

wndclass.hInstance=hInstance;

wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);

wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);

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

wndclass.lpszMenuName=NULL;

wndclass.lpszClassName=lpszClassName;

if(!RegisterClass(&wndclass))

{

MessageBeep(0);

return FALSE;

}

hwnd=CreateWindow(lpszClassName,

lpszTitle,

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT,

CW_USEDEFAULT,

CW_USEDEFAULT,

CW_USEDEFAULT,

NULL,

NULL,

hInstance,

NULL);

ShowWindow(hwnd,nCmdShow);

UpdateWindow(hwnd);

while(1)

{

GetMessage(&Msg,NULL,0,0);

if(Msg.message==WM_QUIT)

{

MessageBox(NULL,_T("收到WM_QUIT,即将跳出消息循环"),_T("注意了"),MB_OK);

break;

}

TranslateMessage(&Msg);

DispatchMessage(&Msg);

}

MessageBox(NULL,_T("已经跳出消息循环,应用程序即将结束!"),_T("注意了"),MB_OK);

return Msg.wParam;

}

LRESULT CALLBACK WndProc(

HWND hwnd,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

switch(message)

{

case WM_CLOSE:

MessageBox(NULL,_T("收到WM_CLOSE消息,即将调用 DestroyWindow(hwnd);"),_T("注意了"),MB_OK);

DestroyWindow(hwnd);

break;

case WM_DESTROY:

MessageBox(NULL,_T("已收到WM_DESTROY,看不到窗口了吧!"),_T("注意了"),MB_OK);

break;

case WM_NCDESTROY:

MessageBox(NULL,_T("收到WM_NCDESTROY!"),_T("注意了"),MB_OK);

PostQuitMessage(0);

break;

case WM_SYSCOMMAND:

if((LOWORD(wParam)&0xFFF0)==SC_CLOSE)

{

MessageBox(NULL,_T("你关闭了窗口,即将发送WM_CLOSE消息!"),_T("注意了"),MB_OK);

SendMessage(hwnd,WM_CLOSE,0,0);

}

//不要添加 break,否则不能响应其它WM_SYSCOMMAND消息

default:

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

}

return(0);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: