1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        univ/combobox.cpp 
   3 // Purpose:     wxComboControl and wxComboBox implementation 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 2000 SciTech Software, Inc. (www.scitechsoft.com) 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "univcombobox.h" 
  24 #include "wx/wxprec.h" 
  35     #include "wx/button.h" 
  36     #include "wx/combobox.h" 
  37     #include "wx/listbox.h" 
  38     #include "wx/textctrl.h" 
  39     #include "wx/bmpbuttn.h" 
  41     #include "wx/validate.h" 
  44 #include "wx/tooltip.h" 
  45 #include "wx/popupwin.h" 
  47 #include "wx/univ/renderer.h" 
  48 #include "wx/univ/inphand.h" 
  49 #include "wx/univ/theme.h" 
  52    The keyboard event flow: 
  54    1. they always come to the text ctrl 
  55    2. it forwards the ones it doesn't process to the wxComboControl 
  56    3. which passes them to the popup window if it is popped up 
  60 // ---------------------------------------------------------------------------- 
  62 // the margin between the text control and the combo button 
  63 static const wxCoord g_comboMargin 
= 2; 
  65 // ---------------------------------------------------------------------------- 
  66 // wxComboButton is just a normal button except that it sends commands to the 
  67 // combobox and not its parent 
  68 // ---------------------------------------------------------------------------- 
  70 class wxComboButton 
: public wxBitmapButton
 
  73     wxComboButton(wxComboControl 
*combo
) 
  74         : wxBitmapButton(combo
->GetParent(), wxID_ANY
, wxNullBitmap
, 
  75                          wxDefaultPosition
, wxDefaultSize
, 
  76                          wxBORDER_NONE 
| wxBU_EXACTFIT
) 
  80         wxBitmap bmpNormal
