Merge branch 'msw-dont-preprocess-unknown'

Don't preprocess messages for unknown windows in wxMSW.

See #23824.
This commit is contained in:
Vadim Zeitlin 2023-09-06 02:41:08 +02:00
commit b3cfab1433
4 changed files with 44 additions and 58 deletions

View file

@ -41,6 +41,8 @@ public:
virtual void SetTitle( const wxString& title) override;
virtual wxString GetTitle() const override;
virtual bool MSWProcessMessage(WXMSG* pMsg) override;
protected:
virtual void DoGetSize(int *width, int *height) const override;
virtual void DoGetClientSize(int *width, int *height) const override;

View file

@ -63,32 +63,10 @@ bool wxGUIEventLoop::PreProcessMessage(WXMSG *msg)
wxWindow *wndThis = wxGetWindowFromHWND((WXHWND)hwnd);
wxWindow *wnd;
// this might happen if we're in a modeless dialog, or if a wx control has
// children which themselves were not created by wx (i.e. wxActiveX control children)
// this might happen a wx control has children which themselves were not
// created by wx (i.e. wxActiveX control children)
if ( !wndThis )
{
while ( hwnd && (::GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD ))
{
hwnd = ::GetParent(hwnd);
// If the control has a wx parent, break and give the parent a chance
// to process the window message
wndThis = wxGetWindowFromHWND((WXHWND)hwnd);
if (wndThis != nullptr)
break;
}
if ( !wndThis )
{
// this may happen if the event occurred in a standard modeless dialog (the
// only example of which I know of is the find/replace dialog) - then call
// IsDialogMessage() to make TAB navigation in it work
// NOTE: IsDialogMessage() just eats all the messages (i.e. returns true for
// them) if we call it for the control itself
return hwnd && ::IsDialogMessage(hwnd, msg) != 0;
}
}
return false;
if ( !AllowProcessing(wndThis) )
{

View file

@ -30,6 +30,10 @@
#include "wx/fdrepdlg.h"
// Use functions from src/msw/window.cpp
extern void wxRemoveHandleAssociation(wxWindowMSW *win);
extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
// ----------------------------------------------------------------------------
// functions prototypes
// ----------------------------------------------------------------------------
@ -334,6 +338,7 @@ wxFindReplaceDialog::~wxFindReplaceDialog()
m_isShown = false;
// and from destroying our window [again]
wxRemoveHandleAssociation(this);
m_hWnd = (WXHWND)nullptr;
}
@ -419,6 +424,7 @@ bool wxFindReplaceDialog::Show(bool show)
}
m_hWnd = (WXHWND)hwnd;
wxAssociateWinWithHandle(m_hWnd, this);
return true;
}
@ -440,6 +446,19 @@ wxString wxFindReplaceDialog::GetTitle() const
return m_title;
}
// ----------------------------------------------------------------------------
// wxFindReplaceDialog message handling
// ----------------------------------------------------------------------------
bool wxFindReplaceDialog::MSWProcessMessage(WXMSG* pMsg)
{
// The base class MSWProcessMessage() doesn't work for us because we don't
// have wxTAB_TRAVERSAL style, but then we don't need it anyhow: as this
// dialog only ever contains standard controls, just using the standard
// function is enough to make TAB navigation work in it.
return m_hWnd && ::IsDialogMessage(m_hWnd, pMsg);
}
// ----------------------------------------------------------------------------
// wxFindReplaceDialog position/size
// ----------------------------------------------------------------------------

View file

@ -291,7 +291,7 @@ void wxTraceMSWMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
#endif // wxDEBUG_LEVEL >= 2
void wxRemoveHandleAssociation(wxWindowMSW *win);
extern void wxRemoveHandleAssociation(wxWindowMSW *win);
extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
// get the text metrics for the current font
@ -7098,44 +7098,31 @@ wxWindow *wxGetActiveWindow()
extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
{
HWND hwnd = (HWND)hWnd;
if ( !hwnd )
return nullptr;
// For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
// by code in msw/radiobox.cpp), for all the others we just search up the
// window hierarchy
wxWindow *win = nullptr;
if ( hwnd )
{
win = wxFindWinFromHandle(hwnd);
if ( !win )
{
// spin control text buddy window should be mapped to spin ctrl
// itself so try it too
wxWindow *win = wxFindWinFromHandle(hwnd);
// spin control text buddy window should be mapped to spin ctrl
// itself so try it too
#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
if ( !win )
{
win = wxSpinCtrl::GetSpinForTextCtrl((WXHWND)hwnd);
}
#endif // wxUSE_SPINCTRL
}
}
while ( hwnd && !win )
if ( !win )
{
// this is a really ugly hack needed to avoid mistakenly returning the
// parent frame wxWindow for the find/replace modeless dialog HWND -
// this, in turn, is needed to call IsDialogMessage() from
// wxApp::ProcessMessage() as for this we must return nullptr from here
//
// FIXME: this is clearly not the best way to do it but I think we'll
// need to change HWND <-> wxWindow code more heavily than I can
// do it now to fix it
win = wxSpinCtrl::GetSpinForTextCtrl((WXHWND)hwnd);
}
#endif // wxUSE_SPINCTRL
while ( !win )
{
// Avoid going beyond the top level window (only they have owner in
// Win32) as we could find its owner wxFrame which would be unwanted.
if ( ::GetWindow(hwnd, GW_OWNER) )
{
// it's a dialog box, don't go upwards
break;
}
return nullptr;
hwnd = ::GetParent(hwnd);
if ( !hwnd )
return nullptr;
win = wxFindWinFromHandle(hwnd);
}