Grootte van de vervolgkeuzebreedte van de ComboBox

De TComboBox component combineert een invoervak ​​met een schuifbare "pick" -lijst. Gebruikers kunnen een item uit de lijst selecteren of rechtstreeks in het bewerkingsvak.

Keuzelijst

Wanneer een keuzelijst met invoervak ​​is weergegeven, tekent Windows een keuzelijst met besturingselementen om keuzelijst met keuzelijsten weer te geven.

De DropDownCount-eigenschap geeft het maximale aantal items aan dat wordt weergegeven in de vervolgkeuzelijst.

De breedte van de vervolgkeuzelijst zou standaard gelijk zijn aan de breedte van de keuzelijst met invoervak.

Als de lengte (van een string) items groter is dan de breedte van de combobox, worden de items weergegeven als afgesneden!

TComboBox biedt geen manier om de breedte van de vervolgkeuzelijst in te stellen :(

De breedte van de vervolgkeuzelijst ComboBox bevestigen

We kunnen de breedte van de vervolgkeuzelijst instellen door een special te sturen Windows-bericht naar de keuzelijst met invoervak. De boodschap is CB_SETDROPPEDWIDTH en verzendt de minimaal toegestane breedte, in pixels, van de keuzelijst van een keuzelijst met invoervak.

instagram viewer

Om de grootte van de vervolgkeuzelijst hard te coderen tot, laten we zeggen, 200 pixels, zou je het volgende kunnen doen:


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

Dit is alleen goed als u zeker weet dat al uw theComboBox. Items zijn niet langer dan 200 px (indien getekend).

Om ervoor te zorgen dat we de vervolgkeuzelijst altijd breed genoeg hebben, kunnen we de vereiste breedte berekenen.

Hier is een functie om de vereiste breedte van de vervolgkeuzelijst te krijgen en in te stellen:

procedure ComboBox_AutoWidth (const theComboBox: TCombobox); const
HORIZONTAL_PADDING = 4; var
itemsFullWidth: geheel getal; idx: geheel getal; itemWidth: geheel getal; beginnen
itemsFullWidth: = 0; // haal het maximale dat nodig is met een van de items in dropdown-statusvoor idx: = 0 naar -1 + theComboBox. Artikelen. Tel Doenbeginnen
itemWidth: = theComboBox. Canvas. TextWidth (theComboBox. Artikelen [idx]); Inc (itemWidth, 2 * HORIZONTAL_PADDING); if (itemWidth> itemsFullWidth) vervolgens itemsFullWidth: = itemWidth; einde; // stel indien nodig de breedte van de drop-down inals (itemsFullWidth> theComboBox. Breedte) dan. beginnen// controleer of er een schuifbalk zou zijnals theComboBox. DropDownCount vervolgens
itemsFullWidth: = itemsFullWidth + GetSystemMetrics (SM_CXVSCROLL); SendMessage (theComboBox. Greep, CB_SETDROPPEDWIDTH, itemsFullWidth, 0); einde; einde; 

De breedte van de langste string wordt gebruikt voor de breedte van de vervolgkeuzelijst.

Wanneer ComboBox_AutoWidth bellen?
Als u de lijst met items vooraf invult (tijdens het ontwerpen of bij het maken van het formulier), kunt u de ComboBox_AutoWidth-procedure aanroepen binnen de formulieren OnCreate event handler.

Als u de lijst met keuzelijstitems dynamisch wijzigt, kunt u de ComboBox_AutoWidth-procedure binnen de OnDropDown event handler - treedt op wanneer de gebruiker de vervolgkeuzelijst opent.

Een toets
Voor een test hebben we 3 comboboxen op een formulier. Ze hebben allemaal items waarvan de tekst breder is dan de daadwerkelijke breedte van de keuzelijst. De derde keuzelijst met invoervak ​​bevindt zich aan de rechterkant van de formulierrand.

De eigenschap Items is voor dit voorbeeld vooraf ingevuld - we noemen onze ComboBox_AutoWidth in de OnCreate-gebeurtenishandler voor het formulier:

// Form's OnCreateprocedure TForm. FormCreate (Afzender: TObject); beginnen
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); einde; 

We hebben ComboBox_AutoWidth niet genoemd voor Combobox1 om het verschil te zien!

Merk op dat de vervolgkeuzelijst voor Combobox2 tijdens het uitvoeren breder zal zijn dan Combobox2.

