ATL CWindow 类有一个有用的虚方法OnFinalMessage
,它在处理完窗口的最后一个窗口消息后调用——此时销毁或删除与窗口关联的任何对象是安全的。从 MFC 类派生的窗口是否有任何等价物CWnd
?
2 回答
PostNcDestroy()是您正在寻找的。
顺便说一句,如果您正在实现一个无模式对话框并且正在寻找“删除它”的位置,那么 PostNcDestroy() 就是该位置。
这个答案描述了我最终如何解决我的问题。我会注意到,虽然 John Dibling 的回答很有帮助,但这并不是我问题的最终解决方案。这是因为 WM_NC_DESTROY 消息作为最终消息发送到窗口,但这可以在窗口的最后一条消息完成处理之前处理。有关问题的解释,请参见例如http://support.microsoft.com/?kbid=202110。
- DialogProc() 使用 WM_CLOSE 调用。
- ProcessWindowMessage() 调用您的 WM_CLOSE 处理程序。
- 在您的 WM_CLOSE 处理程序中,您调用 DestroyWindow()。
- 这最终使用 WM_NCDESTROY 再次调用 DialogProc。
- ProcessWindowMessage() 调用您的 WM_NCDESTROY 处理程序。
- 您在 WM_NCDESTROY 处理程序中调用“删除这个”。
调用 后delete this
,对象不再有效,但从技术上讲,您仍处于WM_CLOSE
处理程序中,因此当您最终回到那里时,您可能会崩溃。这意味着假设您可以在 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);
}
};
我创建了上面的类,注意它是从 ATL CWindow 类派生的——这允许我为这个类使用 OnFinalMessage 处理程序。OnFinalMessage 处理程序与 MFC 窗口中的 PostNcDestroy 不同,它保证仅在堆栈上的最终消息处理程序完成后才被调用。
然后我们使用窗口子类来插入这个窗口作为我自己的窗口的窗口过程:
// roughly speaking
FinalMessageWindow<MyWindow> _finalMessageWindow(this);
finalMessageWindow.SubclassWindow(m_hWnd);
然后我们为我们的窗口实现 OnFinalMessage 处理程序:
void MyWindow::OnFinalMessage(HWND hWnd)
{
delete this;
}