TComboBox

Drop-down selection control with multiple styles and data binding

Fonte: source/classes/combobox.prg  |  Parent: TControl

Overview

TComboBox wraps the Windows ComboBox control, providing a drop-down list from which the user selects one item. It supports three styles:

The combo can bind to either a string variable (the selected item text) or a numeric variable (the selected item index). It supports incremental search, custom drawing, and data-driven item lists.

ComboBox Styles

graph LR subgraph "CBS_DROPDOWN" DD_TEXT["Editable text field"] DD_BTN["Drop-down button"] DD_LIST["List appears on click"] end subgraph "CBS_DROPDOWNLIST" DDL_TEXT["Read-only display"] DDL_BTN["Drop-down button"] DDL_LIST["Selection from list only"] end subgraph "CBS_SIMPLE" S_TEXT["Editable text field"] S_LIST["List always visible"] end style DD_TEXT fill:#1c2129,stroke:#58a6ff,color:#e6edf3 style DDL_TEXT fill:#1c2129,stroke:#3fb950,color:#e6edf3 style S_TEXT fill:#1c2129,stroke:#d29922,color:#e6edf3

Key Properties

PropertyTypeDescription
aItemsArrayArray of strings displayed in the drop-down list
bSetGetBlockData-binding block. For string combos: reads/writes the selected text. For numeric combos: reads/writes the selected index.
bChangeBlockCode block executed when the selection changes
nAtNumericIndex of the currently selected item (1-based)
lIncSearchLogicalEnable incremental search as the user types
lOwnerDrawLogicalEnable custom item drawing via bDrawItem
bDrawItemBlockCustom drawing block for owner-draw mode
cCueTextStringPlaceholder text when nothing is selected
nDropWidthNumericWidth of the drop-down list (can be wider than the control itself)

Key Methods

MethodDescription
New( nRow, nCol, bSetGet, aItems, ... )Constructor. Creates a new combo at the given position.
ReDefine( nId, bSetGet, aItems, oWnd, ... )Redefine from a dialog resource.
Set( cText )Set the selected item by its text.
Select( n )Set the selected item by its index.
Add( cItem )Add an item to the list at runtime.
Del( n )Remove item at index n.
Reset()Clear all items from the list.
Refresh()Repopulate the list from aItems and restore the selection.

Command Syntax

String-bound ComboBox

@ nRow, nCol COMBOBOX oCombo VAR cVar ;
   ITEMS aItems ;
   [ OF oWnd ] ;
   [ SIZE nWidth, nHeight ] ;
   [ ON CHANGE bChange ] ;
   [ VALID bValid ] ;
   [ STYLE CBS_DROPDOWNLIST ] ;
   [ FONT oFont ]

Numeric-bound (index) ComboBox

@ nRow, nCol COMBOBOX oCombo VAR nIndex ;
   ITEMS aItems ;
   [ OF oWnd ] ;
   [ SIZE nWidth, nHeight ] ;
   [ ON CHANGE bChange ]

Data Binding Diagram

sequenceDiagram participant User participant Combo as TComboBox participant Var as Bound Variable User->>Combo: Select "Option B" Combo->>Combo: nAt = 2 alt String binding Combo->>Var: Eval(bSetGet, "Option B") else Numeric binding Combo->>Var: Eval(bSetGet, 2) end Combo->>Combo: Eval(bChange) Note over Combo,Var: On dialog activation, Combo reads
Eval(bSetGet) to set initial selection

Code Examples

Example 1: Simple ComboBox Selections

#include "FiveWin.ch"

FUNCTION ComboDemo()
   LOCAL oDlg, oFont
   LOCAL cCountry := "USA"
   LOCAL nPriority := 2
   LOCAL aCountries := { "USA", "Canada", "Mexico", "Brazil", "UK", "France", "Germany", "Spain" }
   LOCAL aPriority  := { "Low", "Medium", "High", "Critical" }

   DEFINE FONT oFont NAME "Segoe UI" SIZE 0, -14
   DEFINE DIALOG oDlg TITLE "ComboBox Demo" SIZE 400, 300 FONT oFont

   // String-bound combo -- cCountry holds the selected text
   @ 1.0, 1 SAY "Country:" OF oDlg
   @ 1.0, 6 COMBOBOX cCountry ;
      ITEMS aCountries ;
      OF oDlg SIZE 180, 200 ;
      STYLE CBS_DROPDOWNLIST

   // Numeric-bound combo -- nPriority holds the selected index
   @ 3.0, 1 SAY "Priority:" OF oDlg
   @ 3.0, 6 COMBOBOX nPriority ;
      ITEMS aPriority ;
      OF oDlg SIZE 140, 200 ;
      ON CHANGE ( MsgInfo( "Priority changed to: " + aPriority[ nPriority ] ) )

   @ 5.5, 6 BUTTON "&OK" OF oDlg SIZE 80, 25 ;
      ACTION ( MsgInfo( "Country: " + cCountry + CRLF + ;
                        "Priority: " + aPriority[ nPriority ] ), ;
               oDlg:End() ) DEFAULT

   @ 5.5, 16 BUTTON "&Cancel" OF oDlg SIZE 80, 25 ACTION oDlg:End() CANCEL

   ACTIVATE DIALOG oDlg CENTERED

   RELEASE FONT oFont
