Velikost rozbalovací šířky ComboBoxu

click fraud protection

TComboBox komponenta kombinuje editační pole se posouvatelným seznamem „pick“. Uživatelé si mohou vybrat položku ze seznamu nebo zadat přímo do editační pole.

Rozbalovací seznam

Když je rozbalovací seznam v rozevíracím stavu, systém Windows nakreslí typ ovládacího prvku seznamu k zobrazení položek rozbalovacího seznamu pro výběr.

Vlastnost DropDownCount Určuje maximální počet položek zobrazených v rozevíracím seznamu.

šířka rozevíracího seznamu ve výchozím nastavení by se rovnala šířce pole se seznamem.

Pokud délka (řetězce) položek přesáhne šířku comboboxu, položky se zobrazí jako oříznuté!

TComboBox neposkytuje způsob, jak nastavit šířku jeho rozevíracího seznamu :(

Oprava šířky rozevíracího seznamu ComboBox

Šířku rozevíracího seznamu můžeme nastavit zasláním speciálu Windows zpráva do pole se seznamem. Zpráva je CB_SETDROPPEDWIDTH a odešle minimální přípustnou šířku seznamu v rozbalovacím seznamu v pixelech.

Chcete-li pevně zakódovat velikost rozevíracího seznamu, řekněme 200 pixelů, můžete udělat následující kroky:

instagram viewer

SendMessage (theComboBox. Handle, CB_SETDROPPEDWIDTH, 200, 0); 

To je v pořádku, pokud jste si jisti, že všechny vaše theComboBox. Položky nesmí být delší než 200 px (jsou-li nakresleny).

Abychom zajistili, že rozevírací seznam bude vždy dostatečně široký, můžeme vypočítat požadovanou šířku.

Zde je funkce, jak získat požadovanou šířku rozevíracího seznamu a nastavit ji:

postup ComboBox_AutoWidth (konst theComboBox: TCombobox); konst
HORIZONTAL_PADDING = 4; var
itemsFullWidth: integer; idx: celé číslo; itemWidth: integer; začít
itemsFullWidth: = 0; // získejte maximum potřebné pro položky ve rozbalovacím stavupro idx: = 0 na -1 +ComboBox. Položky. Počet dělatzačít
itemWidth: = theComboBox. Plátno. TextWidth (theComboBox. Položky [idx]); Inc (itemWidth, 2 * HORIZONTAL_PADDING); if (itemWidth> itemsFullWidth) pak itemsFullWidth: = itemWidth; konec; // v případě potřeby nastavte šířku rozevíracího seznamu-li (itemsFullWidth> theComboBox. Šířka). začít// zkontrolujte, zda by tam byl posuvník-li theComboBox. DropDownCount pak
itemsFullWidth: = itemsFullWidth + GetSystemMetrics (SM_CXVSCROLL); SendMessage (theComboBox. Popisovač, CB_SETDROPPEDWIDTH, položkyFullWidth, 0); konec; konec; 

Šířka nejdelšího řetězce se používá pro šířku rozevíracího seznamu.

Kdy volat ComboBox_AutoWidth?
Pokud vyplníte seznam položek (v době návrhu nebo při vytváření formuláře), můžete zavolat proceduru ComboBox_AutoWidth uvnitř formuláře OnCreate obsluha události.

Pokud dynamicky změníte seznam položek se seznamem, můžete zavolat proceduru ComboBox_AutoWidth uvnitř OnDropDown obsluha události - nastane, když uživatel otevře rozevírací seznam.

Test
Pro test máme ve formuláři 3 pole se seznamem. Všechny mají položky, jejichž text je širší než skutečná šířka pole se seznamem. Třetí pole se seznamem je umístěn poblíž pravého okraje ohraničení formuláře.

Vlastnost Položky je v tomto příkladu předvyplněna - v obslužném programu události OnCreate voláme náš ComboBox_AutoWidth:

// Formáty OnCreatepostup TForm. FormCreate (odesílatel: TObject); začít
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); konec; 