De volledige vervolgkeuzelijst wordt afgesneden voor 'Plaatsing aan de rechterkant'

Voor Combobox3, degene die zich aan de rechterkant bevindt, wordt de vervolgkeuzelijst afgesneden.

Als u de CB_SETDROPPEDWIDTH verzendt, wordt de vervolgkeuzelijst altijd naar rechts uitgebreid. Wanneer uw combobox zich aan de rechterkant bevindt, zou het uitbreiden van de keuzelijst naar rechts tot gevolg hebben dat de weergave van de keuzelijst wordt afgesneden.

We moeten op de een of andere manier de keuzelijst naar links uitbreiden als dit het geval is, niet naar rechts!

De CB_SETDROPPEDWIDTH kan niet specificeren in welke richting (links of rechts) de keuzelijst moet worden uitgebreid.

Oplossing: WM_CTLCOLORLISTBOX

Net wanneer de vervolgkeuzelijst moet worden weergegeven, stuurt Windows het WM_CTLCOLORLISTBOX-bericht naar het bovenliggende venster van een keuzelijst - naar onze keuzelijst.

In staat zijn om de WM_CTLCOLORLISTBOX voor de bijna-rechtse combobox te verwerken, zou het probleem oplossen.

De Almachtige WindowProc
Elk VCL-besturingselement stelt de eigenschap WindowProc bloot - de procedure die reageert op berichten die naar het besturingselement zijn verzonden. We kunnen de eigenschap WindowProc gebruiken om de vensterprocedure van het besturingselement tijdelijk te vervangen of te subklasse.

Hier is onze gewijzigde WindowProc voor Combobox3 (die aan de rechterkant):

// gewijzigd ComboBox3 WindowProcprocedure TForm. ComboBox3WindowProc (var Bericht: TMessage); var
cr, lbr: TRect; beginnen// het tekenen van de keuzelijst met combobox-items
als Bericht. Msg = WM_CTLCOLORLISTBOX dan. beginnen
GetWindowRect (ComboBox3.Handle, cr); // keuzelijst rechthoek
GetWindowRect (bericht. LParam, lbr); // verplaats het naar links zodat het overeenkomt met de rechterrandals cr. Rechts <> lbr. Rechtsaf vervolgens
MoveWindow (bericht. LParam, lbr. Links- (lbr. Rechts-kl. Rechts), lbr. Top, lbr. Rechts-lbr. Links, lbr. Onderste lbr. Top, True); eindeanders
ComboBox3WindowProcORIGINAL (Bericht); einde; 

Als het bericht dat onze keuzelijst met invoervak ​​ontvangt WM_CTLCOLORLISTBOX is, krijgen we de rechthoek van het venster, we krijgen ook de rechthoek van de keuzelijst die moet worden weergegeven (GetWindowRect). Als het lijkt alsof de keuzelijst meer naar rechts wordt weergegeven, verplaatsen we deze naar links, zodat de keuzelijst met invoervak ​​en de rechterrand van de keuzelijst hetzelfde zijn. Zo eenvoudig als dat :)

Als het bericht niet WM_CTLCOLORLISTBOX is, noemen we gewoon de oorspronkelijke procedure voor het afhandelen van berichten voor de keuzelijst met invoervak ​​(ComboBox3WindowProcORIGINAL).

Ten slotte kan dit allemaal werken als we het correct hebben ingesteld (in de OnCreate-gebeurtenishandler voor het formulier):

// Form's OnCreateprocedure TForm. FormCreate (Afzender: TObject); beginnen
ComboBox_AutoWidth (ComboBox2); ComboBox_AutoWidth (ComboBox3); // voeg aangepaste / aangepaste WindowProc toe voor ComboBox3
ComboBox3WindowProcORIGINAL: = ComboBox3.WindowProc; ComboBox3.WindowProc: = ComboBox3WindowProc; einde; 

Waar in de formulierverklaring hebben we (geheel):

type
TForm = klasse(TForm) ComboBox1: TComboBox; ComboBox2: TComboBox; ComboBox3: TComboBox;procedure FormCreate (Afzender: TObject); privaat
ComboBox3WindowProcORIGINAL: TWndMethod; procedure ComboBox3WindowProc (var Bericht: TMessage); openbaar{Openbare verklaringen}einde; 

En dat is het. Allemaal afgehandeld :)

instagram story viewer