X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cb0afb266214f827417c42474168c7edda7c953e..7848088476db284a94f19eeb24411b45d676ac46:/src/msw/combobox.cpp diff --git a/src/msw/combobox.cpp b/src/msw/combobox.cpp index a01a5d9d24..26ef863e24 100644 --- a/src/msw/combobox.cpp +++ b/src/msw/combobox.cpp @@ -127,7 +127,7 @@ LRESULT APIENTRY _EXPORT wxComboEditWndProc(HWND hWnd, // --------------------------------------------------------------------------- // the pointer to standard radio button wnd proc -static WXFARPROC gs_wndprocEdit = (WXFARPROC)NULL; +static WNDPROC gs_wndprocEdit = (WNDPROC)NULL; // ============================================================================ // implementation @@ -213,11 +213,12 @@ LRESULT APIENTRY _EXPORT wxComboEditWndProc(HWND hWnd, return ::CallWindowProc(CASTWNDPROC gs_wndprocEdit, hWnd, message, wParam, lParam); } -WXHBRUSH wxComboBox::OnCtlColor(WXHDC pDC, WXHWND WXUNUSED(pWnd), WXUINT WXUNUSED(nCtlColor), - WXUINT WXUNUSED(message), - WXWPARAM WXUNUSED(wParam), - WXLPARAM WXUNUSED(lParam) - ) +WXHBRUSH wxComboBox::OnCtlColor(WXHDC pDC, + WXHWND WXUNUSED(pWnd), + WXUINT WXUNUSED(nCtlColor), + WXUINT WXUNUSED(message), + WXWPARAM WXUNUSED(wParam), + WXLPARAM WXUNUSED(lParam)) { HDC hdc = (HDC)pDC; wxColour colBack = GetBackgroundColour(); @@ -234,9 +235,30 @@ WXHBRUSH wxComboBox::OnCtlColor(WXHDC pDC, WXHWND WXUNUSED(pWnd), WXUINT WXUNUSE } // ---------------------------------------------------------------------------- -// wxComboBox +// wxComboBox callbacks // ---------------------------------------------------------------------------- +WXLRESULT wxComboBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) +{ + // handle WM_CTLCOLOR messages from our EDIT control to be able to set its + // colour correctly (to be the same as our own one) + switch ( nMsg ) + { + // we have to handle both: one for the normal case and the other for + // wxCB_READONLY + case WM_CTLCOLOREDIT: + case WM_CTLCOLORSTATIC: + WXWORD nCtlColor; + WXHDC hdc; + WXHWND hwnd; + UnpackCtlColor(wParam, lParam, &nCtlColor, &hdc, &hwnd); + + return (WXLRESULT)OnCtlColor(hdc, hwnd, nCtlColor, nMsg, wParam, lParam); + } + + return wxChoice::MSWWindowProc(nMsg, wParam, lParam); +} + bool wxComboBox::MSWProcessEditMsg(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam) { switch ( msg ) @@ -311,6 +333,14 @@ bool wxComboBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) } else // we're synthesizing text updated event from sel change { + // We need to retrieve the current selection because the user + // may have changed it in the previous handler (for CBN_SELCHANGE + // above). + sel = GetSelection(); + if ( sel > -1 ) + { + value = GetString(sel); + } // we need to do this because the user code expects // wxComboBox::GetValue() to return the new value from // "text updated" handler but it hadn't been updated yet @@ -347,6 +377,10 @@ WXHWND wxComboBox::GetEditHWND() const return (WXHWND)hwndEdit; } +// ---------------------------------------------------------------------------- +// wxComboBox creation +// ---------------------------------------------------------------------------- + bool wxComboBox::Create(wxWindow *parent, wxWindowID id, const wxString& value, const wxPoint& pos, @@ -361,62 +395,23 @@ bool wxComboBox::Create(wxWindow *parent, wxWindowID id, // some noticeable flicker while the control rearranges itself m_isShown = FALSE; - // first create wxWin object - if ( !CreateControl(parent, id, pos, size, style, validator, name) ) - return FALSE; - - // get the right style - long msStyle = WS_TABSTOP | WS_VSCROLL | WS_HSCROLL | - CBS_AUTOHSCROLL | CBS_NOINTEGRALHEIGHT /* | WS_CLIPSIBLINGS */; - if ( style & wxCB_READONLY ) - msStyle |= CBS_DROPDOWNLIST; -#ifndef __WXWINCE__ - else if ( style & wxCB_SIMPLE ) - msStyle |= CBS_SIMPLE; // A list (shown always) and edit control -#endif - else - msStyle |= CBS_DROPDOWN; - - if ( style & wxCB_SORT ) - msStyle |= CBS_SORT; - - if ( style & wxCLIP_SIBLINGS ) - msStyle |= WS_CLIPSIBLINGS; - - - // and now create the MSW control - if ( !MSWCreateControl(_T("COMBOBOX"), msStyle) ) + if ( !CreateAndInit(parent, id, pos, size, n, choices, style, + validator, name) ) return FALSE; - // A choice/combobox normally has a white background (or other, depending - // on global settings) rather than inheriting the parent's background colour. - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - - for ( int i = 0; i < n; i++ ) - { - Append(choices[i]); - } - - if ( !value.IsEmpty() ) - { + // we shouldn't call SetValue() for an empty string because this would + // (correctly) result in an assert with a read only combobox and is useless + // for the other ones anyhow + if ( !value.empty() ) SetValue(value); - } - - // do this after appending the values to the combobox so that autosizing - // works correctly - SetSize(pos.x, pos.y, size.x, size.y); // a (not read only) combobox is, in fact, 2 controls: the combobox itself // and an edit control inside it and if we want to catch events from this // edit control, we must subclass it as well if ( !(style & wxCB_READONLY) ) { - gs_wndprocEdit = (WXFARPROC)::SetWindowLong - ( - (HWND)GetEditHWND(), - GWL_WNDPROC, - (LPARAM)wxComboEditWndProc - ); + gs_wndprocEdit = wxSetWindowProc((HWND)GetEditHWND(), + wxComboEditWndProc); } // and finally, show the control @@ -425,6 +420,52 @@ bool wxComboBox::Create(wxWindow *parent, wxWindowID id, return TRUE; } +bool wxComboBox::Create(wxWindow *parent, wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + const wxArrayString& choices, + long style, + const wxValidator& validator, + const wxString& name) +{ + wxCArrayString chs(choices); + return Create(parent, id, value, pos, size, chs.GetCount(), + chs.GetStrings(), style, validator, name); +} + +WXDWORD wxComboBox::MSWGetStyle(long style, WXDWORD *exstyle) const +{ + // we never have an external border + WXDWORD msStyle = wxChoice::MSWGetStyle + ( + (style & ~wxBORDER_MASK) | wxBORDER_NONE, exstyle + ); + + // remove the style always added by wxChoice + msStyle &= ~CBS_DROPDOWNLIST; + + if ( style & wxCB_READONLY ) + msStyle |= CBS_DROPDOWNLIST; +#ifndef __WXWINCE__ + else if ( style & wxCB_SIMPLE ) + msStyle |= CBS_SIMPLE; // A list (shown always) and edit control +#endif + else + msStyle |= CBS_DROPDOWN; + + // there is no reason to not always use CBS_AUTOHSCROLL, so do use it + msStyle |= CBS_AUTOHSCROLL; + + // NB: we used to also add CBS_NOINTEGRALHEIGHT here but why? + + return msStyle; +} + +// ---------------------------------------------------------------------------- +// wxComboBox text control-like methods +// ---------------------------------------------------------------------------- + void wxComboBox::SetValue(const wxString& value) { if ( HasFlag(wxCB_READONLY) ) @@ -540,18 +581,11 @@ void wxComboBox::SetSelection(long from, long to) toChar = -1; } - if ( -#ifdef __WIN32__ - SendMessage(hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELONG(fromChar, toChar)) -#else // Win16 - SendMessage(hWnd, CB_SETEDITSEL, (WPARAM)fromChar, (LPARAM)toChar) -#endif - == CB_ERR ) + if ( SendMessage(hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELONG(fromChar, toChar)) == CB_ERR ) { wxLogDebug(_T("CB_SETEDITSEL failed")); } } -#endif - // wxUSE_COMBOBOX +#endif // wxUSE_COMBOBOX