win32 API 创建多个窗口,消息捕获问题求解!!

wojiushi3344 2012-11-01 10:26:12

这个问题困惑我很久了,希望有人能帮我解除疑惑!所有分都拿出来了。
现在我创建了多个窗口,每个窗口拥有自己的消息循环,多个窗口共用一个窗口处理过程。如果创建2个窗口,然后关闭窗口的顺序和创建的顺序一样就没有问题,但是如果我最先关闭第一个窗口,后关闭2个窗口就会出现问题。调试发现,当关闭第一个窗口的时候,消息被第2个窗口的消息循环捕获了,请问有没有办法解决这问题?如果没看懂可以看下面的图片描述。谢谢大家!


最终想达到的效果就是,我关闭的哪个窗口就由哪个窗口来捕获消息。现在的问题是就是所有消息都被最后创建的窗口捕获了。在线等大家的结果!!
...全文
721 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
幸福绿光 2015-05-06
  • 打赏
  • 举报
回复

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, (LPWSTR)custommessage.commonvariables.szTitle.c_str(), MAX_LOADSTRING);
LoadString(hInstance, IDS_APP_TITLE, (LPWSTR)custommessage.commonvariables.szWindowClass.c_str(), MAX_LOADSTRING);

custommessage.commonvariables.hInst = hInstance; // Store instance handle in our global variable

custommessage.commonvariables.hMainWnd = CreateDialog(custommessage.commonvariables.hInst, MAKEINTRESOURCE(IDD_DIALOG_WNDPROC), 0, (DLGPROC)WndProc);
if (!custommessage.commonvariables.hMainWnd)
{
return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDM_MENU_CWINDOW));
ShowWindow(custommessage.commonvariables.hMainWnd, nCmdShow);

// Main message loop:

while (GetMessage(&msg, NULL, 0, 0))
{
if (msg.hwnd == 0 || !IsDialogMessage (msg.hwnd, &msg))
{
if(!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}

return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
custommessage.InitializationWndprocControl(hWnd); // 控件初始化
}
break;
case WM_COMMAND:
{
custommessage.commonvariables.wmId = LOWORD(wParam);
custommessage.commonvariables.wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch(custommessage.commonvariables.wmId)
{
case IDB_WNDPROC_SEARCHALLDLGDOWN:
{
custommessage.commonvariables.hSearchWnd = CreateDialog(custommessage.commonvariables.hInst, MAKEINTRESOURCE(IDD_DIALOG_ALLSEARCH), 0, (DLGPROC)AllsearchProc); // hWnd也不成
ShowWindow(custommessage.commonvariables.hSearchWnd, SW_SHOW);
}
break;
case IDM_EXIT:
{
DestroyWindow(hWnd);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
custommessage.commonvariables.hdc = BeginPaint(hWnd, &custommessage.commonvariables.ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &custommessage.commonvariables.ps);
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

LRESULT CALLBACK AllsearchProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
custommessage.InitializationSearchControl(hWnd); // 控件初始化
}
break;
case WM_COMMAND:
{
custommessage.commonvariables.wmId = LOWORD(wParam);
custommessage.commonvariables.wmEvent = HIWORD(wParam);
SetFocus(hWnd);
// Parse the menu selections:
switch(custommessage.commonvariables.wmId)
{
case IDB_SEARCH_ALLSEARCH:
{
DestroyWindow(hWnd);
hWnd = NULL;
}
break;
default:
return FALSE;
}
}
break;
case WM_PAINT:
{
custommessage.commonvariables.hdc = BeginPaint(hWnd, &custommessage.commonvariables.ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &custommessage.commonvariables.ps);
}
break;
case WM_SYSCOMMAND:
{
if(wParam == SC_CLOSE)
{
DestroyWindow(hWnd);
hWnd = NULL;
}
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
default:
return FALSE; // 未处理的消息
}
return TRUE; // 处理过的消息
}



现在需要直接加载RC资源中的对话框,因此

custommessage.commonvariables.hMainWnd = CreateDialog(custommessage.commonvariables.hInst, MAKEINTRESOURCE(IDD_DIALOG_WNDPROC), 0, (DLGPROC)WndProc);


在回掉函数WndProc中,点击高级搜索后弹出搜索的对话框,

case IDB_WNDPROC_SEARCHALLDLGDOWN:
{
custommessage.commonvariables.hSearchWnd = CreateDialog(custommessage.commonvariables.hInst, MAKEINTRESOURCE(IDD_DIALOG_ALLSEARCH), 0, (DLGPROC)AllsearchProc); // hWnd也不成
ShowWindow(custommessage.commonvariables.hSearchWnd, SW_SHOW);
}
break;


其中AllsearchProc与WndProc所对应的两个对话框不是父子关系,而是同等关系。但是点击AllsearchProc中的关闭按钮、移动、点击搜索按钮

case IDB_SEARCH_ALLSEARCH:
{
DestroyWindow(hWnd);
hWnd = NULL;
}
break;


都不响应消息。
而且我也用WM_SYSCOMMAND来实现关闭操作,仍然没反应。

case WM_SYSCOMMAND:
{
if(wParam == SC_CLOSE)
{
DestroyWindow(hWnd);
hWnd = NULL;
}
}
break;


不知道为什么.
I_ask_who 2012-11-01
  • 打赏
  • 举报
回复
wndclass.lpfnWndProc的参数决定了是一类窗口接收到信息而不是一个,所以在WndProc中没有本窗口的概念。WM_DESTROY应该先于WM_QUIT,而且WM_QUIT会导致GetMessage返回false,而且WM_QUIT应该是你的代码Post发出的
wojiushi3344 2012-11-01
  • 打赏
  • 举报
回复
另外在补充一句,多个消息循环是在一个线程里面的
zsscy 2012-11-01
  • 打赏
  • 举报
回复
我想看下你的代码,QQ发给我。 420163105
wojiushi3344 2012-11-01
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
纯C的win32是main不停做GetMessage,受到消息调用DispatchMessage,这时系统会callback WndProc,在GetMessage和DispatchMessage之间你可以做判断,到了WndProc也有hwnd句柄可以做判断
[/Quote]
对呀,WIN32窗口的处理过程就是这样的。但是有个问题呀,当你创建多个窗口的时候就有很多的消息循环一直在检测消息,当你关闭其中一个窗口的时候如何保证是本窗口的消息循环检测到的WM_QUITE消息,而不是其他窗口的消息循环检测到的消息,然后退出。 哥们我的QQ:513670524.一起讨论一下吧!
wojiushi3344 2012-11-01
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]
贴代码吧
感觉是WndProc里没处理好
例如,弹出MessageBox,消息会被这个MessageBox消息循环捕获
[/Quote]
代码比较的长,如果需要可以加QQ,发给你。
wndproc 里面的窗口句柄为操作的窗口句柄,但是捕获消息并转发消息的消息循环式最后创建的窗口。
wojiushi3344 2012-11-01
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]
最终想达到的效果就是,我关闭的哪个窗口就由哪个窗口来捕获消息。现在的问题是就是所有消息都被最后创建的窗口捕获了。在线等大家的结果!!


