1

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

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

此消息首先发送到正在销毁的窗口,然后在子窗口(如果有)被销毁时发送到它们。

有人知道发生了什么吗?

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

谢谢,保罗

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
4

2 回答 2

0

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

无论如何,您的代码不会在重新创建时断言:

virtual void CMyView::OnFinalMessage(HWND)
{
    some_control_.m_hWnd = 0;
}
于 2010-03-06T01:36:15.410 回答
0

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

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

于 2009-12-09T14:50:09.503 回答