1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  11 #pragma implementation "combobox.h" 
  14 #include "wx/combobox.h" 
  18 #include "wx/settings.h" 
  21 #include "wx/textctrl.h"    // for wxEVT_COMMAND_TEXT_UPDATED 
  23 #include "wx/gtk/private.h" 
  25 //----------------------------------------------------------------------------- 
  27 //----------------------------------------------------------------------------- 
  29 extern void wxapp_install_idle_handler(); 
  32 //----------------------------------------------------------------------------- 
  34 //----------------------------------------------------------------------------- 
  36 extern bool   g_blockEventsOnDrag
; 
  38 //----------------------------------------------------------------------------- 
  40 //----------------------------------------------------------------------------- 
  43 gtk_combo_clicked_callback( GtkWidget 
*WXUNUSED(widget
), wxComboBox 
*combo 
) 
  45     if (g_isIdle
) wxapp_install_idle_handler(); 
  47     if (!combo
->m_hasVMT
) return; 
  49     if (g_blockEventsOnDrag
) return; 
  51     if (combo
->m_alreadySent
) 
  53         combo
->m_alreadySent 
= FALSE
; 
  57     combo
->m_alreadySent 
= TRUE
; 
  59     int curSelection 
= combo
->GetSelection(); 
  61     if (combo
->m_prevSelection 
!= curSelection
) 
  63         GtkWidget 
*list 
= GTK_COMBO(combo
->m_widget
)->list
; 
  64         gtk_list_unselect_item( GTK_LIST(list
), combo
->m_prevSelection 
); 
  67     combo
->m_prevSelection 
= curSelection
; 
  69     wxCommandEvent 
event( wxEVT_COMMAND_COMBOBOX_SELECTED
, combo
->GetId() ); 
  70     event
.SetInt( curSelection 
); 
  71     event
.SetString( combo
->GetStringSelection() ); 
  72     event
.SetEventObject( combo 
); 
  74     combo
->GetEventHandler()->ProcessEvent( event 
); 
  77 //----------------------------------------------------------------------------- 
  79 //----------------------------------------------------------------------------- 
  82 gtk_text_changed_callback( GtkWidget 
*WXUNUSED(widget
), wxComboBox 
*combo 
) 
  84     if (g_isIdle
) wxapp_install_idle_handler(); 
  86     if (!combo
->m_hasVMT
) return; 
  88     wxCommandEvent 
event( wxEVT_COMMAND_TEXT_UPDATED
, combo
->GetId() ); 
  89     event
.SetString( combo
->GetValue() ); 
  90     event
.SetEventObject( combo 
); 
  91     combo
->GetEventHandler()->ProcessEvent( event 
); 
  94 //----------------------------------------------------------------------------- 
  96 //----------------------------------------------------------------------------- 
  98 IMPLEMENT_DYNAMIC_CLASS(wxComboBox
,wxControl
) 
 100 BEGIN_EVENT_TABLE(wxComboBox
, wxControl
) 
 101     EVT_SIZE(wxComboBox::OnSize
) 
 102     EVT_CHAR(wxComboBox::OnChar
) 
 105 bool wxComboBox::Create( wxWindow 
*parent
, wxWindowID id
, const wxString
& value
, 
 106                          const wxPoint
& pos
, const wxSize
& size
, 
 107                          int n
, const wxString choices
[], 
 108                          long style
, const wxValidator
& validator
, 
 109                          const wxString
& name 
) 
 111     m_alreadySent 
= FALSE
; 
 113     m_acceptsFocus 
= TRUE
; 
 116     if (!PreCreation( parent
, pos
, size 
) || 
 117         !CreateBase( parent
, id
, pos
, size
, style
, validator
, name 
)) 
 119         wxFAIL_MSG( wxT("wxComboBox creation failed") ); 
 123     m_widget 
= gtk_combo_new(); 
 125     // make it more useable 
 126     gtk_combo_set_use_arrows_always( GTK_COMBO(m_widget
), TRUE 
); 
 128     // and case-sensitive 
 129     gtk_combo_set_case_sensitive( GTK_COMBO(m_widget
), TRUE 
); 
 132     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 135     // gtk_list_set_selection_mode( GTK_LIST(list), GTK_SELECTION_MULTIPLE ); 
 138     for (int i 
= 0; i 
< n
; i
++) 
 140         /* don't send first event, which GTK sends aways when 
 141            inserting the first item */ 
 142         m_alreadySent 
= TRUE
; 
 144         GtkWidget 
