TComboBox Komponent kombinuje editačné pole s posúvateľným zoznamom na výber. Užívatelia si môžu vybrať položku zo zoznamu alebo napísať priamo do editovacie pole.
Rozbaľovací zoznam
Keď je rozbaľovacie pole v rozbaľovacom stave, systém Windows nakreslí typ ovládacieho prvku zoznamu, aby zobrazil položky rozbaľovacieho zoznamu na výber.
Vlastnosť DropDownCount určuje maximálny počet položiek zobrazených v rozbaľovacom zozname.
šírka rozbaľovacieho zoznamu štandardne by sa rovnala šírke rozbaľovacieho zoznamu.
Keď dĺžka (reťazca) položiek presiahne šírku komboboxu, položky sa zobrazia ako orezané!
TComboBox neposkytuje spôsob, ako nastaviť šírku svojho rozbaľovacieho zoznamu :(
Oprava šírky rozbaľovacieho zoznamu ComboBox
Šírku rozbaľovacieho zoznamu môžeme nastaviť odoslaním špeciálnej ponuky Windows správa do rozbaľovacieho zoznamu. Správa je CB_SETDROPPEDWIDTH a odošle minimálnu povolenú šírku zoznamu v rozbaľovacom zozname v pixloch.
Ak chcete pevne zakódovať veľkosť rozbaľovacieho zoznamu, povedzme 200 pixelov, môžete urobiť tieto kroky:
SendMessage (theComboBox. Handle, CB_SETDROPPEDWIDTH, 200, 0);
To je v poriadku, iba ak ste si istí, že všetky vašeComboBox. Položky nie sú dlhšie ako 200 px (ak sú nakreslené).
Aby sme zaistili, že rozbaľovací zoznam bude vždy dostatočne široký, môžeme vypočítať požadovanú šírku.
Tu je funkcia na získanie požadovanej šírky rozbaľovacieho zoznamu a nastavenie:
procedúra ComboBox_AutoWidth (const theComboBox: TCombobox); const
HORIZONTAL_PADDING = 4; var
itemsFullWidth: integer; idx: celé číslo; itemWidth: integer; začať
itemsFullWidth: = 0; // získajte maximum potrebné pre položky v rozbaľovacom stavepre idx: = 0 na -1 +ComboBox. Položky. počítať robiťzačať
itemWidth: = theComboBox. Plátno. TextWidth (theComboBox. Položky [idx]); Inc (itemWidth, 2 * HORIZONTAL_PADDING); if (itemWidth> itemsFullWidth) potom itemsFullWidth: = itemWidth; koniec; // podľa potreby nastavte šírku rozbaľovacej ponukyak (itemsFullWidth> theComboBox. Šírka). začať// skontrolujte, či by sa nemal posúvačak theComboBox. DropDownCount potom
itemsFullWidth: = itemsFullWidth + GetSystemMetrics (SM_CXVSCROLL); SendMessage (theComboBox. Rukoväť, CB_SETDROPPEDWIDTH, položkyFullWidth, 0); koniec; koniec;
Šírka najdlhšieho reťazca sa používa pre šírku rozbaľovacieho zoznamu.
Kedy zavolať ComboBox_AutoWidth?
Ak vyplníte zoznam položiek (v čase návrhu alebo pri vytváraní formulára), môžete volať formulár ComboBox_AutoWidth. OnCreate obsluha udalosti.
Ak dynamicky zmeníte zoznam položiek so zoznamom, môžete volať procedúru ComboBox_AutoWidth vo vnútri OnDropDown obsluha udalostí - nastane, keď používateľ otvorí rozbaľovací zoznam.
Písomka
Na skúšku máme vo formulári 3 rozbaľovacie políčka. Všetky majú položky so svojím textom širším ako je skutočná šírka poľa so zoznamom. Tretí rozbaľovací zoznam je umiestnený blízko pravého okraja okraja formulára.
Vlastnosť Položky je v tomto prípade predvyplnená - vo formulári obsluhujeme udalosť ComboBox_AutoWidth v obslužnej rúre udalosti OnCreate:
// Formáty OnCreateprocedúra TForm. FormCreate (odosielateľ: TObject); začať
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); koniec;
Nevyvolali sme ComboBox_AutoWidth pre Combobox1, aby sme videli rozdiel!
Všimnite si, že po spustení bude rozbaľovací zoznam pre Combobox2 širší ako Combobox2.
Celý rozbaľovací zoznam je orezaný pre umiestnenie „blízko pravého okraja“.
Pre Combobox3, ktorý je umiestnený blízko pravého okraja, je rozbaľovací zoznam orezaný.
Odoslaním CB_SETDROPPEDWIDTH sa vždy rozšíri rozbaľovacie zoznamy napravo. Ak je váš kombobox blízko pravého okraja, rozšírenie zoznamu viac doprava by malo za následok orezanie zobrazenia zoznamu.
Ak je to tak, musíme nejako rozšíriť zoznam doľava, nie doprava!
CB_SETDROPPEDWIDTH nemá žiadny spôsob, ako určiť, ktorým smerom (doľava alebo doprava) rozšíriť zoznam.
Riešenie: WM_CTLCOLORLISTBOX
Len keď sa má zobraziť rozbaľovací zoznam, systém Windows odošle správu WM_CTLCOLORLISTBOX do nadradeného okna zoznamu - do nášho rozbaľovacieho zoznamu.
Problém by sa vyriešil tým, že by sme boli schopní zvládnuť WM_CTLCOLORLISTBOX pre kombinovanýox blízko pravého okraja.
Všemohúce oknoProc
Každý ovládací prvok VCL odhaľuje vlastnosť WindowProc - postup, ktorý reaguje na správy odoslané do ovládacieho prvku. Vlastnosť WindowProc môžeme použiť na dočasné nahradenie alebo podtriedu postupu okna ovládacieho prvku.
Tu je náš upravený WindowProc pre Combobox3 (ten pri pravom okraji):
// upravený ComboBox3 WindowProcprocedúra TForm. ComboBox3WindowProc (var Správa: TMessage); var
cr, lbr: TRect; začať// nakreslenie zoznamu s kombinovanými položkami
ak správa. Msg = WM_CTLCOLORLISTBOX. začať
GetWindowRect (ComboBox3.Handle, cr); // obdĺžnik zoznamu
GetWindowRect (Správa. LParam, lbr); // presuňte ho doľava tak, aby zodpovedala pravému okrajuak cr. Vpravo <> lbr. Správny potom
MoveWindow (Správa. LParam, lbr. Ľavú (LBR. Pravým clbr. Správne), lbr. Top, lbr. Pravým-LBR. Vľavo, lbr. Bottom-LBR. Hore, pravda); koniecinak
ComboBox3WindowProcORIGINAL (Message); koniec;
Ak správa, ktorú prijíma naše rozbaľovacie pole, je WM_CTLCOLORLISTBOX, dostaneme obdĺžnik jeho okna, dostaneme tiež obdĺžnik zobrazeného zoznamu (GetWindowRect). Ak sa zdá, že zoznam by sa zobrazil viac vpravo - presunieme ho doľava, takže pole so zoznamom a pravé pole so zoznamom bude rovnaké. Tak jednoduché ako to :)
Ak správa nie je WM_CTLCOLORLISTBOX, jednoducho zavoláme pôvodný postup spracovania správ pre rozbaľovacie pole (ComboBox3WindowProcORIGINAL).
Nakoniec to všetko môže fungovať, ak sme ho nastavili správne (v obslužnej rutine udalostí OnCreate pre formulár):
// Formáty OnCreateprocedúra TForm. FormCreate (odosielateľ: TObject); začať
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); // pripojiť upravené / vlastné WindowProc pre ComboBox3
ComboBox3WindowProcORIGINAL: = ComboBox3.WindowProc; ComboBox3.WindowProc: = ComboBox3WindowProc; koniec;
Kde vo vyhlásení formulára máme (celé):
typ
TForm = trieda(TForm) ComboBox1: TComboBox; ComboBox2: TComboBox; ComboBox3: TComboBox;procedúra FormCreate (odosielateľ: TObject); súkromné
ComboBox3WindowProcORIGINAL: TWndMethod; procedúra ComboBox3WindowProc (var Správa: TMessage); verejnosť{Verejné vyhlásenia}koniec;
A to je všetko. Všetko spracované :)