Fix sending wxEVT_TEXT_ENTER when using auto-completion in wxMSW
We need to explicitly generate this event from the char hook handler as we don't get the normal WM_CHAR for it, it is apparently intercepted by the window proc installed by the auto-completing code, so check if wxTE_PROCESS_ENTER is used for the text entry and call a special new MSWProcessSpecialKey() method to do the right thing if it is. Similarly, handle Tab presses correctly if wxTE_PROCESS_TAB is used. Closes #12613.
This commit is contained in:
@@ -232,6 +232,7 @@ wxMSW:
|
||||
- Implement SetIcon(), SetPosition(), GetPosition() for native wxProgressDialog.
|
||||
- Fix focus-related problems when using native wxProgressDialog.
|
||||
- Fix crash when reparenting the currently focused window to another TLW.
|
||||
- Fix sending wxEVT_TEXT_ENTER when using auto-completion (Dubby).
|
||||
|
||||
wxOSX:
|
||||
|
||||
|
@@ -158,6 +158,14 @@ private:
|
||||
virtual wxWindow *GetEditableWindow() wxOVERRIDE;
|
||||
virtual WXHWND GetEditHWND() const wxOVERRIDE;
|
||||
|
||||
// Common part of MSWProcessEditMsg() and MSWProcessSpecialKey(), return
|
||||
// true if the key was processed.
|
||||
bool MSWProcessEditSpecialKey(WXWPARAM vkey);
|
||||
|
||||
#if wxUSE_OLE
|
||||
virtual void MSWProcessSpecialKey(wxKeyEvent& event) wxOVERRIDE;
|
||||
#endif // wxUSE_OLE
|
||||
|
||||
// common part of all ctors
|
||||
void Init()
|
||||
{
|
||||
|
@@ -277,6 +277,10 @@ private:
|
||||
// the simple EDIT controls
|
||||
virtual WXHWND GetEditHWND() const wxOVERRIDE { return m_hWnd; }
|
||||
|
||||
#if wxUSE_OLE
|
||||
virtual void MSWProcessSpecialKey(wxKeyEvent& event) wxOVERRIDE;
|
||||
#endif // wxUSE_OLE
|
||||
|
||||
void OnKeyDown(wxKeyEvent& event);
|
||||
|
||||
// Used by EN_MAXTEXT handler to increase the size limit (will do nothing
|
||||
|
@@ -86,6 +86,16 @@ private:
|
||||
virtual WXHWND GetEditHWND() const = 0;
|
||||
|
||||
#if wxUSE_OLE
|
||||
// This method is called to process special keys such as Return and Tab
|
||||
// before they're consumed by the auto-completer. Notice that it is only
|
||||
// called if we do need to process the key, i.e. if the corresponding
|
||||
// wxTE_PROCESS_XXX style is set in the associated object.
|
||||
//
|
||||
// It is not pure virtual because it won't get called if the derived class
|
||||
// doesn't use auto-completer, but it does need to be overridden if it can
|
||||
// be called and the default implementation asserts if this is not the case.
|
||||
virtual void MSWProcessSpecialKey(wxKeyEvent& event);
|
||||
|
||||
// Get the auto-complete object creating it if necessary. Returns NULL if
|
||||
// creating it failed.
|
||||
wxTextAutoCompleteData *GetOrCreateCompleter();
|
||||
|
@@ -218,19 +218,16 @@ WXLRESULT wxComboBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
|
||||
return wxChoice::MSWWindowProc(nMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
bool wxComboBox::MSWProcessEditMsg(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
bool wxComboBox::MSWProcessEditSpecialKey(WXWPARAM vkey)
|
||||
{
|
||||
switch ( msg )
|
||||
{
|
||||
case WM_CHAR:
|
||||
// for compatibility with wxTextCtrl, generate a special message
|
||||
// when Enter is pressed
|
||||
switch ( wParam )
|
||||
switch ( vkey )
|
||||
{
|
||||
case VK_RETURN:
|
||||
{
|
||||
if (SendMessage(GetHwnd(), CB_GETDROPPEDSTATE, 0, 0))
|
||||
return false;
|
||||
break;
|
||||
|
||||
wxCommandEvent event(wxEVT_TEXT_ENTER, m_windowId);
|
||||
|
||||
@@ -266,6 +263,18 @@ bool wxComboBox::MSWProcessEditMsg(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxComboBox::MSWProcessEditMsg(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
{
|
||||
switch ( msg )
|
||||
{
|
||||
case WM_CHAR:
|
||||
if ( MSWProcessEditSpecialKey(wParam) )
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ShouldForwardFromEditToCombo(msg) )
|
||||
@@ -383,6 +392,16 @@ bool wxComboBox::MSWShouldPreProcessMessage(WXMSG *pMsg)
|
||||
return wxChoice::MSWShouldPreProcessMessage(pMsg);
|
||||
}
|
||||
|
||||
#if wxUSE_OLE
|
||||
|
||||
void wxComboBox::MSWProcessSpecialKey(wxKeyEvent& event)
|
||||
{
|
||||
if ( !MSWProcessEditSpecialKey(event.GetRawKeyCode()) )
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
#endif // wxUSE_OLE
|
||||
|
||||
WXHWND wxComboBox::GetEditHWNDIfAvailable() const
|
||||
{
|
||||
WinStruct<COMBOBOXINFO> info;
|
||||
|
@@ -2103,6 +2103,19 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
#if wxUSE_OLE
|
||||
|
||||
void wxTextCtrl::MSWProcessSpecialKey(wxKeyEvent& event)
|
||||
{
|
||||
// It is not a good idea, in general, to manually call another event
|
||||
// handler, but here we need to do exactly the same thing as in OnChar()
|
||||
// above, so it doesn't seem to make much sense to add another function to
|
||||
// forward to when we can just call it directly.
|
||||
OnChar(event);
|
||||
}
|
||||
|
||||
#endif // wxUSE_OLE
|
||||
|
||||
void wxTextCtrl::OnKeyDown(wxKeyEvent& event)
|
||||
{
|
||||
// richedit control doesn't send WM_PASTE, WM_CUT and WM_COPY messages
|
||||
|
@@ -573,23 +573,56 @@ private:
|
||||
|
||||
void OnCharHook(wxKeyEvent& event)
|
||||
{
|
||||
// If the autocomplete drop-down list is currently displayed when the
|
||||
// user presses Escape, we need to dismiss it manually from here as
|
||||
// Escape could be eaten by something else (e.g. EVT_CHAR_HOOK in the
|
||||
// dialog that this control is found in) otherwise.
|
||||
if ( event.GetKeyCode() == WXK_ESCAPE )
|
||||
// We need to override the default handling of some keys here.
|
||||
bool specialKey = false;
|
||||
switch ( event.GetKeyCode() )
|
||||
{
|
||||
case WXK_RETURN:
|
||||
if ( m_win->HasFlag(wxTE_PROCESS_ENTER) )
|
||||
specialKey = true;
|
||||
break;
|
||||
|
||||
case WXK_TAB:
|
||||
if ( m_win->HasFlag(wxTE_PROCESS_TAB) )
|
||||
specialKey = true;
|
||||
break;
|
||||
|
||||
case WXK_ESCAPE:
|
||||
specialKey = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( specialKey )
|
||||
{
|
||||
// Check if the drop down is currently open.
|
||||
DWORD dwFlags = 0;
|
||||
if ( SUCCEEDED(m_autoCompleteDropDown->GetDropDownStatus(&dwFlags,
|
||||
NULL))
|
||||
&& dwFlags == ACDD_VISIBLE )
|
||||
{
|
||||
if ( event.GetKeyCode() == WXK_ESCAPE )
|
||||
{
|
||||
// We need to dismiss the drop-down manually as Escape
|
||||
// could be eaten by something else (e.g. EVT_CHAR_HOOK in
|
||||
// the dialog that this control is found in) otherwise.
|
||||
::SendMessage(GetHwndOf(m_win), WM_KEYDOWN, WXK_ESCAPE, 0);
|
||||
|
||||
// Do not skip the event in this case, we've already handled it.
|
||||
return;
|
||||
}
|
||||
}
|
||||
else // Drop down is not open.
|
||||
{
|
||||
// In this case we need to handle Return and Tab as both of
|
||||
// them are simply eaten by the auto completer and never reach
|
||||
// us at all otherwise.
|
||||
if ( event.GetKeyCode() != WXK_ESCAPE )
|
||||
{
|
||||
m_entry->MSWProcessSpecialKey(event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
@@ -804,6 +837,11 @@ bool wxTextEntry::DoAutoCompleteFileNames(int flags)
|
||||
|
||||
#endif // wxUSE_DYNLIB_CLASS
|
||||
|
||||
void wxTextEntry::MSWProcessSpecialKey(wxKeyEvent& WXUNUSED(event))
|
||||
{
|
||||
wxFAIL_MSG(wxS("Must be overridden if can be called"));
|
||||
}
|
||||
|
||||
wxTextAutoCompleteData *wxTextEntry::GetOrCreateCompleter()
|
||||
{
|
||||
if ( !m_autoCompleteData )
|
||||
|
Reference in New Issue
Block a user