, bmpFocus
, bmpPressed
, bmpDisabled
; 
  82         GetRenderer()->GetComboBitmaps(&bmpNormal
, 
  87         SetBitmapLabel(bmpNormal
); 
  88         SetBitmapFocus(bmpFocus
.Ok() ? bmpFocus 
: bmpNormal
); 
  89         SetBitmapSelected(bmpPressed
.Ok() ? bmpPressed 
: bmpNormal
); 
  90         SetBitmapDisabled(bmpDisabled
.Ok() ? bmpDisabled 
: bmpNormal
); 
  92         SetBestSize(wxDefaultSize
); 
  96     void OnButton(wxCommandEvent
& WXUNUSED(event
)) { m_combo
->ShowPopup(); } 
  98     virtual wxSize 
DoGetBestClientSize() const 
 100         const wxBitmap
& bmp 
= GetBitmapLabel(); 
 102         return wxSize(bmp
.GetWidth(), bmp
.GetHeight()); 
 107     wxComboControl 
*m_combo
; 
 109     DECLARE_EVENT_TABLE() 
 112 // ---------------------------------------------------------------------------- 
 113 // wxComboListBox is a listbox modified to be used as a popup window in a 
 115 // ---------------------------------------------------------------------------- 
 117 class wxComboListBox 
: public wxListBox
, public wxComboPopup
 
 121     wxComboListBox(wxComboControl 
*combo
, int style 
= 0); 
 122     virtual ~wxComboListBox(); 
 124     // implement wxComboPopup methods 
 125     virtual bool SetSelection(const wxString
& value
); 
 126     virtual void SetSelection(int n
, bool select
) 
 127         { wxListBox::SetSelection( n
, select
); }; 
 128     virtual wxControl 
*GetControl() { return this; } 
 129     virtual void OnShow(); 
 130     virtual wxCoord 
GetBestWidth() const; 
 133     // we shouldn't return height too big from here 
 134     virtual wxSize 
DoGetBestClientSize() const; 
 136     // filter mouse move events happening outside the list box 
 137     void OnMouseMove(wxMouseEvent
& event
); 
 139     // set m_clicked value from here 
 140     void OnLeftUp(wxMouseEvent
& event
); 
 142     // called whenever the user selects or activates a listbox item 
 143     void OnSelect(wxCommandEvent
& event
); 
 145     // used to process wxUniv actions 
 146     bool PerformAction(const wxControlAction
& action
, 
 148                        const wxString
& strArg
); 
 151     // has the mouse been released on this control? 
 154     DECLARE_EVENT_TABLE() 
 157 // ---------------------------------------------------------------------------- 
 158 // wxComboTextCtrl is a simple text ctrl which forwards 
 159 // wxEVT_COMMAND_TEXT_UPDATED events and all key events to the combobox 
 160 // ---------------------------------------------------------------------------- 
 162 class wxComboTextCtrl 
: public wxTextCtrl
 
 165     wxComboTextCtrl(wxComboControl 
*combo
, 
 166                     const wxString
& value
, 
 168                     const wxValidator
& validator
); 
 171     void OnKey(wxKeyEvent
& event
); 
 172     void OnText(wxCommandEvent
& event
); 
 175     wxComboControl 
*m_combo
; 
 177     DECLARE_EVENT_TABLE() 
 180 // ---------------------------------------------------------------------------- 
 181 // event tables and such 
 182 // ---------------------------------------------------------------------------- 
 184 BEGIN_EVENT_TABLE(wxComboButton
, wxButton
) 
 185     EVT_BUTTON(wxID_ANY
, wxComboButton::OnButton
) 
 188 BEGIN_EVENT_TABLE(wxComboListBox
, wxListBox
) 
 189     EVT_LISTBOX(wxID_ANY
, wxComboListBox::OnSelect
) 
 190     EVT_LISTBOX_DCLICK(wxID_ANY
, wxComboListBox::OnSelect
) 
 191     EVT_MOTION(wxComboListBox::OnMouseMove
) 
 192     EVT_LEFT_UP(wxComboListBox::OnLeftUp
) 
 195 BEGIN_EVENT_TABLE(wxComboControl
, wxControl
) 
 196     EVT_KEY_DOWN(wxComboControl::OnKey
) 
 197     EVT_KEY_UP(wxComboControl::OnKey
) 
 200 BEGIN_EVENT_TABLE(wxComboTextCtrl
, wxTextCtrl
) 
 201     EVT_KEY_DOWN(wxComboTextCtrl::OnKey
) 
 202     EVT_KEY_UP(wxComboTextCtrl::OnKey
) 
 203     EVT_TEXT(wxID_ANY
, wxComboTextCtrl::OnText
) 
 206 IMPLEMENT_DYNAMIC_CLASS(wxComboBox
, wxControl
) 
 208 // ============================================================================ 
 210 // ============================================================================ 
 212 // ---------------------------------------------------------------------------- 
 213 // wxComboControl creation 
 214 // ---------------------------------------------------------------------------- 
 216 void wxComboControl::Init() 
 218     m_popup 
= (wxComboPopup 
*)NULL
; 
 219     m_winPopup 
= (wxPopupComboWindow 
*)NULL
; 
 220     m_isPopupShown 
= false; 
 225 bool wxComboControl::Create(wxWindow 
*parent
, 
 227                             const wxString
& value
, 
 231                             const wxValidator
& validator
, 
 232                             const wxString
& name
) 
 234     // first create our own window, i.e. the one which will contain all 
 236     style 
&= ~wxBORDER_NONE
; 
 237     style 
|= wxBORDER_SUNKEN
; 
 238     if ( !wxControl::Create(parent
, id
, pos
, size
, style
, validator
, name
) ) 
 241     // create the text control and the button as our siblings (*not* children), 
 242     // don't care about size/position here - they will be set in DoMoveWindow() 
 243     m_btn 
= new wxComboButton(this); 
 244     m_text 
= new wxComboTextCtrl(this, 
 246                                  style 
& wxCB_READONLY 
? wxTE_READONLY 
: 0, 
 249     // for compatibility with the other ports, the height specified is the 
 250     // combined height of the combobox itself and the popup 
 251     if ( size
.y 
== wxDefaultCoord 
) 
 253         // ok, use default height for popup too 
 254         m_heightPopup 
= wxDefaultCoord
; 
 258         m_heightPopup 
= size
.y 
- DoGetBestSize().y
; 
 264     // create the popup window immediately here to allow creating the controls 
 265     // with parent == GetPopupWindow() from the derived class ctor 
 266     m_winPopup 
= new wxPopupComboWindow(this); 
 268     // have to disable this window to avoid interfering it with message 
 269     // processing to the text and the button... but pretend it is enabled to 
 270     // make IsEnabled() return true 
 271     wxControl::Enable(false); // don't use non virtual Disable() here! 
 274     CreateInputHandler(wxINP_HANDLER_COMBOBOX
); 
 279 wxComboControl::~wxComboControl() 
 281     // as the button and the text control are the parent's children and not 
 282     // ours, we have to delete them manually - they are not deleted 
 283     // automatically by wxWidgets when we're deleted 
 290 // ---------------------------------------------------------------------------- 
 292 // ---------------------------------------------------------------------------- 
 294 void wxComboControl::DoSetSize(int x
, int y
, 
 295                                int width
, int WXUNUSED(height
), 
 298     // combo height is always fixed 
 299     wxControl::DoSetSize(x
, y
, width
, DoGetBestSize().y
, sizeFlags
); 
 302 wxSize 
wxComboControl::DoGetBestClientSize() const 
 304     wxSize sizeBtn 
= m_btn
->GetBestSize(), 
 305            sizeText 
= m_text
->GetBestSize(); 
 306     wxCoord widthPopup 
= 0; 
 310         widthPopup 
= m_popup
->GetBestWidth(); 
 313     return wxSize(wxMax(sizeText
.x 
+ g_comboMargin 
+ sizeBtn
.x
, widthPopup
),  
 314                   wxMax(sizeBtn
.y
, sizeText
.y
)); 
 317 void wxComboControl::DoMoveWindow(int x
, int y
, int width
, int height
) 
 319     wxControl::DoMoveWindow(x
, y
, width
, height
); 
 321     // position the subcontrols inside the client area 
 322     wxRect rectBorders 
= GetRenderer()->GetBorderDimensions(GetBorder()); 
 325     width 
-= rectBorders
.x 
+ rectBorders
.width
; 
 326     height 
-= rectBorders
.y 
+ rectBorders
.height
; 
 328     wxSize sizeBtn 
= m_btn
->GetBestSize(); 
 330     wxCoord wText 
= width 
- sizeBtn
.x
; 
 331     wxPoint p 
= GetParent() ? GetParent()->GetClientAreaOrigin() : wxPoint(0,0); 
 332     m_text
->SetSize(x 
- p
.x
, y 
- p
.y
, wText
, height
); 
 333     m_btn
->SetSize(x 
- p
.x 
+ wText
, y 
- p
.y
, sizeBtn
.x
, height
); 
 336 // ---------------------------------------------------------------------------- 
 338 // ---------------------------------------------------------------------------- 
 340 bool wxComboControl::Enable(bool enable
) 
 342     if ( !wxControl::Enable(enable
) ) 
 345     m_btn
->Enable(enable
); 
 346     m_text
->Enable(enable
); 
 351 bool wxComboControl::Show(bool show
) 
 353     if ( !wxControl::Show(show
) ) 
 366 void wxComboControl::DoSetToolTip(wxToolTip 
*tooltip
) 
 368     wxControl::DoSetToolTip(tooltip
);     
 370     // Set tool tip for button and text box 
 375             const wxString 
&tip 
= tooltip
->GetTip(); 
 376             m_text
->SetToolTip(tip
); 
 377             m_btn
->SetToolTip(tip
); 
 381             m_text
->SetToolTip(NULL
); 
 382             m_btn
->SetToolTip(NULL
); 
 386 #endif // wxUSE_TOOLTIPS 
 388 // ---------------------------------------------------------------------------- 
 389 // popup window handling 
 390 // ---------------------------------------------------------------------------- 
 392 void wxComboControl::SetPopupControl(wxComboPopup 
*popup
) 
 397 void wxComboControl::ShowPopup() 
 399     wxCHECK_RET( m_popup
, _T("no popup to show in wxComboControl") ); 
 400     wxCHECK_RET( !IsPopupShown(), _T("popup window already shown") ); 
 402     wxControl 
*control 
= m_popup
->GetControl(); 
 404     // size and position the popup window correctly 
 405     m_winPopup
->SetSize(GetSize().x
, 
 406                         m_heightPopup 
== wxDefaultCoord 
? control
->GetBestSize().y
 
 408     wxSize sizePopup 
= m_winPopup
->GetClientSize(); 
 409     control
->SetSize(0, 0, sizePopup
.x
, sizePopup
.y
); 
 411     // some controls don't accept the size we give then: e.g. a listbox may 
 412     // require more space to show its last row 
 413     wxSize sizeReal 
= control
->GetSize(); 
 414     if ( sizeReal 
!= sizePopup 
) 
 416         m_winPopup
->SetClientSize(sizeReal
); 
 419     m_winPopup
->PositionNearCombo(); 
 423     m_winPopup
->Popup(m_text
); 
 425     m_popup
->SetSelection(m_text
->GetValue()); 
 427     m_isPopupShown 
= true; 
 430 void wxComboControl::HidePopup() 
 432     wxCHECK_RET( m_popup
, _T("no popup to hide in wxComboControl") ); 
 433     wxCHECK_RET( IsPopupShown(), _T("popup window not shown") ); 
 435     m_winPopup
->Dismiss(); 
 437     m_isPopupShown 
= false; 
 440 void wxComboControl::OnSelect(const wxString
& value
) 
 442     m_text
->SetValue(value
); 
 448 void wxComboControl::OnDismiss() 
 454 // ---------------------------------------------------------------------------- 
 456 // ---------------------------------------------------------------------------- 
 458 wxComboTextCtrl::wxComboTextCtrl(wxComboControl 
*combo
, 
 459                                  const wxString
& value
, 
 461                                  const wxValidator
& validator
) 
 462                : wxTextCtrl(combo
->GetParent(), wxID_ANY
, value
, 
 463                             wxDefaultPosition
, wxDefaultSize
, 
 464                             wxBORDER_NONE 
| style
, 
 470 void wxComboTextCtrl::OnText(wxCommandEvent
& event
) 
 472     if ( m_combo
->IsPopupShown() ) 
 474         m_combo
->GetPopupControl()->SetSelection(GetValue()); 
 477     // we need to make a copy of the event to have the correct originating 
 479     wxCommandEvent event2 
= event
; 
 480     event2
.SetEventObject(m_combo
); 
 481     event2
.SetId(m_combo
->GetId()); 
 483     // there is a small incompatibility with wxMSW here: the combobox gets the 
 484     // event before the text control in our case which corresponds to SMW 
 485     // CBN_EDITUPDATE notification and not CBN_EDITCHANGE one wxMSW currently 
 488     // if this is really a problem, we can play games with the event handlers 
 489     // to circumvent this 
 490     (void)m_combo
->ProcessEvent(event2
); 
 495 // pass the keys we don't process to the combo first 
 496 void wxComboTextCtrl::OnKey(wxKeyEvent
& event
) 
 498     switch ( event
.GetKeyCode() ) 
 501             // the popup control gets it first but only if it is shown 
 502             if ( !m_combo
->IsPopupShown() ) 
 513             (void)m_combo
->ProcessEvent(event
); 
 520 // ---------------------------------------------------------------------------- 
 522 // ---------------------------------------------------------------------------- 
 524 wxComboListBox::wxComboListBox(wxComboControl 
*combo
, int style
) 
 525               : wxListBox(combo
->GetPopupWindow(), wxID_ANY
, 
 526                           wxDefaultPosition
, wxDefaultSize
, 
 528                           wxBORDER_SIMPLE 
| wxLB_INT_HEIGHT 
| style
), 
 531     // we don't react to the mouse events outside the window at all 
 535 wxComboListBox::~wxComboListBox() 
 539 bool wxComboListBox::SetSelection(const wxString
& value
) 
 541     // FindItem() would just find the current item for an empty string (it 
 542     // always matches), but we want to show the first one in such case 
 547             wxListBox::SetSelection(0); 
 549         //else: empty listbox - nothing to do 
 551     else if ( !FindItem(value
) ) 
 560 void wxComboListBox::OnSelect(wxCommandEvent
& event
) 
 564         // first update the combo and close the listbox 
 565         m_combo
->OnSelect(event
.GetString()); 
 567         // next let the user code have the event 
 569         // all fields are already filled by the listbox, just change the event 
 570         // type and send it to the combo 
 571         wxCommandEvent event2 
= event
; 
 572         event2
.SetEventType(wxEVT_COMMAND_COMBOBOX_SELECTED
); 
 573         event2
.SetEventObject(m_combo
); 
 574         event2
.SetId(m_combo
->GetId()); 
 575         m_combo
->ProcessEvent(event2
); 
 577     //else: ignore the events resultign from just moving the mouse initially 
 580 void wxComboListBox::OnShow() 
 582     // nobody clicked us yet 
 586 bool wxComboListBox::PerformAction(const wxControlAction
& action
, 
 588                                    const wxString
& strArg
) 
 591     if ( action 
== wxACTION_LISTBOX_FIND 
) 
 593         // we don't let the listbox handle this as instead of just using the 
 594         // single key presses, as usual, we use the text ctrl value as prefix 
 595         // and this is done by wxComboControl itself 
 599     return wxListBox::PerformAction(action
, numArg
, strArg
); 
 602 void wxComboListBox::OnLeftUp(wxMouseEvent
& event
) 
 604     // we should dismiss the combo now 
 610 void wxComboListBox::OnMouseMove(wxMouseEvent
& event
) 
 612     // while a wxComboListBox is shown, it always has capture, so if it doesn't 
 613     // we're about to go away anyhow (normally this shouldn't happen at all, 
 614     // but I don't put assert here as it just might do on other platforms and 
 615     // it doesn't break anythign anyhow) 
 616     if ( this == wxWindow::GetCapture() ) 
 618         if ( HitTest(event
.GetPosition()) == wxHT_WINDOW_INSIDE 
) 
 622         //else: popup shouldn't react to the mouse motions outside it, it only 
 623         //      captures the mouse to be able to detect when it must be 
 624         //      dismissed, so don't call Skip() 
 628 wxCoord 
wxComboListBox::GetBestWidth() const 
 630     wxSize size 
= wxListBox::GetBestSize(); 
 634 wxSize 
wxComboListBox::DoGetBestClientSize() const 
 636     // don't return size too big or we risk to not fit on the screen 
 637     wxSize size 
= wxListBox::DoGetBestClientSize(); 
 638     wxCoord hChar 
= GetCharHeight(); 
 640     int nLines 
= size
.y 
/ hChar
; 
 642     // 10 is the same limit as used by wxMSW 
 651 // ---------------------------------------------------------------------------- 
 653 // ---------------------------------------------------------------------------- 
 655 void wxComboBox::Init() 
 657     m_lbox 
= (wxListBox 
*)NULL
; 
 660 wxComboBox::wxComboBox(wxWindow 
*parent
, 
 662                        const wxString
& value
, 
 665                        const wxArrayString
& choices
, 
 667                        const wxValidator
& validator
, 
 668                        const wxString
& name
) 
 672     Create(parent
, id
, value
, pos
, size
, choices
, style
, validator
, name
); 
 675 bool wxComboBox::Create(wxWindow 
*parent
, 
 677                         const wxString
& value
, 
 680                         const wxArrayString
& choices
, 
 682                         const wxValidator
& validator
, 
 683                         const wxString
& name
) 
 685     wxCArrayString 
chs(choices
); 
 687     return Create(parent
, id
, value
, pos
, size
, chs
.GetCount(), 
 688                   chs
.GetStrings(), style
, validator
, name
); 
 691 bool wxComboBox::Create(wxWindow 
*parent
, 
 693                         const wxString
& value
, 
 697                         const wxString choices
[], 
 699                         const wxValidator
& validator
, 
 700                         const wxString
& name
) 
 702     if ( !wxComboControl::Create(parent
, id
, value
, pos
, size
, style
, 
 708     wxComboListBox 
*combolbox 
= 
 709         new wxComboListBox(this, style 
& wxCB_SORT 
? wxLB_SORT 
: 0); 
 711     m_lbox
->Set(n
, choices
); 
 713     SetPopupControl(combolbox
); 
 718 wxComboBox::~wxComboBox() 
 722 // ---------------------------------------------------------------------------- 
 723 // wxComboBox methods forwarded to wxTextCtrl 
 724 // ---------------------------------------------------------------------------- 
 726 wxString 
wxComboBox::GetValue() const 
 728     return GetText()->GetValue(); 
 731 void wxComboBox::SetValue(const wxString
& value
) 
 733     GetText()->SetValue(value
); 
 736 void wxComboBox::Copy() 
 741 void wxComboBox::Cut() 
 746 void wxComboBox::Paste() 
 751 void wxComboBox::SetInsertionPoint(long pos
) 
 753     GetText()->SetInsertionPoint(pos
); 
 756 void wxComboBox::SetInsertionPointEnd() 
 758     GetText()->SetInsertionPointEnd(); 
 761 long wxComboBox::GetInsertionPoint() const 
 763     return GetText()->GetInsertionPoint(); 
 766 long wxComboBox::GetLastPosition() const 
 768     return GetText()->GetLastPosition(); 
 771 void wxComboBox::Replace(long from
, long to
, const wxString
& value
) 
 773     GetText()->Replace(from
, to
, value
); 
 776 void wxComboBox::Remove(long from
, long to
) 
 778     GetText()->Remove(from
, to
); 
 781 void wxComboBox::SetSelection(long from
, long to
) 
 783     GetText()->SetSelection(from
, to
); 
 786 void wxComboBox::SetEditable(bool editable
) 
 788     GetText()->SetEditable(editable
); 
 791 // ---------------------------------------------------------------------------- 
 792 // wxComboBox methods forwarded to wxListBox 
 793 // ---------------------------------------------------------------------------- 
 795 void wxComboBox::Clear() 
 798     GetText()->SetValue(wxEmptyString
); 
 801 void wxComboBox::Delete(int n
) 
 803     wxCHECK_RET( (n 
>= 0) && (n 
< GetCount()), _T("invalid index in wxComboBox::Delete") ); 
 805     if (GetSelection() == n
) 
 806         GetText()->SetValue(wxEmptyString
); 
 808     GetLBox()->Delete(n
); 
 811 int wxComboBox::GetCount() const 
 813     return GetLBox()->GetCount(); 
 816 wxString 
wxComboBox::GetString(int n
) const 
 818     wxCHECK_MSG( (n 
>= 0) && (n 
< GetCount()), wxEmptyString
, _T("invalid index in wxComboBox::GetString") ); 
 820     return GetLBox()->GetString(n
); 
 823 void wxComboBox::SetString(int n
, const wxString
& s
) 
 825     wxCHECK_RET( (n 
>= 0) && (n 
< GetCount()), _T("invalid index in wxComboBox::SetString") ); 
 827     GetLBox()->SetString(n
, s
); 
 830 int wxComboBox::FindString(const wxString
& s
) const 
 832     return GetLBox()->FindString(s
); 
 835 void wxComboBox::Select(int n
) 
 837     wxCHECK_RET( (n 
>= 0) && (n 
< GetCount()), _T("invalid index in wxComboBox::Select") ); 
 839     GetLBox()->SetSelection(n
); 
 840     GetText()->SetValue(GetLBox()->GetString(n
)); 
 843 int wxComboBox::GetSelection() const 
 845 #if 1 // FIXME:: What is the correct behavior? 
 846     // if the current value isn't one of the listbox strings, return -1 
 847     return GetLBox()->GetSelection(); 
 849     // Why oh why is this done this way?  
 850     // It is not because the value displayed in the text can be found  
 851     // in the list that it is the item that is selected! 
 852     return FindString(GetText()->GetValue()); 
 856 int wxComboBox::DoAppend(const wxString
& item
) 
 858     return GetLBox()->Append(item
); 
 861 int wxComboBox::DoInsert(const wxString
& item
, int pos
) 
 863     wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT
), -1, wxT("can't insert into sorted list")); 
 864     wxCHECK_MSG((pos
>=0) && (pos
<=GetCount()), -1, wxT("invalid index")); 
 866     if (pos 
== GetCount()) 
 867         return DoAppend(item
); 
 869     GetLBox()->Insert(item
, pos
); 
 873 void wxComboBox::DoSetItemClientData(int n
, void* clientData
) 
 875     GetLBox()->SetClientData(n
, clientData
); 
 878 void *wxComboBox::DoGetItemClientData(int n
) const 
 880     return GetLBox()->GetClientData(n
); 
 883 void wxComboBox::DoSetItemClientObject(int n
, wxClientData
* clientData
) 
 885     GetLBox()->SetClientObject(n
, clientData
); 
 888 wxClientData
* wxComboBox::DoGetItemClientObject(int n
) const 
 890     return GetLBox()->GetClientObject(n
); 
 893 // ---------------------------------------------------------------------------- 
 895 // ---------------------------------------------------------------------------- 
 897 void wxComboControl::OnKey(wxKeyEvent
& event
) 
 899     if ( m_isPopupShown 
) 
 901         // pass it to the popped up control 
 902         (void)m_popup
->GetControl()->ProcessEvent(event
); 
 910 bool wxComboControl::PerformAction(const wxControlAction
& action
, 
 912                                    const wxString
& strArg
) 
 914     bool processed 
= false; 
 915     if ( action 
== wxACTION_COMBOBOX_POPUP 
) 
 917         if ( !m_isPopupShown 
) 
 924     else if ( action 
== wxACTION_COMBOBOX_DISMISS 
) 
 926         if ( m_isPopupShown 
) 
 937         return wxControl::PerformAction(action
, numArg
, strArg
); 
 943 // ---------------------------------------------------------------------------- 
 944 // wxStdComboBoxInputHandler 
 945 // ---------------------------------------------------------------------------- 
 947 wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler 
*inphand
) 
 948                          : wxStdInputHandler(inphand
) 
 952 bool wxStdComboBoxInputHandler::HandleKey(wxInputConsumer 
*consumer
, 
 953                                           const wxKeyEvent
& event
, 
 958         wxControlAction action
; 
 959         switch ( event
.GetKeyCode() ) 
 962                 action 
= wxACTION_COMBOBOX_POPUP
; 
 966                 action 
= wxACTION_COMBOBOX_DISMISS
; 
 970         if ( !action
.IsEmpty() ) 
 972             consumer
->PerformAction(action
); 
 978     return wxStdInputHandler::HandleKey(consumer
, event
, pressed
); 
 981 #endif // wxUSE_COMBOBOX