我有一个适用于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
答案 0 :(得分:0)
我不是百分百肯定,但似乎some_control_ CEdit控件未在父窗口中注册。我想你需要用父句柄作为参数调用some_control_.Create(...)。
有关CEdit::Create()的文档,请参阅msdn文章。
答案 1 :(得分:0)
创建,销毁和重新创建同一个窗口不是一个好习惯,您应该考虑隐藏它并在再次显示时重新初始化您的内容。
无论如何,你的代码不会在重新创建时使用:
virtual void CMyView::OnFinalMessage(HWND)
{
some_control_.m_hWnd = 0;
}