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.
|
- Implement SetIcon(), SetPosition(), GetPosition() for native wxProgressDialog.
|
||||||
- Fix focus-related problems when using native wxProgressDialog.
|
- Fix focus-related problems when using native wxProgressDialog.
|
||||||
- Fix crash when reparenting the currently focused window to another TLW.
|
- Fix crash when reparenting the currently focused window to another TLW.
|
||||||
|
- Fix sending wxEVT_TEXT_ENTER when using auto-completion (Dubby).
|
||||||
|
|
||||||
wxOSX:
|
wxOSX:
|
||||||
|
|
||||||
|
@@ -158,6 +158,14 @@ private:
|
|||||||
virtual wxWindow *GetEditableWindow() wxOVERRIDE;
|
virtual wxWindow *GetEditableWindow() wxOVERRIDE;
|
||||||
virtual WXHWND GetEditHWND() const 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
|
// common part of all ctors
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
|
@@ -277,6 +277,10 @@ private:
|
|||||||
// the simple EDIT controls
|
// the simple EDIT controls
|
||||||
virtual WXHWND GetEditHWND() const wxOVERRIDE { return m_hWnd; }
|
virtual WXHWND GetEditHWND() const wxOVERRIDE { return m_hWnd; }
|
||||||
|
|
||||||
|
#if wxUSE_OLE
|
||||||
|
virtual void MSWProcessSpecialKey(wxKeyEvent& event) wxOVERRIDE;
|
||||||
|
#endif // wxUSE_OLE
|
||||||
|
|
||||||
void OnKeyDown(wxKeyEvent& event);
|
void OnKeyDown(wxKeyEvent& event);
|
||||||
|
|
||||||
// Used by EN_MAXTEXT handler to increase the size limit (will do nothing
|
// Used by EN_MAXTEXT handler to increase the size limit (will do nothing
|
||||||
|
@@ -86,6 +86,16 @@ private:
|
|||||||
virtual WXHWND GetEditHWND() const = 0;
|
virtual WXHWND GetEditHWND() const = 0;
|
||||||
|
|
||||||
#if wxUSE_OLE
|
#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
|
// Get the auto-complete object creating it if necessary. Returns NULL if
|
||||||
// creating it failed.
|
// creating it failed.
|
||||||
wxTextAutoCompleteData *GetOrCreateCompleter();
|
wxTextAutoCompleteData *GetOrCreateCompleter();
|
||||||
|
@@ -218,19 +218,16 @@ WXLRESULT wxComboBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
|
|||||||
return wxChoice::MSWWindowProc(nMsg, wParam, lParam);
|
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
|
// for compatibility with wxTextCtrl, generate a special message
|
||||||
// when Enter is pressed
|
// when Enter is pressed
|
||||||
switch ( wParam )
|
switch ( vkey )
|
||||||
{
|
{
|
||||||
case VK_RETURN:
|
case VK_RETURN:
|
||||||
{
|
{
|
||||||
if (SendMessage(GetHwnd(), CB_GETDROPPEDSTATE, 0, 0))
|
if (SendMessage(GetHwnd(), CB_GETDROPPEDSTATE, 0, 0))
|
||||||
return false;
|
break;
|
||||||
|
|
||||||
wxCommandEvent event(wxEVT_TEXT_ENTER, m_windowId);
|
wxCommandEvent event(wxEVT_TEXT_ENTER, m_windowId);
|
||||||
|
|
||||||
@@ -266,6 +263,18 @@ bool wxComboBox::MSWProcessEditMsg(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam)
|
|||||||
}
|
}
|
||||||
break;
|
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) )
|
if ( ShouldForwardFromEditToCombo(msg) )
|
||||||
@@ -383,6 +392,16 @@ bool wxComboBox::MSWShouldPreProcessMessage(WXMSG *pMsg)
|
|||||||
return wxChoice::MSWShouldPreProcessMessage(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
|
WXHWND wxComboBox::GetEditHWNDIfAvailable() const
|
||||||
{
|
{
|
||||||
WinStruct<COMBOBOXINFO> info;
|
WinStruct<COMBOBOXINFO> info;
|
||||||
|
@@ -2103,6 +2103,19 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
event.Skip();
|
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)
|
void wxTextCtrl::OnKeyDown(wxKeyEvent& event)
|
||||||
{
|
{
|
||||||
// richedit control doesn't send WM_PASTE, WM_CUT and WM_COPY messages
|
// richedit control doesn't send WM_PASTE, WM_CUT and WM_COPY messages
|
||||||
|
@@ -573,23 +573,56 @@ private:
|
|||||||
|
|
||||||
void OnCharHook(wxKeyEvent& event)
|
void OnCharHook(wxKeyEvent& event)
|
||||||
{
|
{
|
||||||
// If the autocomplete drop-down list is currently displayed when the
|
// We need to override the default handling of some keys here.
|
||||||
// user presses Escape, we need to dismiss it manually from here as
|
bool specialKey = false;
|
||||||
// Escape could be eaten by something else (e.g. EVT_CHAR_HOOK in the
|
switch ( event.GetKeyCode() )
|
||||||
// dialog that this control is found in) otherwise.
|
|
||||||
if ( event.GetKeyCode() == WXK_ESCAPE )
|
|
||||||
{
|
{
|
||||||
|
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;
|
DWORD dwFlags = 0;
|
||||||
if ( SUCCEEDED(m_autoCompleteDropDown->GetDropDownStatus(&dwFlags,
|
if ( SUCCEEDED(m_autoCompleteDropDown->GetDropDownStatus(&dwFlags,
|
||||||
NULL))
|
NULL))
|
||||||
&& dwFlags == ACDD_VISIBLE )
|
&& 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);
|
::SendMessage(GetHwndOf(m_win), WM_KEYDOWN, WXK_ESCAPE, 0);
|
||||||
|
|
||||||
// Do not skip the event in this case, we've already handled it.
|
// Do not skip the event in this case, we've already handled it.
|
||||||
return;
|
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();
|
event.Skip();
|
||||||
}
|
}
|
||||||
@@ -804,6 +837,11 @@ bool wxTextEntry::DoAutoCompleteFileNames(int flags)
|
|||||||
|
|
||||||
#endif // wxUSE_DYNLIB_CLASS
|
#endif // wxUSE_DYNLIB_CLASS
|
||||||
|
|
||||||
|
void wxTextEntry::MSWProcessSpecialKey(wxKeyEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
wxFAIL_MSG(wxS("Must be overridden if can be called"));
|
||||||
|
}
|
||||||
|
|
||||||
wxTextAutoCompleteData *wxTextEntry::GetOrCreateCompleter()
|
wxTextAutoCompleteData *wxTextEntry::GetOrCreateCompleter()
|
||||||
{
|
{
|
||||||
if ( !m_autoCompleteData )
|
if ( !m_autoCompleteData )
|
||||||
|
Reference in New Issue
Block a user