一个简单的Hello程序,我想问的是,当此程序运行,先关闭WND2的话,会显示“窗口被关闭”,而如果先关闭WND1的话,则WndProc2的WM_DESTROY似乎没有被响应,这是为什么呢?
#include <windows.h>
LRESULT CALLBACK WndProc1(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
MessageBox(hwnd,"Close","MsgBox",MB_OK);
DestroyWindow(hwnd);
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd,msg,wParam,lParam);
}
}
LRESULT CALLBACK WndProc2(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_LBUTTONDOWN:
MessageBox(hwnd,"Click","MsgBox",MB_OK);
return 0;
case WM_DESTROY:
MessageBox(hwnd,"窗口被关闭","MsgBox",MB_OK);
default:
return DefWindowProc(hwnd,msg,wParam,lParam);
}
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
MSG msg;
WNDCLASS wc1,wc2;
HWND hwnd1,hwnd2;
wc1.style=CS_HREDRAW|CS_VREDRAW;
wc1.lpszMenuName=NULL;
wc1.lpszClassName="WC1";
wc1.lpfnWndProc=WndProc1;
wc1.hInstance=hInstance;
wc1.hIcon=LoadIcon(NULL,IDI_WINLOGO);
wc1.hCursor=LoadCursor(NULL,IDC_ARROW);
wc1.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
wc1.cbWndExtra=0;
wc1.cbClsExtra=0;
RegisterClass(&wc1); wc2.style=CS_HREDRAW|CS_VREDRAW;
wc2.lpszMenuName=NULL;
wc2.lpszClassName="WC2";
wc2.lpfnWndProc=WndProc2;
wc2.hInstance=hInstance;
wc2.hIcon=LoadIcon(NULL,IDI_WINLOGO);
wc2.hCursor=LoadCursor(NULL,IDC_ARROW);
wc2.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);
wc2.cbWndExtra=0;
wc2.cbClsExtra=0;
RegisterClass(&wc2); hwnd1=CreateWindow("WC1","WND1",WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL);
hwnd2=CreateWindow("WC2","WND2",WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL);
ShowWindow(hwnd1,nShowCmd);
ShowWindow(hwnd2,nShowCmd);
UpdateWindow(hwnd1);
UpdateWindow(hwnd2); while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
#include <windows.h>
LRESULT CALLBACK WndProc1(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
MessageBox(hwnd,"Close","MsgBox",MB_OK);
DestroyWindow(hwnd);
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd,msg,wParam,lParam);
}
}
LRESULT CALLBACK WndProc2(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_LBUTTONDOWN:
MessageBox(hwnd,"Click","MsgBox",MB_OK);
return 0;
case WM_DESTROY:
MessageBox(hwnd,"窗口被关闭","MsgBox",MB_OK);
default:
return DefWindowProc(hwnd,msg,wParam,lParam);
}
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
MSG msg;
WNDCLASS wc1,wc2;
HWND hwnd1,hwnd2;
wc1.style=CS_HREDRAW|CS_VREDRAW;
wc1.lpszMenuName=NULL;
wc1.lpszClassName="WC1";
wc1.lpfnWndProc=WndProc1;
wc1.hInstance=hInstance;
wc1.hIcon=LoadIcon(NULL,IDI_WINLOGO);
wc1.hCursor=LoadCursor(NULL,IDC_ARROW);
wc1.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
wc1.cbWndExtra=0;
wc1.cbClsExtra=0;
RegisterClass(&wc1); wc2.style=CS_HREDRAW|CS_VREDRAW;
wc2.lpszMenuName=NULL;
wc2.lpszClassName="WC2";
wc2.lpfnWndProc=WndProc2;
wc2.hInstance=hInstance;
wc2.hIcon=LoadIcon(NULL,IDI_WINLOGO);
wc2.hCursor=LoadCursor(NULL,IDC_ARROW);
wc2.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);
wc2.cbWndExtra=0;
wc2.cbClsExtra=0;
RegisterClass(&wc2); hwnd1=CreateWindow("WC1","WND1",WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL);
hwnd2=CreateWindow("WC2","WND2",WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL);
ShowWindow(hwnd1,nShowCmd);
ShowWindow(hwnd2,nShowCmd);
UpdateWindow(hwnd1);
UpdateWindow(hwnd2); while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
==========
确实没有执行,原因很简单,在Proc1中调用DestroyWindow(hwnd);之后你调用了PostQuitMessage(0);此时它发送WM_QUIT消息,GetMessage收到WM_QUIT之后结束消息循环,线程结束,进程也就结束,窗口被系统销毁了。
wnd1先处理了wm_Destory返回,线程退出。。窗口2并未收到此消息。。
wndproc1先处理了wm_Destory返回,直接结束了进程了,窗口2并没收到此消息
我并不是想把hwnd2做成hwnd1的子窗口,只是我刚入门,看到的所有SDK的例子都是只建立一个窗口的。我想知道,一个进程有一个消息队列吗?一个进程可以建立多个窗口吧?如果是建立多个窗口,那么负责退出的窗口,是不是要通知或去主动Destroy所有其他的窗口呢?
罗云彬的Windows汇编设计的书上讲到,DefWindowProc对于WM_DESTROY,并不发送WM_QUIT,原因很简单,就是如果程序中有多个窗口的话,如果DefWindowProc对于WM_DESTROY的默认行为如果是发送WM_QUIT,那么任何一个窗口关闭,程序就结束了。于是我想,如果一个程序可以建立多个窗口,只在其中一个设置PostQuitMessage会是什么样。
但是有窗口的线程一定会有进程、线程不会主动去调用DestroyWindow,如果你希望在程序结束之前发送WM_DESTROY给每个窗口,你必须在WM_QUIT之前调用各个窗口的DestroyWindow,对于API编程而言,这一切都得自己做,对于MFC工程,系统是通过一个独特得机制实现得。以SDI为例,所有窗口都是CMainFrame的子窗口,因此一旦这个窗口,被销毁,所有其他窗口自动被销毁(而且我认为单窗口作为顶级窗口很正常,除了一些dialog之外)。而当你按Alt+F4, 或者窗口右上角的小叉销毁进程时,系统会分别发送WM_APP_EXIT菜单消息和WM_SYSCOMMAND给CMainFrame,这里会最终触发WM_NCDESTROY,这里会DestroyWindow
一个进程收到WM_QUIT后,进程就会结束,窗口就会被系统收回,至于强行回收的窗口是不是用DestroyWindow不好说,我觉得还是用了这个API的,不过进程结束了,WM_DESTROY当然无从发出,也没有窗口函数了,都结束了,所以也就没必要讨论有没有收到WM_DESTROY消息了。 我并不是想把hwnd2做成hwnd1的子窗口,只是我刚入门,看到的所有SDK的例子都是只建立一个窗口的。我想知道,一个进程有一个消息队列吗?一个进程可以建立多个窗口吧?如果是建立多个窗口,那么负责退出的窗口,是不是要通知或去主动Destroy所有其他的窗口呢?
===========
消息队列是对应一个线程的,并不是一个进程一个消息队列,另外,建立多个窗口的话,如果你不进行特殊处理,每个窗口只管自己的事,不会去通知别的窗口的,当然你自己发消息通知那是另外一回事。
罗云彬的Windows汇编设计的书上讲到,DefWindowProc对于WM_DESTROY,并不发送WM_QUIT,原因很简单,就是如果程序中有多个窗口的话,如果DefWindowProc对于WM_DESTROY的默认行为如果是发送WM_QUIT,那么任何一个窗口关闭,程序就结束了。于是我想,如果一个程序可以建立多个窗口,只在其中一个设置PostQuitMessage会是什么样。
==============
PostQuitMessage就是发送WM_QUIT,所以在其中一个窗口处理函数中调用它的话,进程就结束了,别的窗口同时被回收。