X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e9717bd5d8ff2e3ff91d99d44850b1d2485f5edf..69d31e313035d5e22d9400ec946f6007f710910c:/src/msw/combobox.cpp?ds=sidebyside diff --git a/src/msw/combobox.cpp b/src/msw/combobox.cpp index bd3650dc3b..8fbcce2237 100644 --- a/src/msw/combobox.cpp +++ b/src/msw/combobox.cpp @@ -39,8 +39,13 @@ #endif #include "wx/clipbrd.h" +#include "wx/wupdlock.h" #include "wx/msw/private.h" +#if wxUSE_UXTHEME + #include "wx/msw/uxtheme.h" +#endif + #if wxUSE_TOOLTIPS #include "wx/tooltip.h" #endif // wxUSE_TOOLTIPS @@ -183,7 +188,7 @@ LRESULT APIENTRY _EXPORT wxComboEditWndProc(HWND hWnd, // longer, check for it to avoid bogus assert failures if ( !win->IsBeingDeleted() ) { - wxFAIL_MSG( _T("should have combo as parent") ); + wxFAIL_MSG( wxT("should have combo as parent") ); } } else if ( combo->MSWProcessEditMsg(message, wParam, lParam) ) @@ -196,7 +201,7 @@ LRESULT APIENTRY _EXPORT wxComboEditWndProc(HWND hWnd, case WM_GETDLGCODE: { - wxCHECK_MSG( win, 0, _T("should have a parent") ); + wxCHECK_MSG( win, 0, wxT("should have a parent") ); if ( win->GetWindowStyle() & wxTE_PROCESS_ENTER ) { @@ -205,13 +210,6 @@ LRESULT APIENTRY _EXPORT wxComboEditWndProc(HWND hWnd, } } break; - - case WM_CUT: - case WM_COPY: - case WM_PASTE: - if( win->HandleClipboardEvent( message ) ) - return 0; - break; } return ::CallWindowProc(CASTWNDPROC gs_wndprocEdit, hWnd, message, wParam, lParam); @@ -240,8 +238,23 @@ WXLRESULT wxComboBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara long fromOld, toOld; GetSelection(&fromOld, &toOld); + + // if an editable combobox has a not empty text not from the + // list, it tries to autocomplete it from the list when it is + // resized, but we don't want this to happen as it doesn't seem + // to make any sense, so we forcefully restore the old text + wxString textOld; + if ( !HasFlag(wxCB_READONLY) && GetCurrentSelection() == -1 ) + textOld = GetValue(); + + // eliminate flickering during following hacks + wxWindowUpdateLocker lock(this); + WXLRESULT result = wxChoice::MSWWindowProc(nMsg, wParam, lParam); + if ( !textOld.empty() && GetValue() != textOld ) + SetLabel(textOld); + long fromNew, toNew; GetSelection(&fromNew, &toNew); @@ -302,6 +315,11 @@ bool wxComboBox::MSWProcessEditMsg(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam) case WM_KILLFOCUS: return HandleKillFocus((WXHWND)wParam); + + case WM_CUT: + case WM_COPY: + case WM_PASTE: + return HandleClipboardEvent(msg); } return false; @@ -314,6 +332,29 @@ bool wxComboBox::MSWCommand(WXUINT param, WXWORD id) switch ( param ) { + case CBN_DROPDOWN: + // remember the last selection, just as wxChoice does + m_lastAcceptedSelection = GetCurrentSelection(); + if ( m_lastAcceptedSelection == -1 ) + { + // but unlike with wxChoice we may have no selection but still + // have some text and we should avoid erasing it if the drop + // down is cancelled (see #8474) + m_lastAcceptedSelection = wxID_NONE; + } + { + wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_DROPDOWN, GetId()); + event.SetEventObject(this); + ProcessCommand(event); + } + break; + case CBN_CLOSEUP: + { + wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_CLOSEUP, GetId()); + event.SetEventObject(this); + ProcessCommand(event); + } + break; case CBN_SELENDOK: #ifndef __SMARTPHONE__ // we need to reset this to prevent the selection from being undone @@ -345,6 +386,7 @@ bool wxComboBox::MSWCommand(WXUINT param, WXWORD id) // logical as the text does change) case CBN_EDITCHANGE: + if ( m_allowTextEvents ) { wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId()); @@ -366,7 +408,7 @@ bool wxComboBox::MSWCommand(WXUINT param, WXWORD id) } // skip wxChoice version as it would generate its own events for - // CBN_SELENDOK + // CBN_SELENDOK and also interfere with our handling of CBN_DROPDOWN return true; } @@ -396,12 +438,13 @@ bool wxComboBox::MSWShouldPreProcessMessage(WXMSG *pMsg) WXHWND wxComboBox::GetEditHWNDIfAvailable() const { - POINT pt = { 4, 4 }; - WXHWND hWndEdit = (WXHWND)::ChildWindowFromPoint(GetHwnd(), pt); - if ( hWndEdit == GetHWND() ) - hWndEdit = NULL; + // notice that a slightly safer alternative could be to use FindWindowEx() + // but it's not available under WinCE so just take the first child for now + // to keep one version of the code for all platforms and fix it later if + // problems are discovered - return hWndEdit; + // we assume that the only child of the combobox is the edit window + return (WXHWND)::GetWindow(GetHwnd(), GW_CHILD); } WXHWND wxComboBox::GetEditHWND() const @@ -409,14 +452,22 @@ WXHWND wxComboBox::GetEditHWND() const // this function should not be called for wxCB_READONLY controls, it is // the callers responsibility to check this wxASSERT_MSG( !HasFlag(wxCB_READONLY), - _T("read-only combobox doesn't have any edit control") ); + wxT("read-only combobox doesn't have any edit control") ); WXHWND hWndEdit = GetEditHWNDIfAvailable(); - wxASSERT_MSG( hWndEdit, _T("combobox without edit control?") ); + wxASSERT_MSG( hWndEdit, wxT("combobox without edit control?") ); return hWndEdit; } +wxWindow *wxComboBox::GetEditableWindow() +{ + wxASSERT_MSG( !HasFlag(wxCB_READONLY), + wxT("read-only combobox doesn't have any edit control") ); + + return this; +} + // ---------------------------------------------------------------------------- // wxComboBox creation // ---------------------------------------------------------------------------- @@ -582,15 +633,12 @@ void wxComboBox::OnRedo(wxCommandEvent& WXUNUSED(event)) void wxComboBox::OnDelete(wxCommandEvent& WXUNUSED(event)) { - long from, to; - GetSelection(& from, & to); - if (from != -1 && to != -1) - Remove(from, to); + RemoveSelection(); } void wxComboBox::OnSelectAll(wxCommandEvent& WXUNUSED(event)) { - SetSelection(-1, -1); + SelectAll(); } void wxComboBox::OnUpdateCut(wxUpdateUIEvent& event) @@ -610,12 +658,12 @@ void wxComboBox::OnUpdatePaste(wxUpdateUIEvent& event) void wxComboBox::OnUpdateUndo(wxUpdateUIEvent& event) { - event.Enable( CanUndo() ); + event.Enable( IsEditable() && CanUndo() ); } void wxComboBox::OnUpdateRedo(wxUpdateUIEvent& event) { - event.Enable( CanRedo() ); + event.Enable( IsEditable() && CanRedo() ); } void wxComboBox::OnUpdateDelete(wxUpdateUIEvent& event) @@ -625,7 +673,7 @@ void wxComboBox::OnUpdateDelete(wxUpdateUIEvent& event) void wxComboBox::OnUpdateSelectAll(wxUpdateUIEvent& event) { - event.Enable(IsEditable() && GetLastPosition() > 0); + event.Enable(IsEditable() && !wxTextEntry::IsEmpty()); } #if wxUSE_TOOLTIPS @@ -640,4 +688,22 @@ void wxComboBox::DoSetToolTip(wxToolTip *tip) #endif // wxUSE_TOOLTIPS +#if wxUSE_UXTHEME + +bool wxComboBox::SetHint(const wxString& hintOrig) +{ + wxString hint(hintOrig); + if ( wxUxThemeEngine::GetIfActive() ) + { + // under XP (but not Vista) there is a bug in cue banners + // implementation for combobox edit control: the first character is + // partially chopped off, so prepend a space to make it fully visible + hint.insert(0, " "); + } + + return wxTextEntry::SetHint(hint); +} + +#endif // wxUSE_UXTHEME + #endif // wxUSE_COMBOBOX