From af8b662868caaea6705e1d728ad5a793313cc732 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Mon, 2 Aug 2021 10:03:42 +0300 Subject: [PATCH] Handle WM_GETDLGCODE in wxTextCtrl for wxUniv too --- include/wx/univ/textctrl.h | 6 +++ src/msw/window.cpp | 105 ++++++++++++++++++++++++++++++++++++- src/univ/dialog.cpp | 8 ++- src/univ/textctrl.cpp | 22 ++++++++ 4 files changed, 138 insertions(+), 3 deletions(-) diff --git a/include/wx/univ/textctrl.h b/include/wx/univ/textctrl.h index 3a15244a8b..d5cea66484 100644 --- a/include/wx/univ/textctrl.h +++ b/include/wx/univ/textctrl.h @@ -451,6 +451,12 @@ protected: bool DoCut(); bool DoPaste(); +#ifdef __WXMSW__ +public: + // override MSWHandleMessage to process WM_GETDLGCODE + bool MSWHandleMessage(WXLRESULT *result, WXUINT message, WXWPARAM wParam, WXLPARAM lParam); +#endif // __WXMSW__ + private: // all these methods are for multiline text controls only diff --git a/src/msw/window.cpp b/src/msw/window.cpp index cba433d6be..417e86e62a 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -2676,7 +2676,104 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } } #else // __WXUNIVERSAL__ - wxUnusedVar(pMsg); + // But it also handles clicks on default button + if ( m_hWnd && + HasFlag(wxTAB_TRAVERSAL) && + wxHasWindowExStyle(this, WS_EX_CONTROLPARENT) ) + { + MSG *msg = (MSG *)pMsg; + + if ( msg->message == WM_KEYDOWN ) + { + bool bCtrlDown = wxIsCtrlDown(); + + // WM_GETDLGCODE: ask the control if it wants the key for itself, + // don't process it if it's the case (except for Ctrl-Tab/Enter + // combinations which are always processed) + LONG lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0); + + // surprisingly, DLGC_WANTALLKEYS bit mask doesn't contain the + // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically, + // it, of course, implies them + if ( lDlgCode & DLGC_WANTALLKEYS ) + { + lDlgCode |= DLGC_WANTTAB | DLGC_WANTARROWS; + } + + switch ( msg->wParam ) + { + case VK_RETURN: + { +#if wxUSE_BUTTON + // currently active button should get enter press even + // if there is a default button elsewhere so check if + // this window is a button first + wxButton *btn = NULL; + if ( lDlgCode & DLGC_DEFPUSHBUTTON ) + { + // let IsDialogMessage() handle this for all + // buttons except the owner-drawn ones which it + // just seems to ignore + long style = ::GetWindowLong(msg->hwnd, GWL_STYLE); + if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW ) + { + btn = wxDynamicCast + ( + wxFindWinFromHandle(msg->hwnd), + wxButton + ); + } + } + else // not a button itself, do we have default button? + { + // check if this window or any of its ancestors + // wants the message for itself (we always reserve + // Ctrl-Enter for dialog navigation though) + wxWindow *win = wxDynamicCast(this, wxWindow); + if ( !bCtrlDown ) + { + // this will contain the dialog code of this + // window and all of its parent windows in turn + LONG lDlgCode2 = lDlgCode; + + while ( win ) + { + if ( lDlgCode2 & DLGC_WANTMESSAGE ) + { + // as it wants to process Enter itself, + // don't call IsDialogMessage() which + // would consume it + return false; + } + + // don't propagate keyboard messages beyond + // the first top level window parent + if ( win->IsTopLevel() ) + break; + + win = win->GetParent(); + + lDlgCode2 = ::SendMessage + ( + GetHwndOf(win), + WM_GETDLGCODE, + 0, + 0 + ); + } + } + + btn = MSWGetDefaultButtonFor(win); + } + + if ( MSWClickButtonIfPossible(btn) ) + return true; +#endif // wxUSE_BUTTON + } + break; + } + } + } #endif // !__WXUNIVERSAL__/__WXUNIVERSAL__ #if wxUSE_TOOLTIPS @@ -2812,8 +2909,14 @@ bool wxWindowMSW::MSWClickButtonIfPossible(wxButton* btn) #if wxUSE_BUTTON if ( btn && btn->IsEnabled() && btn->IsShownOnScreen() ) { +#ifndef __WXUNIVERSAL__ btn->MSWCommand(BN_CLICKED, 0 /* unused */); return true; +#endif // !__WXUNIVERSAL + + wxCommandEvent event(wxEVT_BUTTON, btn->GetId()); + event.SetEventObject(btn); + return btn->HandleWindowEvent(event); } #endif // wxUSE_BUTTON diff --git a/src/univ/dialog.cpp b/src/univ/dialog.cpp index 8de1a92a5d..fae198adbb 100644 --- a/src/univ/dialog.cpp +++ b/src/univ/dialog.cpp @@ -96,8 +96,12 @@ void wxDialog::OnOK(wxCommandEvent &WXUNUSED(event)) } else { - SetReturnCode(wxID_OK); - Show(false); + // don't change return code from event char if it was set earlier + if (GetReturnCode() == 0) + { + SetReturnCode(wxID_OK); + Show(false); + } } } } diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index 8cf17e9825..53ca0ae95f 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -4805,6 +4805,28 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) event.Skip(); } +#ifdef __WXMSW__ +bool wxTextCtrl::MSWHandleMessage(WXLRESULT* result, WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +{ + bool processed = wxTextCtrlBase::MSWHandleMessage(result, message, wParam, lParam); + switch ( message ) + { + case WM_GETDLGCODE: + { + long lDlgCode = 0; + + // multiline controls should always get ENTER for themselves + if ( HasFlag(wxTE_PROCESS_ENTER) || HasFlag(wxTE_MULTILINE) ) + lDlgCode |= DLGC_WANTMESSAGE; + + *result |= lDlgCode; + return true; + } + } + return processed; +} +#endif // __WXMSW__ + /* static */ wxInputHandler *wxTextCtrl::GetStdInputHandler(wxInputHandler *handlerDef) {