Nevyvolali jsme ComboBox_AutoWidth pro Combobox1, abychom viděli rozdíl!

Při spuštění bude rozevírací seznam pro Combobox2 širší než Combobox2.

Celý rozevírací seznam je oříznut pro umístění „blízko pravého okraje“.

U Combobox3, který je umístěn poblíž pravého okraje, je rozevírací seznam oříznut.

Odesláním CB_SETDROPPEDWIDTH se vždy rozšíří rozevírací seznam vpravo. Pokud je váš combobox blízko pravého okraje, rozšíření seznamu více doprava by mělo za následek oříznutí zobrazení seznamu.

Je-li tomu tak, musíme nějak rozbalit seznam vlevo, ne vpravo!

CB_SETDROPPEDWIDTH nemá žádný způsob, jak určit, kterým směrem (vlevo nebo vpravo) rozšířit seznam.

Řešení: WM_CTLCOLORLISTBOX

Právě při zobrazení rozevíracího seznamu Windows odešle zprávu WM_CTLCOLORLISTBOX do nadřazeného okna seznamu - do našeho pole se seznamem.

Problém by vyřešila možnost zvládnout WM_CTLCOLORLISTBOX pro kombobox s pravou hranou.

Všemohoucí oknoProc
Každý ovládací prvek VCL vystavuje vlastnost WindowProc - proceduru, která reaguje na zprávy odeslané ovládacímu prvku. Pomocí vlastnosti WindowProc můžeme dočasně nahradit nebo podtřídit proceduru okna ovládacího prvku.

Zde je náš upravený WindowProc pro Combobox3 (ten u pravého okraje):

// upravený ComboBox3 WindowProcpostup TForm. ComboBox3WindowProc (var Zpráva: TMessage); var
cr, lbr: TRect; začít// nakreslení seznamu se seznamy combobox
pokud zpráva. Msg = WM_CTLCOLORLISTBOX. začít
GetWindowRect (ComboBox3.Handle, cr); // obdélník seznamu
GetWindowRect (Zpráva. LParam, lbr); // přesuňte jej doleva, aby odpovídal pravému okraji-li cr. Vpravo <> lbr. Že jo pak
MoveWindow (Zpráva. LParam, lbr. Vlevo- (lbr. Pravý úder. Správně), lbr. Top, lbr. Pravá lbr. Vlevo, lbr. Spodní lbr. Top, True); konecjiný
ComboBox3WindowProcORIGINAL (Message); konec; 

Pokud zpráva, kterou naše pole se seznamem obdrží, je WM_CTLCOLORLISTBOX, dostaneme obdélník jeho okna, získáme také obdélník seznamu, který má být zobrazen (GetWindowRect). Pokud by se zdálo, že by se pole se seznamem objevilo více vpravo - přesuneme jej doleva, aby byl pravý rámeček se seznamem a seznamem stejný. Tak snadné jako to :)

Pokud zpráva není WM_CTLCOLORLISTBOX, jednoduše zavoláme původní postup zpracování zpráv pro pole se seznamem (ComboBox3WindowProcORIGINAL).

Nakonec to všechno může fungovat, pokud jsme ji nastavili správně (v obslužném programu události OnCreate pro formulář):

// Formáty OnCreatepostup TForm. FormCreate (odesílatel: TObject); začít
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); // připojit upravený / vlastní WindowProc pro ComboBox3
ComboBox3WindowProcORIGINAL: = ComboBox3.WindowProc; ComboBox3.WindowProc: = ComboBox3WindowProc; konec; 

Kde ve formuláři prohlášení máme (celé):

typ
TForm = třída(TForm) ComboBox1: TComboBox; ComboBox2: TComboBox; ComboBox3: TComboBox;postup FormCreate (odesílatel: TObject); soukromé
ComboBox3WindowProcORIGINAL: TWndMethod; postup ComboBox3WindowProc (var Zpráva: TMessage); veřejnost{Veřejná prohlášení}konec; 

A to je vše. Vše zpracováno :)

instagram story viewer