*list_item 
= gtk_list_item_new_with_label( wxGTK_CONV( choices
[i
] ) ); 
 146         m_clientDataList
.Append( (wxObject
*)NULL 
); 
 147         m_clientObjectList
.Append( (wxObject
*)NULL 
); 
 149         gtk_container_add( GTK_CONTAINER(list
), list_item 
); 
 151         gtk_signal_connect( GTK_OBJECT(list_item
), "select", 
 152            GTK_SIGNAL_FUNC(gtk_combo_clicked_callback
), (gpointer
)this ); 
 154         gtk_widget_show( list_item 
); 
 157     m_parent
->DoAddChild( this ); 
 159     m_focusWidget 
= GTK_COMBO(m_widget
)->entry
; 
 163     ConnectWidget( GTK_COMBO(m_widget
)->button 
); 
 165     if (!value
.IsNull()) SetValue( value 
); 
 167     if (style 
& wxCB_READONLY
) 
 168         gtk_entry_set_editable( GTK_ENTRY( GTK_COMBO(m_widget
)->entry 
), FALSE 
); 
 170     gtk_signal_connect( GTK_OBJECT(GTK_COMBO(m_widget
)->entry
), "changed", 
 171       GTK_SIGNAL_FUNC(gtk_text_changed_callback
), (gpointer
)this); 
 173     wxSize 
size_best( DoGetBestSize() ); 
 174     wxSize 
new_size( size 
); 
 175     if (new_size
.x 
== -1) 
 176         new_size
.x 
= size_best
.x
; 
 177     if (new_size
.y 
== -1) 
 178         new_size
.y 
= size_best
.y
; 
 179     if (new_size
.y 
> size_best
.y
) 
 180         new_size
.y 
= size_best
.y
; 
 181     if ((new_size
.x 
!= size
.x
) || (new_size
.y 
!= size
.y
)) 
 183         SetSize( new_size
.x
, new_size
.y 
); 
 185         // This is required for tool bar support 
 186         gtk_widget_set_usize( m_widget
, new_size
.x
, new_size
.y 
); 
 190     SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW 
) ); 
 191     SetForegroundColour( parent
->GetForegroundColour() ); 
 198 wxComboBox::~wxComboBox() 
 200     wxNode 
*node 
= m_clientObjectList
.First(); 
 203         wxClientData 
*cd 
= (wxClientData
*)node
->Data(); 
 207     m_clientObjectList
.Clear(); 
 209     m_clientDataList
.Clear(); 
 212 void wxComboBox::SetFocus() 
 216         // don't do anything if we already have focus 
 220     gtk_widget_grab_focus( m_focusWidget 
); 
 223 void wxComboBox::AppendCommon( const wxString 
&item 
) 
 225     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 227     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 229     GtkWidget 
*list_item 
= gtk_list_item_new_with_label( wxGTK_CONV( item 
) ); 
 231     gtk_container_add( GTK_CONTAINER(list
), list_item 
); 
 233     gtk_signal_connect( GTK_OBJECT(list_item
), "select", 
 234       GTK_SIGNAL_FUNC(gtk_combo_clicked_callback
), (gpointer
)this ); 
 236     if (GTK_WIDGET_REALIZED(m_widget
)) 
 238         gtk_widget_realize( list_item 
); 
 239         gtk_widget_realize( GTK_BIN(list_item
)->child 
); 
 241         if (m_widgetStyle
) ApplyWidgetStyle(); 
 244     gtk_widget_show( list_item 
); 
 247 void wxComboBox::Append( const wxString 
&item 
) 
 249     m_clientDataList
.Append( (wxObject
*) NULL 
); 
 250     m_clientObjectList
.Append( (wxObject
*) NULL 
); 
 252     AppendCommon( item 
); 
 255 void wxComboBox::Append( const wxString 
&item
, void *clientData 
) 
 257     m_clientDataList
.Append( (wxObject
*) clientData 
); 
 258     m_clientObjectList
.Append( (wxObject
*)NULL 
); 
 260     AppendCommon( item 
); 
 263 void wxComboBox::Append( const wxString 
&item
, wxClientData 
*clientData 
) 
 265     m_clientDataList
.Append( (wxObject
*) NULL 
); 
 266     m_clientObjectList
.Append( (wxObject
*) clientData 
); 
 268     AppendCommon( item 
); 
 271 void wxComboBox::SetClientData( int n
, void* clientData 
) 
 273     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 275     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 278     node