RETURN NIL

Example 2: Database-Driven ComboBox

#include "FiveWin.ch"

FUNCTION DBCombo()
   LOCAL oDlg, oCmb
   LOCAL cCategory := ""
   LOCAL aCategories := {}

   // Build the items array from a database table
   USE Categories VIA "DBFCDX" NEW
   Categories->( DbGoTop() )
   DO WHILE !Categories->( Eof() )
      AAdd( aCategories, AllTrim( Categories->CATNAME ) )
      Categories->( DbSkip() )
   ENDDO

   DEFINE DIALOG oDlg TITLE "Select Category" SIZE 400, 200

   @ 1.5, 1 SAY "Category:" OF oDlg
   @ 1.5, 6 COMBOBOX oCmb VAR cCategory ;
      ITEMS aCategories ;
      OF oDlg SIZE 200, 200 ;
      STYLE CBS_DROPDOWN ;
      VALID ( !Empty( cCategory ) ) ;
      CUETEXT "Type or select a category"

   @ 4.0, 6 BUTTON "&Select" OF oDlg SIZE 90, 25 ;
      ACTION ( MsgInfo( "Selected: " + cCategory ), oDlg:End() ) DEFAULT

   @ 4.0, 16 BUTTON "&Cancel" OF oDlg SIZE 80, 25 ACTION oDlg:End() CANCEL

   ACTIVATE DIALOG oDlg CENTERED

   CLOSE Categories
RETURN NIL

Example 3: Dependent ComboBoxes (Country/City)

#include "FiveWin.ch"

FUNCTION DependentCombos()
   LOCAL oDlg
   LOCAL cCountry := "USA"
   LOCAL cCity    := ""
   LOCAL oCmbCountry, oCmbCity
   LOCAL aCountries := { "USA", "Canada", "UK" }
   LOCAL aCities    := {}

   DEFINE DIALOG oDlg TITLE "Dependent Combos" SIZE 400, 250

   @ 1, 1 SAY "Country:" OF oDlg
   @ 1, 6 COMBOBOX oCmbCountry VAR cCountry ;
      ITEMS aCountries OF oDlg SIZE 160, 200 ;
      STYLE CBS_DROPDOWNLIST ;
      ON CHANGE ( UpdateCities( cCountry, @aCities, oCmbCity ) )

   @ 3, 1 SAY "City:" OF oDlg
   @ 3, 6 COMBOBOX oCmbCity VAR cCity ;
      ITEMS aCities OF oDlg SIZE 160, 200 ;
      STYLE CBS_DROPDOWNLIST

   // Initialize cities for the default country
   UpdateCities( cCountry, @aCities, oCmbCity )

   @ 5.5, 6  BUTTON "&OK"     OF oDlg SIZE 80, 25 ACTION oDlg:End() DEFAULT
   @ 5.5, 16 BUTTON "&Cancel" OF oDlg SIZE 80, 25 ACTION oDlg:End() CANCEL

   ACTIVATE DIALOG oDlg CENTERED
RETURN NIL

STATIC FUNCTION UpdateCities( cCountry, aCities, oCmbCity )
   DO CASE
   CASE cCountry == "USA"
      aCities := { "New York", "Los Angeles", "Chicago", "Houston" }
   CASE cCountry == "Canada"
      aCities := { "Toronto", "Montreal", "Vancouver", "Calgary" }
   CASE cCountry == "UK"
      aCities := { "London", "Manchester", "Birmingham", "Glasgow" }
   OTHERWISE
      aCities := {}
   ENDCASE

   IF oCmbCity != NIL
      oCmbCity:aItems := aCities
      oCmbCity:Reset()
      oCmbCity:Refresh()
      IF Len( aCities ) > 0
         oCmbCity:Select( 1 )
      ENDIF
   ENDIF
RETURN NIL

Tips

Veja Também