想看你窗1和窗体2的建立过程。
应该是WndProc先收到消息吧。然后转发子窗体。
[/Quote]

先创建窗口1,然后创建窗口2.2个窗口没有任何的依赖关系。WndProc这个收到消息也是由消息循环转发过来的呀,现在问题就是所有窗口的消息都被最后创建的窗口给捕获了,如果你关闭的不是最后创建的窗口那么就收不消息,最后窗口就退不出来。
stjay 2012-11-01
  • 打赏
  • 举报
回复
贴代码吧
感觉是WndProc里没处理好
例如,弹出MessageBox,消息会被这个MessageBox消息循环捕获
I_ask_who 2012-11-01
  • 打赏
  • 举报
回复
纯C的win32是main不停做GetMessage,受到消息调用DispatchMessage,这时系统会callback WndProc,在GetMessage和DispatchMessage之间你可以做判断,到了WndProc也有hwnd句柄可以做判断
傻X 2012-11-01
  • 打赏
  • 举报
回复
最终想达到的效果就是,我关闭的哪个窗口就由哪个窗口来捕获消息。现在的问题是就是所有消息都被最后创建的窗口捕获了。在线等大家的结果!!


想看你窗1和窗体2的建立过程。
应该是WndProc先收到消息吧。然后转发子窗体。
I_ask_who 2012-11-01
  • 打赏
  • 举报
回复
可以创建一个无效窗口map全局变量,关闭一个窗口往里面添加一个hwnd,凡是在里面hwnd的就是过期的
wojiushi3344 2012-11-01
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
MSG结构有hwnd成员,可以在DispatchMessage之前比较一下,已经过期的扔掉或者交给DefWindowProc
[/Quote]
请问过期是什么意思?
I_ask_who 2012-11-01
  • 打赏
  • 举报
回复
MSG结构有hwnd成员,可以在DispatchMessage之前比较一下,已经过期的扔掉或者交给DefWindowProc
Dobzhansky 2012-11-01
  • 打赏
  • 举报
回复
同一个线程中的消息循环好比栈,
一个一个的建立, 反着一个一个的退出

如果在最后一个消息循环时, 还有多个窗口

那么窗口关闭时, 向消息发送 Quit Message 的就是主窗口

窗口关闭时判断自己是不是最后一个,
再觉得是否 PostQuitMessage/
schlafenhamster 2012-11-01
  • 打赏
  • 举报
回复
给我们看看 create

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