Add wxPU_CONTAINS_CONTROLS style for wxPopupWindow
This restores the default behavior of a popup window in MSW to the
behavior it had before 56c4191168
. The new
flag added by this commit can be used to give the popup window the
behavior from after that commit, i.e. choose the implementation using a
WS_POPUP window rather than the default one using a WS_CHILD of the
desktop.
The old behavior kept the popup from taking focus from its parent window
but left some controls not working. The new behavior has the popup take
focus and lets all controls work.
Closes https://github.com/wxWidgets/wxWidgets/pull/1123
This commit is contained in:
committed by
Vadim Zeitlin
parent
8deb2cf0bb
commit
07f64c3b75
@@ -25,11 +25,15 @@ public:
|
||||
|
||||
bool Create(wxWindow *parent, int flags = wxBORDER_NONE);
|
||||
|
||||
virtual void SetFocus() wxOVERRIDE;
|
||||
virtual bool Show(bool show = true) wxOVERRIDE;
|
||||
|
||||
// return the style to be used for the popup windows
|
||||
virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle) const wxOVERRIDE;
|
||||
|
||||
// get the HWND to be used as parent of this window with CreateWindow()
|
||||
virtual WXHWND MSWGetParent() const wxOVERRIDE;
|
||||
|
||||
|
||||
// Implementation only from now on.
|
||||
|
||||
|
@@ -15,6 +15,15 @@
|
||||
|
||||
#if wxUSE_POPUPWIN
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxPopupWindow specific flags
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// This flag can be used in MSW if some controls are not working with the
|
||||
// default popup style.
|
||||
#define wxPU_CONTAINS_CONTROLS 0x0001
|
||||
|
||||
|
||||
#include "wx/nonownedwnd.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -124,6 +133,13 @@ public:
|
||||
wxPopupTransientWindow() { }
|
||||
wxPopupTransientWindow(wxWindow *parent, int style = wxBORDER_NONE)
|
||||
{ Create(parent, style); }
|
||||
bool Create(wxWindow *parent, int style = wxBORDER_NONE)
|
||||
{
|
||||
return wxPopupTransientWindowBase::Create
|
||||
(
|
||||
parent, style | wxPU_CONTAINS_CONTROLS
|
||||
);
|
||||
}
|
||||
|
||||
// Implement base class pure virtuals.
|
||||
virtual void Popup(wxWindow *focus = NULL) wxOVERRIDE;
|
||||
|
@@ -11,6 +11,19 @@
|
||||
A special kind of top level window used for popup menus,
|
||||
combobox popups and such.
|
||||
|
||||
@beginStyleTable
|
||||
@style{wxPU_CONTAINS_CONTROLS}
|
||||
By default in wxMSW, a popup window will not take focus from its parent
|
||||
window. However many standard controls, including common ones such as
|
||||
wxTextCtrl, need focus to function correctly and will not work when
|
||||
placed on a default popup. This flag can be used to make the popup take
|
||||
focus and let all controls work but at the price of not allowing the
|
||||
parent window to keep focus while the popup is shown, which can also be
|
||||
sometimes desirable. This style is currently only implemented in MSW
|
||||
and simply does nothing under the other platforms (it's new since
|
||||
wxWidgets 3.1.3).
|
||||
@endStyleTable
|
||||
|
||||
@library{wxcore}
|
||||
@category{managedwnd}
|
||||
|
||||
|
@@ -64,13 +64,24 @@ WXDWORD wxPopupWindow::MSWGetStyle(long flags, WXDWORD *exstyle) const
|
||||
// we only honour the border flags, the others don't make sense for us
|
||||
WXDWORD style = wxWindow::MSWGetStyle(flags & wxBORDER_MASK, exstyle);
|
||||
|
||||
// We need to be a popup (i.e. not a child) window in order to not be
|
||||
// confined to the parent window area, as is required for a drop down, for
|
||||
// example. Old implementation used WS_CHILD and made this window a child
|
||||
// of the desktop window, but this resulted in problems with handling input
|
||||
// in the popup children, and so was changed to the current version.
|
||||
// wxMSW uses 2 rather different implementations of wxPopupWindow
|
||||
// internally, each one with its own limitations, so we allow specifying
|
||||
// wxPU_CONTAINS_CONTROLS flag to select which one is used. The default is
|
||||
// to use a child window of the desktop for the popup, which is compatible
|
||||
// with the previous wxWidgets versions and works well for simple popups,
|
||||
// but many standard controls can't work as children of such a window
|
||||
// because it doesn't accept focus. So an alternative implementation for
|
||||
// the popups that will contain such controls is available, but this one
|
||||
// has problems due to the fact that it does take focus and not only can
|
||||
// (and does) this break existing code, but it also prevents the parent
|
||||
// window from keeping focus while showing the popup, as must be done when
|
||||
// using auto-completion tooltips, for example. So neither implementation
|
||||
// can be used in all cases and you have to explicitly choose your poison.
|
||||
if ( HasFlag(wxPU_CONTAINS_CONTROLS) )
|
||||
{
|
||||
style &= ~WS_CHILD;
|
||||
style |= WS_POPUP;
|
||||
}
|
||||
|
||||
if ( exstyle )
|
||||
{
|
||||
@@ -81,6 +92,31 @@ WXDWORD wxPopupWindow::MSWGetStyle(long flags, WXDWORD *exstyle) const
|
||||
return style;
|
||||
}
|
||||
|
||||
WXHWND wxPopupWindow::MSWGetParent() const
|
||||
{
|
||||
if ( HasFlag(wxPU_CONTAINS_CONTROLS) )
|
||||
{
|
||||
return wxPopupWindowBase::MSWGetParent();
|
||||
}
|
||||
else
|
||||
{
|
||||
// we must be a child of the desktop to be able to extend beyond the
|
||||
// parent window client area (like the comboboxes drop downs do)
|
||||
return (WXHWND)::GetDesktopWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void wxPopupWindow::SetFocus()
|
||||
{
|
||||
// Focusing on a popup window does not work on MSW unless WS_POPUP style
|
||||
// is set. Since this is only the case if the style wxPU_CONTAINS_CONTROLS
|
||||
// is used, we'll handle the focus in that case and otherwise do nothing.
|
||||
if ( HasFlag(wxPU_CONTAINS_CONTROLS) )
|
||||
{
|
||||
wxPopupWindowBase::SetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
bool wxPopupWindow::Show(bool show)
|
||||
{
|
||||
// It's important to update wxCurrentPopupWindow before showing the window,
|
||||
@@ -88,7 +124,30 @@ bool wxPopupWindow::Show(bool show)
|
||||
// from inside Show() so that it knows to remain [appearing] active.
|
||||
wxCurrentPopupWindow = show ? this : NULL;
|
||||
|
||||
if ( HasFlag(wxPU_CONTAINS_CONTROLS) )
|
||||
{
|
||||
return wxPopupWindowBase::Show(show);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !wxWindowMSW::Show(show) )
|
||||
return false;
|
||||
|
||||
if ( show )
|
||||
{
|
||||
// raise to top of z order
|
||||
if ( !::SetWindowPos(GetHwnd(), HWND_TOP, 0, 0, 0, 0,
|
||||
SWP_NOMOVE | SWP_NOSIZE) )
|
||||
{
|
||||
wxLogLastError(wxT("SetWindowPos"));
|
||||
}
|
||||
|
||||
// and set it as the foreground window so the mouse can be captured
|
||||
::SetForegroundWindow(GetHwnd());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user