子窗口没有收到 WM_DESTROY?

Posted

技术标签:

【中文标题】子窗口没有收到 WM_DESTROY?【英文标题】:Child windows does not receive WM_DESTROY? 【发布时间】:2014-05-27 11:16:24 【问题描述】:

我将winapi CreateWindowEx 打包成一个简单的类。由于每个窗口都共享同一个 wndProc(hwnd,msg,wparam,lparam),所以我将 CreateWindowEx 创建的每个窗口都放到一个 map 中来分发 msg,如下所示:

wndProc(hwnd, msg, wparam, lparam)
    if(map[hwnd]!=nil)
        switch(msg)
            map[hwnd].wndProc(...)
        
    

并且每次销毁一个窗口或其父窗口时,将其从地图中移除:

case WM_DESTROY: delete(map, hwnd)

但是按钮之类的东西不接收 WM_DESTROY。我在 WM_NOTIFY 和 WM_COMMAND 中打印了所有味精,但我注意到了。

那么我怎样才能在正确的时间从地图中移除那些子窗口呢?或者在不创建 hwnd 映射的情况下分发 msg 的方法?

【问题讨论】:

【参考方案1】:

他们肯定确实收到了这条信息。但他们的窗口过程在 Windows 内部,而不是在您的程序内部。所以你永远看不到它。您可以在MSDN documentation 中阅读一些内容,请注意 WM_DESTROY 没有得到任何特殊处理。也不会生成您的父窗口可以看到的通知。

当您看到父窗口被破坏时,不会自动删除所有子窗口,subclassing controls 是 C++ 类库包装器的一个非常标准的要求。顺便说一句,最好不要自己发明,这已经做过很多次了。

【讨论】:

【参考方案2】:

那么我怎样才能在正确的时间从地图中移除那些子窗口呢?

您必须使用SetWindowLongPtr(GWL_WNDPROC)SetWindowSubClass() 对您创建的每个窗口进行子类化,然后您将收到所有WM_DESTROY 消息。

或者一种不创建 hwnd 映射的方式分发 msg?

像 ATL 和 VCL 这样的框架通过为每个窗口动态分配一个 thunk 并将对象指针放在 thunk 中,然后将 thunk 用作窗口过程来处理这个问题。这样,每当调用 thunk 时,它都会将消息直接传递给其关联对象。

【讨论】:

以上是关于子窗口没有收到 WM_DESTROY?的主要内容,如果未能解决你的问题,请参考以下文章

WM_DESTROY没有在包装的WndProc中调用

winapi查找网页对话框的子窗口标题(属性)

SetFocus 到父窗口,然后回到子窗口

Qt学习3---子窗口与父窗口

WinForms:如何确定窗口是不是不再活动(没有子窗口有焦点)?

使子窗口出现在任务栏中