2009-11-11 3 views
1

У меня есть приложение WTL 8.0 SDI для Windows Mobile 5. В этом надуманном примере ниже я создаю представление, уничтожаю его, а затем повторно создаю. Но при повторном создании утверждений в обработчике WM_INITDIALOG происходит сбой, поскольку HWND элемента управления недействителен.по умолчанию WM_DESTROY неправильно очищает дочерние окна

Я отмечаю, что могу исправить это, обработав WM_DESTROY в CMyView и уничтожив каждый дочерний элемент вручную. Но я не думал, что должен. MSDN even says:

Это сообщение посылается первым в окно уничтожается, а затем в дочерние окна (если таковые имеются), поскольку они уничтожены.

У кого-нибудь есть идея, что происходит?

Редактировать: Если я обрабатываю WM_NCDESTROY в CMyView, все дочерние элементы управления все еще действительны! (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

Неправильная практика создания, уничтожения и повторного создания одного и того же окна, вам следует рассмотреть возможность скрытия и повторной инициализации содержимого при его повторном отображении.

В любом случае ваш код не будет УТВЕРЖДАТЬ при воссоздании с:

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

Спасибо за помощь. Что делает эту «неправдоподобную практику»? – PaulH

+0

Принципиально, потому что создание и уничтожение окна - это система, требующая операции. Практически потому, что ATL :: CWindowImpl неправильно обрабатывает его, поэтому у нас есть дополнительная работа :-) –

0

Я не сто процентов уверен, но кажется, что контроль some_control_ CEdit не зарегистрирован с родительское окно. Я думаю, вам нужно будет вызвать some_control_.Create (...) с родительским дескриптором в качестве параметра.

см. Статью msdn для документации CEdit::Create().

+0

Это сделано по той части я имею как «Message Map и другие стандартные макросы WTL». Предполагалось включить DDX_MAP, который бы справился с этим. – PaulH