->SetData( (wxObject
*) clientData 
); 
 281 void* wxComboBox::GetClientData( int n 
) 
 283     wxCHECK_MSG( m_widget 
!= NULL
, NULL
, wxT("invalid combobox") ); 
 285     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 286     if (!node
) return NULL
; 
 291 void wxComboBox::SetClientObject( int n
, wxClientData
* clientData 
) 
 293     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 295     wxNode 
*node 
= m_clientObjectList
.Nth( n 
); 
 298     wxClientData 
*cd 
= (wxClientData
*) node
->Data(); 
 301     node
->SetData( (wxObject
*) clientData 
); 
 304 wxClientData
* wxComboBox::GetClientObject( int n 
) 
 306     wxCHECK_MSG( m_widget 
!= NULL
, (wxClientData
*)NULL
, wxT("invalid combobox") ); 
 308     wxNode 
*node 
= m_clientObjectList
.Nth( n 
); 
 309     if (!node
) return (wxClientData
*) NULL
; 
 311     return (wxClientData
*) node
->Data(); 
 314 void wxComboBox::Clear() 
 316     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 318     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 319     gtk_list_clear_items( GTK_LIST(list
), 0, Number() ); 
 321     wxNode 
*node 
= m_clientObjectList
.First(); 
 324         wxClientData 
*cd 
= (wxClientData
*)node
->Data(); 
 328     m_clientObjectList
.Clear(); 
 330     m_clientDataList
.Clear(); 
 333 void wxComboBox::Delete( int n 
) 
 335     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 337     GtkList 
*listbox 
= GTK_LIST( GTK_COMBO(m_widget
)->list 
); 
 339     GList 
*child 
= g_list_nth( listbox
->children
, n 
); 
 343         wxFAIL_MSG(wxT("wrong index")); 
 347     GList 
*list 
= g_list_append( (GList
*) NULL
, child
->data 
); 
 348     gtk_list_remove_items( listbox
, list 
); 
 351     wxNode 
*node 
= m_clientObjectList
.Nth( n 
); 
 354         wxClientData 
*cd 
= (wxClientData
*)node
->Data(); 
 356         m_clientObjectList
.DeleteNode( node 
); 
 359     node 
= m_clientDataList
.Nth( n 
); 
 362         m_clientDataList
.DeleteNode( node 
); 
 366 int wxComboBox::FindString( const wxString 
&item 
) 
 368     wxCHECK_MSG( m_widget 
!= NULL
, -1, wxT("invalid combobox") ); 
 370     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 372     GList 
*child 
= GTK_LIST(list
)->children
; 
 376         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 377         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 379         wxString 
str( wxGTK_CONV_BACK( gtk_label_get_text(label
) ) ); 
 381         wxString 
str( label
->label 
); 
 393 int wxComboBox::GetSelection() const 
 395     wxCHECK_MSG( m_widget 
!= NULL
, -1, wxT("invalid combobox") ); 
 397     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 399     GList 
*selection 
= GTK_LIST(list
)->selection
; 
 402         GList 
*child 
= GTK_LIST(list
)->children
; 
 406             if (child
->data 
== selection
->data
) return count
; 
 415 wxString 
wxComboBox::GetString( int n 
) const 
 417     wxCHECK_MSG( m_widget 
!= NULL
, wxT(""), wxT("invalid combobox") ); 
 419     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 422     GList 
*child 
= g_list_nth( GTK_LIST(list
)->children
, n 
); 
 425         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 426         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 428         str 
= wxGTK_CONV_BACK( gtk_label_get_text(label
) ); 
 430         str 
= wxString( label
->label 
); 
 435         wxFAIL_MSG( wxT("wxComboBox: wrong index") ); 
 441 wxString 
wxComboBox::GetStringSelection() const 
 443     wxCHECK_MSG( m_widget 
!= NULL
, wxT(""), wxT("invalid combobox") ); 
 445     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 447     GList 
*selection 
= GTK_LIST(list
)->selection
; 
 450         GtkBin 
*bin 
= GTK_BIN( selection
->data 
); 
 451         GtkLabel 
*label 
= GTK_LABEL( bin
->child 
); 
 453         wxString 
tmp( wxGTK_CONV_BACK( gtk_label_get_text(label
) ) ); 
 455         wxString 
tmp( label
->label 
); 
 460     wxFAIL_MSG( wxT("wxComboBox: no selection") ); 
 465 int wxComboBox::Number() const 
 467     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid combobox") ); 
 469     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 471     GList 
