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
This commit is contained in:
Vadim Zeitlin 2002-05-25 13:02:58 +00:00
parent d45bc43695
commit 7e25f59e48
7 changed files with 119 additions and 25 deletions

View File

@ -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)
};

View File

@ -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()

View File

@ -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; }

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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