一个简单的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;
}

解决方案 »

  1.   

    WM_EXIT肯定被执行的。用SPY++看下。
      

  2.   

    一个简单的Hello程序,我想问的是,当此程序运行,先关闭WND2的话,会显示“窗口被关闭”,而如果先关闭WND1的话,则WndProc2的WM_DESTROY似乎没有被响应,这是为什么呢? 
    ==========
    确实没有执行,原因很简单,在Proc1中调用DestroyWindow(hwnd);之后你调用了PostQuitMessage(0);此时它发送WM_QUIT消息,GetMessage收到WM_QUIT之后结束消息循环,线程结束,进程也就结束,窗口被系统销毁了。
      

  3.   

    一个线程拥有一个消息队列,
    wnd1先处理了wm_Destory返回,线程退出。。窗口2并未收到此消息。。
      

  4.   

    另外还有一个问题,你关闭WND2,WM_DESTROY只会发给WndProc2进行处理,同样,你关闭WND1,WM_DESTROY也只发给WndProc1进行处理。你的代码中关闭WND1时WND2之所以也关闭了也是因为上面所有的进程结束了,系统收回了相关的窗口资源。如果你将上面代码中的PostQuitMessage(0)去掉就会发现,关WND1的话WND2并不会被关闭。
      

  5.   

    在Proc1中调用DestroyWindow(hwnd);之后你调用了PostQuitMessage(0);此时它发送WM_QUIT消息,GetMessage收到WM_QUIT之后结束消息循环,线程结束,进程也就结束。
      

  6.   

    你这俩窗口没啥关系啊 
    wndproc1先处理了wm_Destory返回,直接结束了进程了,窗口2并没收到此消息
      

  7.   

      也就是说,如果一个进程收到WM_QUIT,就会退出,而一旦退出,该进程建立的窗口全部会被销毁。但是与我显式使用DestroyWindow(或系统在DefWindowProc中调用它)不同,被强行回收的窗口并不使用DestroyWindow收回,所以其窗口函数不会收到WM_DESTROY。
      我并不是想把hwnd2做成hwnd1的子窗口,只是我刚入门,看到的所有SDK的例子都是只建立一个窗口的。我想知道,一个进程有一个消息队列吗?一个进程可以建立多个窗口吧?如果是建立多个窗口,那么负责退出的窗口,是不是要通知或去主动Destroy所有其他的窗口呢?
      罗云彬的Windows汇编设计的书上讲到,DefWindowProc对于WM_DESTROY,并不发送WM_QUIT,原因很简单,就是如果程序中有多个窗口的话,如果DefWindowProc对于WM_DESTROY的默认行为如果是发送WM_QUIT,那么任何一个窗口关闭,程序就结束了。于是我想,如果一个程序可以建立多个窗口,只在其中一个设置PostQuitMessage会是什么样。
      

  8.   

    进程不拥有消息队列,而是线程拥有,并且不是每个线程都拥有
    但是有窗口的线程一定会有进程、线程不会主动去调用DestroyWindow,如果你希望在程序结束之前发送WM_DESTROY给每个窗口,你必须在WM_QUIT之前调用各个窗口的DestroyWindow,对于API编程而言,这一切都得自己做,对于MFC工程,系统是通过一个独特得机制实现得。以SDI为例,所有窗口都是CMainFrame的子窗口,因此一旦这个窗口,被销毁,所有其他窗口自动被销毁(而且我认为单窗口作为顶级窗口很正常,除了一些dialog之外)。而当你按Alt+F4, 或者窗口右上角的小叉销毁进程时,系统会分别发送WM_APP_EXIT菜单消息和WM_SYSCOMMAND给CMainFrame,这里会最终触发WM_NCDESTROY,这里会DestroyWindow
      

  9.   

      也就是说,如果一个进程收到WM_QUIT,就会退出,而一旦退出,该进程建立的窗口全部会被销毁。但是与我显式使用DestroyWindow(或系统在DefWindowProc中调用它)不同,被强行回收的窗口并不使用DestroyWindow收回,所以其窗口函数不会收到WM_DESTROY。==================================
    一个进程收到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,所以在其中一个窗口处理函数中调用它的话,进程就结束了,别的窗口同时被回收。
      

  10.   

      哦,这样有些理解了,就是当注册窗口类和创建窗口的时候,将hInstance和hwnd传给了系统,系统自己负责生成了消息队列。