*child 
= GTK_LIST(list
)->children
; 
 473     while (child
) { count
++; child 
= child
->next
; } 
 477 void wxComboBox::SetSelection( int n 
) 
 479     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 483     GtkWidget 
*list 
= GTK_COMBO(m_widget
)->list
; 
 484     gtk_list_unselect_item( GTK_LIST(list
), m_prevSelection 
); 
 485     gtk_list_select_item( GTK_LIST(list
), n 
); 
 491 void wxComboBox::SetStringSelection( const wxString 
&string 
) 
 493     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 495     int res 
= FindString( string 
); 
 496     if (res 
== -1) return; 
 500 wxString 
wxComboBox::GetValue() const 
 502     GtkEntry 
*entry 
= GTK_ENTRY( GTK_COMBO(m_widget
)->entry 
); 
 503     wxString 
tmp( wxGTK_CONV_BACK( gtk_entry_get_text( entry 
) ) ); 
 506     for (int i 
= 0; i 
< wxStrlen(tmp
.c_str()) +1; i
++) 
 509         printf( "%d ", (int) (c
) ); 
 517 void wxComboBox::SetValue( const wxString
& value 
) 
 519     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 521     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 522     wxString tmp 
= wxT(""); 
 523     if (!value
.IsNull()) tmp 
= value
; 
 524     gtk_entry_set_text( GTK_ENTRY(entry
), wxGTK_CONV( tmp 
) ); 
 527 void wxComboBox::Copy() 
 529     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 531     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 532     gtk_editable_copy_clipboard( GTK_EDITABLE(entry
) DUMMY_CLIPBOARD_ARG 
); 
 535 void wxComboBox::Cut() 
 537     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 539     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 540     gtk_editable_cut_clipboard( GTK_EDITABLE(entry
) DUMMY_CLIPBOARD_ARG 
); 
 543 void wxComboBox::Paste() 
 545     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 547     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 548     gtk_editable_paste_clipboard( GTK_EDITABLE(entry
) DUMMY_CLIPBOARD_ARG
); 
 551 void wxComboBox::SetInsertionPoint( long pos 
) 
 553     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 555     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 556     gtk_entry_set_position( GTK_ENTRY(entry
), (int)pos 
); 
 559 void wxComboBox::SetInsertionPointEnd() 
 561     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 563     SetInsertionPoint( -1 ); 
 566 long wxComboBox::GetInsertionPoint() const 
 568     return (long) GET_EDITABLE_POS( GTK_COMBO(m_widget
)->entry 
); 
 571 long wxComboBox::GetLastPosition() const 
 573     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 574     int pos 
= GTK_ENTRY(entry
)->text_length
; 
 578 void wxComboBox::Replace( long from
, long to
, const wxString
& value 
) 
 580     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 582     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 583     gtk_editable_delete_text( GTK_EDITABLE(entry
), (gint
)from
, (gint
)to 
); 
 584     if (value
.IsNull()) return; 
 588     wxCharBuffer buffer 
= wxConvUTF8
.cWX2MB( value 
); 
 589     gtk_editable_insert_text( GTK_EDITABLE(entry
), (const char*) buffer
, strlen( (const char*) buffer 
), &pos 
); 
 591     gtk_editable_insert_text( GTK_EDITABLE(entry
), value
.c_str(), value
.Length(), &pos 
); 
 595 void wxComboBox::Remove(long from
, long to
) 
 597     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid combobox") ); 
 599     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 600     gtk_editable_delete_text( GTK_EDITABLE(entry
), (gint
)from
, (gint
)to 
); 
 603 void wxComboBox::SetSelection( long from
, long to 
) 
 605     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 606     gtk_editable_select_region( GTK_EDITABLE(entry
), (gint
)from
, (gint
)to 
); 
 609 void wxComboBox::SetEditable( bool editable 
) 
 611     GtkWidget 
*entry 
= GTK_COMBO(m_widget
)->entry
; 
 612     gtk_entry_set_editable( GTK_ENTRY(entry
), editable 
); 
 615 void wxComboBox::OnChar( wxKeyEvent 
&event 
) 
 617     if ( event
.GetKeyCode() == WXK_RETURN 
) 
 619         wxString value 
= GetValue(); 
 623             // make Enter generate "selected" event if there is only one item 
 624             // in the combobox - without it, it's impossible to select it at 
 626             wxCommandEvent 
