From 7e25f59e48c3ee93fcb54aa7fca1fd51628c2fac Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 25 May 2002 13:02:58 +0000 Subject: [PATCH] prevent the parent window from losing activation when a popup is shown git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15662 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/msw/popupwin.h | 15 ++++++++++++++ include/wx/msw/toplevel.h | 9 ++++++++- include/wx/popupwin.h | 4 +++- src/msw/frame.cpp | 2 +- src/msw/popupwin.cpp | 42 +++++++++++++++++++++++++++++++++++++++ src/msw/toplevel.cpp | 40 +++++++++++++++++++++++++++++++++++++ src/msw/window.cpp | 32 ++++++++++------------------- 7 files changed, 119 insertions(+), 25 deletions(-) diff --git a/include/wx/msw/popupwin.h b/include/wx/msw/popupwin.h index 3ec588a476..9147f5bac1 100644 --- a/include/wx/msw/popupwin.h +++ b/include/wx/msw/popupwin.h @@ -30,11 +30,26 @@ public: bool Create(wxWindow *parent, int flags = wxBORDER_NONE); + // implementation only from now on + // ------------------------------- + + // override Show() to prevent wxPopupWindow from being activated + virtual bool Show(bool show = TRUE); + + // find a shown popup window with the given window as parent, return NULL + // if none + static wxPopupWindow *FindPopupFor(wxWindow *win); + protected: + // popups handle the position like wxTopLevelWindow, not wxWindow virtual void DoGetPosition(int *x, int *y) const; + // return the style to be used for the popup windows virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle) const; + // the list of all currently shown popup windows used by FindPopupFor() + static wxWindowList ms_shownPopups; + DECLARE_DYNAMIC_CLASS(wxPopupWindow) }; diff --git a/include/wx/msw/toplevel.h b/include/wx/msw/toplevel.h index 85bf00c072..5db5199e47 100644 --- a/include/wx/msw/toplevel.h +++ b/include/wx/msw/toplevel.h @@ -89,10 +89,17 @@ protected: // common part of Iconize(), Maximize() and Restore() void DoShowWindow(int nShowCmd); + // prevent the window from being deactivated sometimes (see comments in the + // code) + long HandleNcActivate(bool activate); + // translate wxWindows flags to Windows ones virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle) const; - // is the frame currently iconized? + // we handle WM_NCACTIVATE specially here + virtual long MSWWindowProc(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam); + + // is the window currently iconized? bool m_iconized; // should the frame be maximized when it will be shown? set by Maximize() diff --git a/include/wx/popupwin.h b/include/wx/popupwin.h index 63c4d65eea..b4558ee4d4 100644 --- a/include/wx/popupwin.h +++ b/include/wx/popupwin.h @@ -86,8 +86,10 @@ public: // hide the window virtual void Dismiss(); - + // can the window be dismissed now? + // + // VZ: where is this used?? virtual bool CanDismiss() { return TRUE; } diff --git a/src/msw/frame.cpp b/src/msw/frame.cpp index 99f1e9c763..98c8c7eacd 100644 --- a/src/msw/frame.cpp +++ b/src/msw/frame.cpp @@ -841,7 +841,7 @@ long wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) } if ( !processed ) - rc = wxWindow::MSWWindowProc(message, wParam, lParam); + rc = wxFrameBase::MSWWindowProc(message, wParam, lParam); return rc; } diff --git a/src/msw/popupwin.cpp b/src/msw/popupwin.cpp index ab65556566..87d82460ca 100644 --- a/src/msw/popupwin.cpp +++ b/src/msw/popupwin.cpp @@ -35,6 +35,8 @@ #include "wx/msw/private.h" // for WS_CHILD and WS_POPUP +wxWindowList wxPopupWindow::ms_shownPopups; + // ============================================================================ // implementation // ============================================================================ @@ -76,3 +78,43 @@ WXDWORD wxPopupWindow::MSWGetStyle(long flags, WXDWORD *exstyle) const return style; } +bool wxPopupWindow::Show(bool show) +{ + // skip wxWindow::Show() which calls wxBringWindowToTop(): this results in + // activating the popup window and stealing the atcivation from our parent + // which means that the parent frame becomes deactivated when opening a + // combobox, for example -- definitely not what we want + if ( !wxWindowBase::Show(show) ) + return FALSE; + + if ( show ) + { + ms_shownPopups.Append(this); + } + else // remove from the shown list + { + ms_shownPopups.DeleteObject(this); + } + + ::ShowWindow(GetHwnd(), show ? SW_SHOWNOACTIVATE : SW_HIDE); + + return TRUE; +} + +/* static */ +wxPopupWindow *wxPopupWindow::FindPopupFor(wxWindow *winParent) +{ + // find a popup with the given parent in the linked list of all shown + // popups + for ( wxWindowList::Node *node = ms_shownPopups.GetFirst(); + node; + node = node->GetNext() ) + { + wxWindow *win = node->GetData(); + if ( win->GetParent() == winParent ) + return (wxPopupWindow *)win; + } + + return NULL; +} + diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 8283ec20d6..83c019347d 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -39,6 +39,8 @@ #include "wx/msw/private.h" +#include "wx/popupwin.h" + #ifndef ICON_BIG #define ICON_BIG 1 #endif @@ -653,3 +655,41 @@ bool wxTopLevelWindowMSW::EnableCloseButton(bool enable) return TRUE; } +// ---------------------------------------------------------------------------- +// wxTopLevelWindowMSW message processing +// ---------------------------------------------------------------------------- + +long wxTopLevelWindowMSW::HandleNcActivate(bool activate) +{ +#if wxUSE_POPUPWIN + /* + Normally, when another top level (whether it is overlapped or popup) + window is shown, it is activated and the parent window (i.e. we) loses + the activation. This, however, looks very ugly when the child window is + a [custom] combobox which we implement using a popup window as surely + opening a combobox shouldn't result in deactivating the parent window. + + So we don't redraw the title bar in this case, even if we still return + TRUE to let the change of activation to take place as otherwise the + controls inside the popup window wouldn't work properly. + */ + if ( !activate && wxPopupWindow::FindPopupFor(this) ) + { + return TRUE; + } +#endif // wxUSE_POPUPWIN + + return FALSE; +} + +long +wxTopLevelWindowMSW::MSWWindowProc(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam) +{ + if ( msg == WM_NCACTIVATE && HandleNcActivate(wParam != 0) ) + { + // we processed WM_NCACTIVATE ourselves + return TRUE; + } + + return wxTopLevelWindowBase::MSWWindowProc(msg, wParam, lParam); +} diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 19ee42d586..ebd05bfd52 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -2918,31 +2918,19 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, wxWindow *parent = GetParent(); bool isChild = (style & WS_CHILD) != 0; HWND hParent; - if ( GetWindowStyleFlag() & wxPOPUP_WINDOW ) + if ( (isChild || HasFlag(wxPOPUP_WINDOW) || HasFlag(wxFRAME_TOOL_WINDOW)) ) { - // popup windows should have desktop as parent because they shouldn't - // be limited to the parents client area as child windows usually are - hParent = ::GetDesktopWindow(); + // this is either a normal child window, a popup window or a top level + // window with wxFRAME_TOOL_WINDOW style (see below) + hParent = parent ? GetHwndOf(parent) : NULL; } - else // !popup + else { - if ( (isChild || HasFlag(wxFRAME_TOOL_WINDOW)) && parent ) - { - // this is either a normal child window or a top level window with - // wxFRAME_TOOL_WINDOW style (see below) - hParent = GetHwndOf(parent); - } - else - { - // this is either a window for which no parent was specified (not - // much we can do then) or a frame without wxFRAME_TOOL_WINDOW - // style: we should use NULL parent HWND for it 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 special - // wxFRAME_TOOL_WINDOW as above) - hParent = NULL; - } - + // this is a frame without wxFRAME_TOOL_WINDOW style: we should use + // NULL parent HWND for it 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 special wxFRAME_TOOL_WINDOW as above) + hParent = NULL; } // controlId is menu handle for the top level windows, so set it to 0 -- 2.47.2