Merge branch 'msw-combo-keys'

Fix behaviour of comboboxes in presence of accelerators in wxMSW.

See https://github.com/wxWidgets/wxWidgets/pull/2443
This commit is contained in:
Vadim Zeitlin
2021-08-06 20:29:20 +01:00
5 changed files with 114 additions and 97 deletions

View File

@@ -84,6 +84,10 @@ protected:
// Returns true if this control uses standard file names completion. // Returns true if this control uses standard file names completion.
bool MSWUsesStandardAutoComplete() const; bool MSWUsesStandardAutoComplete() const;
// Returns false if this message shouldn't be preprocessed, but is always
// handled by the EDIT control represented by this object itself.
bool MSWShouldPreProcessMessage(WXMSG* msg) const;
// Helper for wxTE_PROCESS_ENTER handling: activates the default button in // Helper for wxTE_PROCESS_ENTER handling: activates the default button in
// the dialog containing this control if any. // the dialog containing this control if any.
bool ClickDefaultButtonIfPossible(); bool ClickDefaultButtonIfPossible();

View File

@@ -121,21 +121,32 @@ bool wxChoice::Create(wxWindow *parent,
style, validator, name); style, validator, name);
} }
bool wxChoice::MSWShouldPreProcessMessage(WXMSG *pMsg) bool wxChoice::MSWShouldPreProcessMessage(WXMSG *msg)
{ {
MSG *msg = (MSG *) pMsg; if ( msg->message == WM_KEYDOWN &&
!(HIWORD(msg->lParam) & KF_ALTDOWN) &&
// if the dropdown list is visible, don't preprocess certain keys !wxIsShiftDown() &&
if ( msg->message == WM_KEYDOWN !wxIsCtrlDown() )
&& (msg->wParam == VK_ESCAPE || msg->wParam == VK_RETURN) )
{ {
if (::SendMessage(GetHwndOf(this), CB_GETDROPPEDSTATE, 0, 0)) switch ( msg->wParam )
{ {
return false; case VK_ESCAPE:
case VK_RETURN:
// These keys are needed by the control itself when the
// dropdown list is visible, so don't preprocess them then.
if (::SendMessage(GetHwndOf(this), CB_GETDROPPEDSTATE, 0, 0))
{
return false;
}
break;
case VK_F4:
// This key can always be used to show the dropdown.
return false;
} }
} }
return wxControl::MSWShouldPreProcessMessage(pMsg); return wxControl::MSWShouldPreProcessMessage(msg);
} }
WXDWORD wxChoice::MSWGetStyle(long style, WXDWORD *exstyle) const WXDWORD wxChoice::MSWGetStyle(long style, WXDWORD *exstyle) const

View File

@@ -383,26 +383,9 @@ bool wxComboBox::MSWCommand(WXUINT param, WXWORD id)
bool wxComboBox::MSWShouldPreProcessMessage(WXMSG *pMsg) bool wxComboBox::MSWShouldPreProcessMessage(WXMSG *pMsg)
{ {
// prevent command accelerators from stealing editing return (HasFlag(wxCB_READONLY) ||
// hotkeys when we have the focus wxTextEntry::MSWShouldPreProcessMessage(pMsg)) &&
if (wxIsCtrlDown()) wxChoice::MSWShouldPreProcessMessage(pMsg);
{
WPARAM vkey = pMsg->wParam;
switch (vkey)
{
case 'C':
case 'V':
case 'X':
case VK_INSERT:
case VK_DELETE:
case VK_HOME:
case VK_END:
return false;
}
}
return wxChoice::MSWShouldPreProcessMessage(pMsg);
} }
#if wxUSE_OLE #if wxUSE_OLE

View File

