简体   繁体   English

等价于MFC Windows的OnFinalMessage吗?

[英]Equivalent of OnFinalMessage for MFC windows?

ATL CWindow class has a useful virtual method OnFinalMessage which is called after the last window message for the window is processed - at this point it is safe to destroy or deleted any objects associated with the window. ATL CWindow类具有一个有用的虚拟方法OnFinalMessage ,在处理该窗口的最后一个窗口消息之后将调用该方法-此时可以安全地销毁或删除与该窗口关联的任何对象。 Is there any equivalent for windows derived from the MFC CWnd class? 从MFC CWnd类派生的Windows是否有等效的窗口?

PostNcDestroy() is what you're looking for. 您正在寻找PostNcDestroy()

By the way, if you're implementing a modeless dialog and are looking for where to "delete this;", PostNcDestroy() is the place. 顺便说一句,如果您要实现无模式对话框,并且正在寻找“删除此内容”的位置,那么PostNcDestroy()就是这里。

This answer describes how I eventually solved my problem. 这个答案描述了我最终如何解决我的问题。 I'll note that while the answer by John Dibling was helpful, this was not the final solution to my problem. 我会注意到,尽管John Dibling的回答很有帮助,但这并不是解决我的问题的最终方法。 This is because the WM_NC_DESTROY message is sent as the final message to the window, but this can be handled before the last message to the window has finished being handled. 这是因为WM_NC_DESTROY消息是作为最终消息发送到窗口的,但是可以在完成对窗口的最后一条消息之前对其进行处理。 See for example http://support.microsoft.com/?kbid=202110 for an explanation of the problem. 请参阅例如http://support.microsoft.com/?kbid=202110 ,以获取有关该问题的说明。

  1. DialogProc() is called with WM_CLOSE. 使用WM_CLOSE调用DialogProc()。
  2. ProcessWindowMessage() calls your WM_CLOSE handler. ProcessWindowMessage()调用WM_CLOSE处理程序。
  3. In your WM_CLOSE handler, you call DestroyWindow(). 在WM_CLOSE处理程序中,调用DestroyWindow()。
  4. This ends up calling DialogProc again with WM_NCDESTROY. 这样最终用WM_NCDESTROY再次调用DialogProc。
  5. ProcessWindowMessage() calls your WM_NCDESTROY handler. ProcessWindowMessage()调用您的WM_NCDESTROY处理程序。
  6. You call "delete this" in your WM_NCDESTROY handler. 您在WM_NCDESTROY处理程序中调用“删除此”。

After having called delete this , the object is no longer valid, but you are still technically in the WM_CLOSE handler so you will probably crash when you eventually get back there. 调用delete this ,该对象不再有效,但是从技术上讲,您仍然在WM_CLOSE处理程序中,因此当您最终回到那里时,可能会崩溃。 This means it is not really safe to assume that you can do delete this in PostNcDestroy, since the object may still be live in some other stack frame. 这意味着假设您确实可以在PostNcDestroy中delete this它并不安全,因为该对象可能仍然存在于其他堆栈框架中。

/// 
/// A window designed to allow any window to use the "OnFinalMessage" method from the ATL CWindow class
/// You must call SubclassWindow for this instance so that the window procedure runs
template<class T>
class FinalMessageWindow : public CWindowImpl<FinalMessageWindow<T> >
{
    T *_t; /// The object wanting to receive the final message notification
public:
    BEGIN_MSG_MAP(FinalMessageWindow<T>)
    END_MSG_MAP()

    /// 
    /// The constructor
    /// \param t The object that wants to get the OnFinalMessage notification
    FinalMessageWindow(T *t)
        : _t(t)
    {
    }

    /// 
    /// Called when the final window message for the window has been processed - this is often a good time to delete the object
    /// \param hWnd The window handle
    virtual void OnFinalMessage(HWND hWnd)
    {
        _t->OnFinalMessage(hWnd);
    }
};

I created the above class, note that it is derived from the ATL CWindow class - this allows me to use the OnFinalMessage handler for this class. 我创建了上面的类,请注意,它是从ATL CWindow类派生的-这使我可以对该类使用OnFinalMessage处理程序。 The OnFinalMessage handler is different from the PostNcDestroy in MFC windows in that it is guaranteed to be called only after the final message handler on the stack has completed. OnFinalMessage处理程序与MFC窗口中的PostNcDestroy的不同之处在于,它保证仅在堆栈上的最终消息处理程序完成后才被调用。

We then use window subclassing to insert this window as the window procedure for my own window: 然后,我们使用窗口子类化将此窗口作为我自己窗口的窗口过程插入:

// roughly speaking
FinalMessageWindow<MyWindow> _finalMessageWindow(this);
finalMessageWindow.SubclassWindow(m_hWnd);

Then we implement the OnFinalMessage handler for our window: 然后,我们为窗口实现OnFinalMessage处理程序:

void MyWindow::OnFinalMessage(HWND hWnd)
{
    delete this;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM