From a275e42188dc124f6eab7e381fa650182f88154c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 2 Oct 2002 23:32:23 +0000 Subject: [PATCH] delete the hidden TLW parent window from a module to ensure that it is done even if OnInit() returns FALSE; also create it without using wxTLW itself which actually simplifies the code git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@17442 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/msw/toplevel.h | 4 - src/msw/toplevel.cpp | 160 +++++++++++++++++++++++++++----------- 2 files changed, 116 insertions(+), 48 deletions(-) diff --git a/include/wx/msw/toplevel.h b/include/wx/msw/toplevel.h index d09a48ce0a..202983d285 100644 --- a/include/wx/msw/toplevel.h +++ b/include/wx/msw/toplevel.h @@ -119,10 +119,6 @@ protected: // the last focused child: we restore focus to it on activation wxWindow *m_winLastFocused; - // the hidden parent window for the frames which shouldn't appear in the - // taskbar - static wxWindow *ms_hiddenParent; - DECLARE_EVENT_TABLE() }; diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 6d5605551f..d046ea5279 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -76,8 +76,30 @@ wxWindowList wxModelessWindows; // the name of the default wxWindows class extern const wxChar *wxCanvasClassName; -// the hidden parent for wxFRAME_NO_TASKBAR unowned frames -wxWindow *wxTopLevelWindowMSW::ms_hiddenParent = NULL; +// ---------------------------------------------------------------------------- +// wxTLWHiddenParentModule: used to manage the hidden parent window (we need a +// module to ensure that the window is always deleted) +// ---------------------------------------------------------------------------- + +class wxTLWHiddenParentModule : public wxModule +{ +public: + // module init/finalize + virtual bool OnInit(); + virtual void OnExit(); + + // get the hidden window (creates on demand) + static HWND GetHWND(); + +private: + // the HWND of the hidden parent + static HWND ms_hwnd; + + // the class used to create it + static const wxChar *ms_className; + + DECLARE_DYNAMIC_CLASS(wxTLWHiddenParentModule) +}; // ============================================================================ // wxTopLevelWindowMSW implementation @@ -213,38 +235,32 @@ WXHWND wxTopLevelWindowMSW::MSWGetParent() const // parent HWND or it would be always on top of its parent which is not what // we usually want (in fact, we only want it for frames with the // wxFRAME_FLOAT_ON_PARENT flag) - wxWindow *parent; + HWND hwndParent = NULL; if ( HasFlag(wxFRAME_FLOAT_ON_PARENT) ) { - parent = GetParent(); + const wxWindow *parent = GetParent(); - // this flag doesn't make sense then and will be ignored - wxASSERT_MSG( parent, - _T("wxFRAME_FLOAT_ON_PARENT but no parent?") ); - } - else // don't float on parent, must not be owned - { - parent = NULL; + if ( !parent ) + { + // this flag doesn't make sense then and will be ignored + wxFAIL_MSG( _T("wxFRAME_FLOAT_ON_PARENT but no parent?") ); + } + else + { + hwndParent = GetHwndOf(parent); + } } + //else: don't float on parent, must not be owned // now deal with the 2nd taskbar-related problem (see comments above in // MSWGetStyle()) - if ( HasFlag(wxFRAME_NO_TASKBAR) && !parent ) + if ( HasFlag(wxFRAME_NO_TASKBAR) && !hwndParent ) { - if ( !ms_hiddenParent ) - { - ms_hiddenParent = new wxTopLevelWindowMSW(NULL, -1, _T("")); - - // we shouldn't leave it in wxTopLevelWindows or we wouldn't - // terminate the app when the last user-created frame is deleted -- - // see ~wxTopLevelWindowMSW - wxTopLevelWindows.DeleteObject(ms_hiddenParent); - } - - parent = ms_hiddenParent; + // use hidden parent + hwndParent = wxTLWHiddenParentModule::GetHWND(); } - return parent ? parent->GetHWND() : WXHWND(NULL); + return (WXHWND)hwndParent; } bool wxTopLevelWindowMSW::CreateDialog(const void *dlgTemplate, @@ -451,15 +467,6 @@ bool wxTopLevelWindowMSW::Create(wxWindow *parent, wxTopLevelWindowMSW::~wxTopLevelWindowMSW() { - if ( this == ms_hiddenParent ) - { - // stop [infinite] recursion which would otherwise happen when we do - // "delete ms_hiddenParent" below -- and we're not interested in doing - // anything of the rest below for that window because the rest of - // wxWindows doesn't even know about it - return; - } - if ( wxModelessWindows.Find(this) ) wxModelessWindows.DeleteObject(this); @@ -475,17 +482,6 @@ wxTopLevelWindowMSW::~wxTopLevelWindowMSW() ::BringWindowToTop(GetHwndOf(parent)); } } - - // if this is the last top-level window, we're going to exit and we should - // delete ms_hiddenParent now to avoid leaking it - if ( IsLastBeforeExit() ) - { - if ( ms_hiddenParent ) - { - delete ms_hiddenParent; - ms_hiddenParent = NULL; - } - } } // ---------------------------------------------------------------------------- @@ -796,3 +792,79 @@ wxDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) } } +// ============================================================================ +// wxTLWHiddenParentModule implementation +// ============================================================================ + +HWND wxTLWHiddenParentModule::ms_hwnd = NULL; + +const wxChar *wxTLWHiddenParentModule::ms_className = NULL; + +bool wxTLWHiddenParentModule::OnInit() +{ + ms_hwnd = NULL; + ms_className = NULL; + + return TRUE; +} + +void wxTLWHiddenParentModule::OnExit() +{ + if ( ms_hwnd ) + { + if ( !::DestroyWindow(ms_hwnd) ) + { + wxLogLastError(_T("DestroyWindow(hidden TLW parent)")); + } + + ms_hwnd = NULL; + } + + if ( ms_className ) + { + if ( !::UnregisterClass(ms_className, wxGetInstance()) ) + { + wxLogLastError(_T("UnregisterClass(\"wxTLWHiddenParent\")")); + } + + ms_className = NULL; + } +} + +/* static */ +HWND wxTLWHiddenParentModule::GetHWND() +{ + if ( !ms_hwnd ) + { + if ( !ms_className ) + { + static const wxChar *HIDDEN_PARENT_CLASS = _T("wxTLWHiddenParent"); + + WNDCLASS wndclass; + wxZeroMemory(wndclass); + + wndclass.lpfnWndProc = DefWindowProc; + wndclass.hInstance = wxGetInstance(); + wndclass.lpszClassName = HIDDEN_PARENT_CLASS; + + if ( !::RegisterClass(&wndclass) ) + { + wxLogLastError(_T("RegisterClass(\"wxTLWHiddenParent\")")); + } + else + { + ms_className = HIDDEN_PARENT_CLASS; + } + } + + ms_hwnd = ::CreateWindow(ms_className, _T(""), 0, 0, 0, 0, 0, NULL, + (HMENU)NULL, wxGetInstance(), NULL); + if ( !ms_hwnd ) + { + wxLogLastError(_T("CreateWindow(hidden TLW parent)")); + } + } + + return ms_hwnd; +} +