event( wxEVT_COMMAND_COMBOBOX_SELECTED
, GetId() ); 
 628             event
.SetString( value 
); 
 629             event
.SetEventObject( this ); 
 630             GetEventHandler()->ProcessEvent( event 
); 
 634             // add the item to the list if it's not there yet 
 635             if ( FindString(value
) == wxNOT_FOUND 
) 
 638                 SetStringSelection(value
); 
 640                 // and generate the selected event for it 
 641                 wxCommandEvent 
event( wxEVT_COMMAND_COMBOBOX_SELECTED
, GetId() ); 
 642                 event
.SetInt( Number() - 1 ); 
 643                 event
.SetString( value 
); 
 644                 event
.SetEventObject( this ); 
 645                 GetEventHandler()->ProcessEvent( event 
); 
 648             // This will invoke the dialog default action, such 
 649             // as the clicking the default button. 
 651             wxWindow 
*top_frame 
= m_parent
; 
 652             while (top_frame
->GetParent() && !(top_frame
->IsTopLevel())) 
 653             top_frame 
= top_frame
->GetParent(); 
 655             if (top_frame 
&& GTK_IS_WINDOW(top_frame
->m_widget
)) 
 657                 GtkWindow 
*window 
= GTK_WINDOW(top_frame
->m_widget
); 
 659                 if (window
->default_widget
) 
 661                     gtk_widget_activate (window
->default_widget
); 
 673 void wxComboBox::DisableEvents() 
 675     GtkList 
*list 
= GTK_LIST( GTK_COMBO(m_widget
)->list 
); 
 676     GList 
*child 
= list
->children
; 
 679         gtk_signal_disconnect_by_func( GTK_OBJECT(child
->data
), 
 680           GTK_SIGNAL_FUNC(gtk_combo_clicked_callback
), (gpointer
)this ); 
 686 void wxComboBox::EnableEvents() 
 688     GtkList 
*list 
= GTK_LIST( GTK_COMBO(m_widget
)->list 
); 
 689     GList 
*child 
= list
->children
; 
 692         gtk_signal_connect( GTK_OBJECT(child
->data
), "select", 
 693           GTK_SIGNAL_FUNC(gtk_combo_clicked_callback
), (gpointer
)this ); 
 699 void wxComboBox::OnSize( wxSizeEvent 
&event 
) 
 705     gtk_widget_set_usize( GTK_COMBO(m_widget
)->entry
, m_width
-w
-1, m_height 
); 
 707     gtk_widget_set_uposition( GTK_COMBO(m_widget
)->button
, m_x
+m_width
-w
, m_y 
); 
 708     gtk_widget_set_usize( GTK_COMBO(m_widget
)->button
, w
, m_height 
); 
 712 void wxComboBox::ApplyWidgetStyle() 
 716 //    gtk_widget_set_style( GTK_COMBO(m_widget)->button, m_widgetStyle ); 
 717     gtk_widget_set_style( GTK_COMBO(m_widget
)->entry
, m_widgetStyle 
); 
 718     gtk_widget_set_style( GTK_COMBO(m_widget
)->list
, m_widgetStyle 
); 
 720     GtkList 
*list 
= GTK_LIST( GTK_COMBO(m_widget
)->list 
); 
 721     GList 
*child 
= list
->children
; 
 724         gtk_widget_set_style( GTK_WIDGET(child
->data
), m_widgetStyle 
); 
 726         GtkBin 
*bin 
= GTK_BIN(child
->data
); 
 727         gtk_widget_set_style( bin
->child
, m_widgetStyle 
); 
 733 GtkWidget
* wxComboBox::GetConnectWidget() 
 735     return GTK_COMBO(m_widget
)->entry
; 
 738 bool wxComboBox::IsOwnGtkWindow( GdkWindow 
*window 
) 
 740     return ( (window 
== GTK_ENTRY( GTK_COMBO(m_widget
)->entry 
)->text_area
) || 
 741              (window 
== GTK_COMBO(m_widget
)->button
->window 
) ); 
 744 wxSize 
wxComboBox::DoGetBestSize() const 
 746     wxSize 
ret( wxControl::DoGetBestSize() ); 
 748     // we know better our horizontal extent: it depends on the longest string 
 754         size_t count 
= GetCount(); 
 755         for ( size_t n 
= 0; n 
< count
; n
++ ) 
 757             GetTextExtent( GetString(n
), &width
, NULL
, NULL
, NULL
, &m_font 
); 
 763     // empty combobox should have some reasonable default size too