![]() |
TComboBox csOwnerDrawVariable DropDownCount Höhe spinnt
Hallo zusammen!
Ich möchte mir eine ComboBox basteln, welche die normale Höhe einer ComboBox hat (21px, bzw. 14px ItemHeight), die Items selbst aber z.B. 50px hoch sind. Die Anpassung von ItemHeight macht ja auch gleich die komplette ComboBox größer, deshalb kann ich dies nicht benutzen. Ich habe den Style auf csOwnerDrawVariable gesetzt und verwende eine OnMeasureItem Prozedur (siehe unten), die nur für die Items (-1 ist der angezeigte Eintrag in der ComboBox selbst, afaik) die Höhe auf 50 setzt. Problem: Wenn die Box <= 2 Items hat, kann man sie garnicht ausklappen (Bug?). Bei >= 3 Items ist die heruntergeklappte Höhe (Items.Count * ItemHeight), was natürlich bei Einträgen mit je 50px Höhe kompletten Unsinn ergibt, weil ItemHeight ja immernoch 14 ist, und bei 3 Einträgen die Liste somit nur 42px statt 150px hoch ist. Lösungsansätze? Die in ![]() Kann ich alternativ ItemHeight einfach ändern, und die ComboBox selbst auf eine Höhe von 21px zwingen? Bin gespannt, ob Ihr die Probleme nachvollziehen könnt, oder nur ich die wieder habe. Windows 7 Pro, ohne Themes ("Windows - klassisch") Danke im Vorraus!
Delphi-Quellcode:
procedure TForm1.MyComboBoxMeasureItem(Control: TWinControl; Index: Integer; var _Height: Integer);
begin if Index > -1 then _Height := 50; end; procedure TForm1.Button1Click(Sender: TObject); var tmpComboBox: TComboBox; begin tmpComboBox := TComboBox.Create(Self); with tmpComboBox do begin Height := 21; Left := 10; Top := 10; Style := csOwnerDrawVariable; OnMeasureItem := MyComboBoxMeasureItem; Parent := Self; Items.Add('123'); Items.Add('456'); // Items.Add('789'); // Items.Add('123'); // Items.Add('123'); // Items.Add('123'); // Items.Add('123'); // Items.Add('456'); // Items.Add('789'); // Items.Add('123'); // Items.Add('456'); // Items.Add('789'); ItemIndex := 0; end; end; |
AW: TComboBox csOwnerDrawVariable DropDownCount Höhe spinnt
Da Edit so spät nicht mehr geht, hier der nächste Eintrag:
Ich konnte zwar die Ursache für das Problem nicht finden, aber eine andere Lösung:
Delphi-Quellcode:
Mit dieser abgeleiteten Combobox wird die Höhe nicht mehr komplett automatisch berechnet.
TMyComboBox = class(TComboBox)
protected procedure CreateParams(var Params: TCreateParams); override; end; procedure TMyComboBox.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); with Params do Style := Style or CBS_NOINTEGRALHEIGHT; end; Dann kann man z.B. folgendes machen:
Delphi-Quellcode:
Die ComboBox scheint jetzt generell das zu machen, was sie soll.
FComboBox := TMyComboBox.Create(Self);
with FComboBox do begin Height := 21; Style := csOwnerDrawVariable; ItemHeight := 50; OnMeasureItem := ComboBoxMeasureItem; OnDrawItem := ComboBoxDrawItem; DropDownCount := 7; Parent := Self; end; procedure blabla.ComboBoxMeasureItem(Control: TWinControl; Index: Integer; var _Height: Integer); begin if Index > -1 then begin _Height := 50; // alle ausgeklappten Einträge mit 50px zeichen end else _Height := 14; // den Inhalt der 21px hohen Combobox nur 14px hoch zeichnen end; procedure blabla.ComboBoxDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); var ItemString: string; begin // das hier bitte mit eigener Zeichnen-Funktion ersetzen, das ist nur ein Dummy, der mehrzeilig Text ausgibt TComboBox(Control).Canvas.FillRect(Rect); ItemString := TComboBox(Control).Items.Strings[Index]; DrawText(TComboBox(Control).Canvas.Handle, PChar(ItemString), - 1, Rect, DT_WORDBREAK); end; Tip: Mit Style := csOwnerDrawFixed scheint das nicht zu klappen. Also immer brav csOwnerDrawVariable verwenden. Ich hoffe, mit dieser kleinen Erkenntnis konnte ich zukünftig Suchenden ein wenig helfen. PS: Wie kommt man von sich aus darauf, nach "CreateParams" zu suchen? :shock: Lg Mathias Noch ein Nachtrag: Es muss nicht unbedingt die Lösung für das Spinnen der Höhenberechnung sein, aber eine ComboBox dreht komplett durch, wenn man in der ComboBoxDrawItem Prozedur versehentlich Eigenschaften ändert, die man eigentlich beim Canvas ändern wollte: Am Besten führt man ja die ComboBoxDrawItem Prozedur mit "with TComboBox(Control).Canvas do begin" durch, damit alle Zugriffe auf Font, Brush, ... direkt den Canvas betreffen. Bei einem Quick'n'Dirty Testprogramm, wo man nur 1-2 Sachen testen will, kann im Eifer des Gefechts auch mal ein Font.Color := ... vor oder hinter diesen "with" Block gelanden. Und dann passiert nur noch Unsinn ;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:49 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz