A ComboBox legördülő szélességének méretezése

Az TComboBox Az összetevő egyesíti a szerkesztődobozt egy görgethető "válogatási" listával. A felhasználók kiválaszthatnak egy elemet a listából, vagy közvetlenül beírhatják a szerkesztési mező.

Legördülő lista

Ha a kombinált doboz leesett állapotban van, a Windows felhívja a listamező típusú vezérlőelemet a választható kombinált doboz elemek megjelenítéséhez.

Az DropDownCount tulajdonság meghatározza a legördülő listában megjelenő elemek maximális számát.

Az a legördülő lista szélessége alapértelmezés szerint megegyezik a kombinált doboz szélességével.

Ha az elemek (egy karakterlánc) hossza meghaladja a kombinált doboz szélességét, akkor az elemek cut-offként jelennek meg!

A TComboBox nem biztosítja a legördülő lista szélességének beállítását :(

A ComboBox legördülő lista szélességének javítása

A legördülő lista szélességét beállíthatjuk egy speciális küldéssel Windows üzenet a kombinált dobozba. Az üzenet: CB_SETDROPPEDWIDTH és elküldi a kombinált doboz listájának minimális megengedett szélességét pixelekben.

instagram viewer

Ha a legördülő lista méretét 200 pixelre állítja, akkor ezt megteheti:


SendMessage (a ComboBox. Fogantyú, CB_SETDROPPEDWIDTH, 200, 0); 

Ez csak akkor van rendben, ha biztos benne, hogy az összes ComboBox-on van. Az elemek nem lehetnek hosszabbak 200 képpontnál (rajzoláskor).

Annak érdekében, hogy a legördülő lista mindig elég széles legyen, kiszámolhatjuk a szükséges szélességet.

Itt van egy funkció a legördülő lista kívánt szélességének eléréséhez és beállításához:

eljárás ComboBox_AutoWidth (const theComboBox: TCombobox); const
HORIZONTAL_PADDING = 4; var
itemsFullWidth: egész szám; idx: egész szám; itemWidth: egész szám; kezdődik
tételek teljes szélessége: = 0; // kapja meg a szükséges maximális értéket az elemek legördülő állapotábanmert idx: = 0 nak nek -1 + a ComboBox. Terméket. Számol csinálkezdődik
itemWidth: = a ComboBox. Vászon. Szövegszélesség (a ComboBox. Tételek [IDX]); Inc (tételszélesség, 2 * HORIZONTAL_PADDING); if (itemWidth> itemsFullWidth) azután itemsFullWidth: = itemWidth; vég; // állítsa be a legördülő szélességet, ha szükségesha (tételek teljes szélessége> a comboBox. Szélesség), majd. kezdődik// ellenőrizze, hogy létezik-e görgetősávha theComboBox. DropDownCount azután
tételek teljes szélessége: = tételek teljes szélessége + GetSystemMetrics (SM_CXVSCROLL); SendMessage (a ComboBox. Fogantyú, CB_SETDROPPEDWIDTH, itemsFullWidth, 0); vég; vég; 

A leghosszabb húr szélességét a legördülő lista szélességére használjuk.

Mikor kell hívni a ComboBox_AutoWidth-t?
Ha előre kitölti az elemek listáját (a tervezés idején vagy az űrlap létrehozásakor), akkor meghívhatja a ComboBox_AutoWidth eljárást az űrlapon belül OnCreate eseménykezelő.

Ha dinamikusan megváltoztatja a kombinált dobozok listáját, akkor felhívhatja a ComboBox_AutoWidth eljárást a OnDropDown eseménykezelő - akkor fordul elő, amikor a felhasználó megnyitja a legördülő listát.

Egy teszt
A teszthez 3 kombinált doboz van egy űrlapon. Mindegyiknél vannak olyan elemek, amelyek szövege szélesebb, mint a kombinált doboz tényleges szélessége. A harmadik kombinált dobozt az űrlap határának jobb széle közelében kell elhelyezni.

A Példák Tulajdonság ebben a példában előzetesen kitöltésre kerül - hívjuk a ComboBox_AutoWidth-et az OnCreate eseménykezelőben az űrlaphoz:

// Az űrlap OnCreateeljárás TForm. FormCreate (Feladó: TObject); kezdődik
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); vég; 

Nem hívtuk a ComboBox_AutoWidth-et a Combobox1-hez, hogy lássa a különbséget!

Vegye figyelembe, hogy futtatáskor a Combobox2 legördülő listája szélesebb lesz, mint a Combobox2.

A teljes legördülő listát levágják a "Jobb szélső elhelyezés"

A jobb széléhez közeli Combobox3 esetében a legördülő lista levágásra kerül.

A CB_SETDROPPEDWIDTH elküldésekor a legördülő listát mindig jobbra kell kiterjeszteni. Ha a kombinált doboz a jobb széle közelében helyezkedik el, akkor a listamező jobbra történő kiterjesztésekor a listamező megjelenése levágásra kerül.

Valahogy ki kell terjesztenünk a listát, ha ez a helyzet, nem jobbra!

A CB_SETDROPPEDWIDTH semmilyen módon nem tudja meghatározni, hogy milyen irányba (balra vagy jobbra) bővítse a listát.

Megoldás: WM_CTLCOLORLISTBOX

A legördülő lista megjelenésekor a Windows elküldi a WM_CTLCOLORLISTBOX üzenetet a listamező szülőablakához - a kombinált mezőbe.

A WM_CTLCOLORLISTBOX kezelése a jobboldali szélső kombinált dobozban megoldja a problémát.

A Mindenható WindowProc
Minden VCL-vezérlő kiteszi a WindowProc tulajdonságot - az az eljárás, amely a vezérlőnek küldött üzenetekre reagál. A WindowProc tulajdonsággal ideiglenesen helyettesíthetjük vagy alosztályozhatjuk a vezérlés ablakának eljárását.

Itt van a módosított WindowProc a Combobox3-hoz (a jobb szélénél lévő):

// módosított ComboBox3 WindowProceljárás TForm. ComboBox3WindowProc (var Üzenet: TMessage); var
cr, lbr: TRect; kezdődik// a listamező rajzolása kombinált elemekkel
ha Üzenet. Msg = WM_CTLCOLORLISTBOX, akkor. kezdődik
GetWindowRect (ComboBox3.Handle, cr); // lista doboz téglalap
GetWindowRect (Üzenet. LParam, lbr); // mozgassa balra, hogy megegyezzen a jobb szélgelha kr. Jobb <> lbr. Jobb azután
MoveWindow (Üzenet. LParam, lbr. Jobb- (LBR. Jobb clbr. Jobbra), lbr. Top, lbr. Jobb LBR. Balra, lbr. Bottom-LBR. Felső, igaz); végmás
ComboBox3WindowProcORIGINAL (Message); vég; 

Ha az üzenet, amelyet a kombinált dobozunkban kap, a WM_CTLCOLORLISTBOX, megkapjuk az ablak téglalapját, akkor a megjelenő listamező téglalapját is megkapjuk (GetWindowRect). Ha úgy tűnik, hogy a listamező jobbra jelenik meg - balra mozgatjuk úgy, hogy a kombinált doboz és a listamező jobb szegélye megegyezzen. Olyan egyszerű :)

Ha az üzenet nem WM_CTLCOLORLISTBOX, akkor egyszerűen meghívjuk a kombinált doboz eredeti üzenetkezelési eljárását (ComboBox3WindowProcORIGINAL).

Végül, mindez működhet, ha helyesen állítottuk be (az űrlap OnCreate eseménykezelőjében):

// Az űrlap OnCreateeljárás TForm. FormCreate (Feladó: TObject); kezdődik
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); // csatoljon módosított / egyedi WindowProc szoftvert a ComboBox3-hoz
ComboBox3WindowProcORIGINAL: = ComboBox3.WindowProc; ComboBox3.WindowProc: = ComboBox3WindowProc; vég; 

Ahol az űrlapnyilatkozatban van (teljes):

típus
TForm = osztály(TForm) ComboBox1: TComboBox; ComboBox2: TComboBox; ComboBox3: TComboBox;eljárás FormCreate (Feladó: TObject); magán
ComboBox3WindowProcORIGINAL: TWndMethod; eljárás ComboBox3WindowProc (var Üzenet: TMessage); nyilvános{Nyilvános nyilatkozatok}vég; 

És ez az. Minden kezelt :)