From 1b6dc0a2fbae391a1a0dd784b914ba53464ae9f5 Mon Sep 17 00:00:00 2001 From: Ilya Sinitsyn Date: Fri, 1 Nov 2019 00:19:53 +0700 Subject: [PATCH 1/4] Add MSWGetFocusHWND to allow focus a subwindow Under MSW allow override which subwindow will be focused for composite windows which are implemented not as a set of wxControl (i.e. using only Windows native controls). --- include/wx/msw/private.h | 1 + include/wx/msw/window.h | 5 +++++ src/msw/window.cpp | 8 +++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/wx/msw/private.h b/include/wx/msw/private.h index f850b7b554..46dffa05a6 100644 --- a/include/wx/msw/private.h +++ b/include/wx/msw/private.h @@ -838,6 +838,7 @@ private: // --------------------------------------------------------------------------- #define GetHwnd() ((HWND)GetHWND()) +#define MSWGetFocusHwnd() ((HWND)MSWGetFocusHWND()) #define GetHwndOf(win) ((HWND)((win)->GetHWND())) // old name #define GetWinHwnd GetHwndOf diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h index dd6c10a6b5..306cd814da 100644 --- a/include/wx/msw/window.h +++ b/include/wx/msw/window.h @@ -168,6 +168,11 @@ public: void AssociateHandle(WXWidget handle) wxOVERRIDE; void DissociateHandle() wxOVERRIDE; + // returns the handle of the focused window (i.e. in composite windows + // which can't be implemented via a set of wxControl's focus may be wanted + // by a subwindow instead of the main window) + virtual WXHWND MSWGetFocusHWND() const { return GetHWND(); } + // does this window have deferred position and/or size? bool IsSizeDeferred() const; diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 08028038b0..fd048e6e01 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -577,7 +577,7 @@ void wxWindowMSW::SetId(wxWindowID winid) void wxWindowMSW::SetFocus() { - HWND hWnd = GetHwnd(); + HWND hWnd = MSWGetFocusHwnd(); wxCHECK_RET( hWnd, wxT("can't set focus to invalid window") ); ::SetLastError(0); @@ -599,13 +599,15 @@ void wxWindowMSW::SetFocus() void wxWindowMSW::SetFocusFromKbd() { + HWND hWnd = MSWGetFocusHwnd(); + // when the focus is given to the control with DLGC_HASSETSEL style from // keyboard its contents should be entirely selected: this is what // ::IsDialogMessage() does and so we should do it as well to provide the // same LNF as the native programs - if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE, 0, 0) & DLGC_HASSETSEL ) + if ( ::SendMessage(hWnd, WM_GETDLGCODE, 0, 0) & DLGC_HASSETSEL ) { - ::SendMessage(GetHwnd(), EM_SETSEL, 0, -1); + ::SendMessage(hWnd, EM_SETSEL, 0, -1); } // do this after (maybe) setting the selection as like this when From bfde3d3e08dbddde566bee063bdc74c7ac12d210 Mon Sep 17 00:00:00 2001 From: Ilya Sinitsyn Date: Fri, 1 Nov 2019 00:27:43 +0700 Subject: [PATCH 2/4] Fix focus behaviour of the spin control under MSW Override MSWGetFocusHwnd for wxSpinCtrl to focus the right subwindow. So the correct window will be used in wxWindowMSW::SetFocusFromKbd and the spin controls content will be selected on TAB key. --- include/wx/msw/spinctrl.h | 3 ++- src/msw/spinctrl.cpp | 12 +++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/wx/msw/spinctrl.h b/include/wx/msw/spinctrl.h index 0e3f05c132..491d9d99bd 100644 --- a/include/wx/msw/spinctrl.h +++ b/include/wx/msw/spinctrl.h @@ -77,7 +77,6 @@ public: virtual int GetValue() const wxOVERRIDE; virtual void SetRange(int minVal, int maxVal) wxOVERRIDE; virtual bool SetFont(const wxFont &font) wxOVERRIDE; - virtual void SetFocus() wxOVERRIDE; virtual bool Enable(bool enable = true) wxOVERRIDE; virtual bool Show(bool show = true) wxOVERRIDE; @@ -115,6 +114,8 @@ public: virtual void SetLayoutDirection(wxLayoutDirection dir) wxOVERRIDE; + virtual WXHWND MSWGetFocusHWND() const wxOVERRIDE; + protected: virtual void DoGetPosition(int *x, int *y) const wxOVERRIDE; virtual void DoMoveWindow(int x, int y, int width, int height) wxOVERRIDE; diff --git a/src/msw/spinctrl.cpp b/src/msw/spinctrl.cpp index 11fa10ee83..321f6b11c5 100644 --- a/src/msw/spinctrl.cpp +++ b/src/msw/spinctrl.cpp @@ -522,6 +522,13 @@ void wxSpinCtrl::SetLayoutDirection(wxLayoutDirection dir) SetSize(-1, -1, -1, -1, wxSIZE_AUTO | wxSIZE_FORCE); } +WXHWND wxSpinCtrl::MSWGetFocusHWND() const +{ + // Return the buddy hwnd because it shuld be focused instead of the + // wxSpinCtrl itself. + return m_hwndBuddy; +} + // ---------------------------------------------------------------------------- // wxSpinButton methods // ---------------------------------------------------------------------------- @@ -653,11 +660,6 @@ bool wxSpinCtrl::Enable(bool enable) return true; } -void wxSpinCtrl::SetFocus() -{ - ::SetFocus(GetBuddyHwnd()); -} - #if wxUSE_TOOLTIPS void wxSpinCtrl::DoSetToolTip(wxToolTip *tip) From 96da0060ca159f49c8781d0ec02a6ff262b7a797 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 31 Oct 2019 23:56:55 +0100 Subject: [PATCH 3/4] Remove MSWGetFocusHwnd() helper It doesn't seem worth having it when it's only used in a couple of places in a single file, unlike GetHwnd() which is used in dozens of places across entire wxMSW. --- include/wx/msw/private.h | 1 - src/msw/window.cpp | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/wx/msw/private.h b/include/wx/msw/private.h index 46dffa05a6..f850b7b554 100644 --- a/include/wx/msw/private.h +++ b/include/wx/msw/private.h @@ -838,7 +838,6 @@ private: // --------------------------------------------------------------------------- #define GetHwnd() ((HWND)GetHWND()) -#define MSWGetFocusHwnd() ((HWND)MSWGetFocusHWND()) #define GetHwndOf(win) ((HWND)((win)->GetHWND())) // old name #define GetWinHwnd GetHwndOf diff --git a/src/msw/window.cpp b/src/msw/window.cpp index fd048e6e01..8f683c5773 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -577,7 +577,7 @@ void wxWindowMSW::SetId(wxWindowID winid) void wxWindowMSW::SetFocus() { - HWND hWnd = MSWGetFocusHwnd(); + HWND hWnd = (HWND)MSWGetFocusHWND(); wxCHECK_RET( hWnd, wxT("can't set focus to invalid window") ); ::SetLastError(0); @@ -599,7 +599,7 @@ void wxWindowMSW::SetFocus() void wxWindowMSW::SetFocusFromKbd() { - HWND hWnd = MSWGetFocusHwnd(); + HWND hWnd = (HWND)MSWGetFocusHWND(); // when the focus is given to the control with DLGC_HASSETSEL style from // keyboard its contents should be entirely selected: this is what From c0d992cf674042105b1a07f746aa9a8fd1ca28db Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 31 Oct 2019 23:58:21 +0100 Subject: [PATCH 4/4] Improve wording of MSWGetFocusHWND() comment No real changes, just try to explain what this function is for better. --- include/wx/msw/window.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h index 306cd814da..2ee4558b94 100644 --- a/include/wx/msw/window.h +++ b/include/wx/msw/window.h @@ -168,9 +168,10 @@ public: void AssociateHandle(WXWidget handle) wxOVERRIDE; void DissociateHandle() wxOVERRIDE; - // returns the handle of the focused window (i.e. in composite windows - // which can't be implemented via a set of wxControl's focus may be wanted - // by a subwindow instead of the main window) + // returns the handle of the native window to focus when this wxWindow gets + // focus (i.e. in composite windows: by default, this is just the HWND for + // this window itself, but it can be overridden to return something + // different for composite controls virtual WXHWND MSWGetFocusHWND() const { return GetHWND(); } // does this window have deferred position and/or size?