@@ -2058,80 +2058,29 @@ void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* msg) bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* msg)
{ {
// check for our special keys here: if we don't do it and the parent frame // Handle keys specific to (multiline) text controls here.
// uses them as accelerators, they wouldn't work at all, so we disable if ( msg->message == WM_KEYDOWN && !(HIWORD(msg->lParam) & KF_ALTDOWN) )
// usual preprocessing for them
if ( msg->message == WM_KEYDOWN )
{ {
const WPARAM vkey = msg->wParam; switch ( msg->wParam )
if ( HIWORD(msg->lParam) & KF_ALTDOWN )
{ {
// Alt-Backspace is accelerator for "Undo" case VK_RETURN:
if ( vkey == VK_BACK ) // This key must be handled only by multiline controls and only
return false; // if it's pressed on its own, not with some modifier.
} if ( !wxIsShiftDown() && !wxIsCtrlDown() && IsMultiLine() )
else // no Alt return false;
{ break;
// we want to process some Ctrl-foo and Shift-bar but no key
// combinations without either Ctrl or Shift nor with both of them
// pressed
const int ctrl = wxIsCtrlDown(),
shift = wxIsShiftDown();
switch ( ctrl + shift )
{
default:
wxFAIL_MSG( wxT("how many modifiers have we got?") );
wxFALLTHROUGH;
case 0: case VK_BACK:
switch ( vkey ) if ( wxIsCtrlDown() && !wxIsShiftDown() &&
{ MSWNeedsToHandleCtrlBackspace() )
case VK_RETURN: return false;
// This one is only special for multi line controls. break;
if ( !IsMultiLine() )
break;
wxFALLTHROUGH;
case VK_DELETE:
case VK_HOME:
case VK_END:
return false;
}
wxFALLTHROUGH;
case 2:
break;
case 1:
// either Ctrl or Shift pressed
if ( ctrl )
{
switch ( vkey )
{
case 'A':
case 'C':
case 'V':
case 'X':
case VK_INSERT:
case VK_DELETE:
case VK_HOME:
case VK_END:
return false;
case VK_BACK:
if ( MSWNeedsToHandleCtrlBackspace() )
return false;
}
}
else // Shift is pressed
{
if ( vkey == VK_INSERT || vkey == VK_DELETE )
return false;
}
}
} }
} }
return wxControl::MSWShouldPreProcessMessage(msg); // Delegate all the other checks to the base classes.
return wxTextEntry::MSWShouldPreProcessMessage(msg) &&
wxControl::MSWShouldPreProcessMessage(msg);
} }
void wxTextCtrl::OnChar(wxKeyEvent& event) void wxTextCtrl::OnChar(wxKeyEvent& event)

View File

@@ -1072,4 +1072,74 @@ bool wxTextEntry::ClickDefaultButtonIfPossible()
wxWindow::MSWGetDefaultButtonFor(GetEditableWindow())); wxWindow::MSWGetDefaultButtonFor(GetEditableWindow()));
} }
bool wxTextEntry::MSWShouldPreProcessMessage(WXMSG* msg) const
{
// check for our special keys here: if we don't do it and the parent frame
// uses them as accelerators, they wouldn't work at all, so we disable
// usual preprocessing for them
if ( msg->message == WM_KEYDOWN )
{
const WPARAM vkey = msg->wParam;
if ( HIWORD(msg->lParam) & KF_ALTDOWN )
{
// Alt-Backspace is accelerator for "Undo"
if ( vkey == VK_BACK )
return false;
}
else // no Alt
{
// we want to process some Ctrl-foo and Shift-bar but no key
// combinations without either Ctrl or Shift nor with both of them
// pressed
const int ctrl = wxIsCtrlDown(),
shift = wxIsShiftDown();
switch ( ctrl + shift )
{
default:
wxFAIL_MSG( wxT("how many modifiers have we got?") );
wxFALLTHROUGH;
case 0:
switch ( vkey )
{
case VK_DELETE:
case VK_HOME:
case VK_END:
return false;
}
break;
case 1:
// either Ctrl or Shift pressed
if ( ctrl )
{
switch ( vkey )
{
case 'A':
case 'C':
case 'V':
case 'X':
case VK_INSERT:
case VK_DELETE:
case VK_HOME:
case VK_END:
return false;
}
}
else // Shift is pressed
{
if ( vkey == VK_INSERT || vkey == VK_DELETE )
return false;
}
break;
case 2:
break;
}
}
}
return true;
}
#endif // wxUSE_TEXTCTRL || wxUSE_COMBOBOX #endif // wxUSE_TEXTCTRL || wxUSE_COMBOBOX