默认WM_DESTROY没有正确清理子窗口

时间:2009-11-11 22:13:35

标签: c++ winapi wtl

我有一个适用于Windows Mobile 5的WTL 8.0 SDI应用程序。在下面的这个设计示例中,我创建了一个视图,将其销毁,然后重新创建它。但是,当它重新创建WM_INITDIALOG处理程序中的断言失败时,因为控件的HWND无效。

我注意到我可以通过在CMyView中处理WM_DESTROY并手动销毁每个子控件来解决这个问题。但是,我认为不应该这样做。 MSDN even says

  

此消息首先发送到   窗户被摧毁然后到了   儿童窗户(如果有的话)   破坏。

有人知道发生了什么事吗?

编辑:如果我在CMyView中处理WM_NCDESTROY,所有子控件句柄仍然有效! (some_control_.IsWindow()==TRUE)那不是应该如何......

谢谢, PaulH

class CMyView : public CDialogImpl< CMyView >,
                public CWinDataExchange< CMyView >
{
    // <snip> Message Map and other standard WTL macros </snip>

    LRESULT OnInitDialog( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/ )
    {
        DoDataExchange( FALSE );
        // assertion fails within the SetWindowText() call
        // atlwin.h line 876
        // ATLASSERT(::IsWindow(m_hWnd));
        some_control_.SetWindowText( _T( "Foo" ) );
        return 0;
    };

private:
    CEdit some_control_;
}; // class CMyView

class CMainFrame : public CFrameWindowImpl< CMainFrame >, 
                   public CUpdateUI< CMainFrame >,
                   public CMessageFilter, 
                   public CIdleHandler
{
public:
    // <snip> Message Map and other standard WTL macros </snip>

    BOOL CMainFrame::PreTranslateMessage( MSG* pMsg )
    {
        if( CFrameWindowImpl< CMainFrame >::PreTranslateMessage( pMsg ) )
            return TRUE;

        return my_view_.PreTranslateMessage( pMsg );
    };

    LRESULT OnCreate( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/ )
    {
        CMessageLoop* pLoop = _Module.GetMessageLoop();
        ATLASSERT( pLoop != NULL );
        pLoop->AddMessageFilter( this );
        pLoop->AddIdleHandler( this );

        m_hWndClient = my_view_.Create( m_hWnd );
        my_view_.DestroyWindow();
        m_hWndClient = my_view_.Create( m_hWnd );
    };

private:
    CMyView my_view_;
}; // class CMainFrame

2 个答案:

答案 0 :(得分:0)

我不是百分百肯定,但似乎some_control_ CEdit控件未在父窗口中注册。我想你需要用父句柄作为参数调用some_control_.Create(...)。

有关CEdit::Create()的文档,请参阅msdn文章。

答案 1 :(得分:0)

创建,销毁和重新创建同一个窗口不是一个好习惯,您应该考虑隐藏它并在再次显示时重新初始化您的内容。

无论如何,你的代码不会在重新创建时使用:

virtual void CMyView::OnFinalMessage(HWND)
{
    some_control_.m_hWnd = 0;
}