Search code examples
windowsdelphicomboboxvcl

Delphi VCL Custom TCombobox Dropdown Width


I have a simple descendant of Delphi's VCL TCombobox for a very special customer showcase. It has only 2 features (separator lines, multi-line items) that I did not find on a ready-to-use component. Works fine, but I'm unable to control the size of the dropdown area / flyout menu below. I did what I found googling that:

procedure TMyownCombobox.DropDown;
begin
inherited;
var iDropdownHeight:=360;
// does NOT work, as it affects the width, not the height of the flyout
// according to WinAPI documentation, there is no equivalent of CB_SETDROPPEDWIDTH for the height ("CB_SETDROPPEDHEIGHT")
SendMessage(Self.Handle, CB_SETDROPPEDWIDTH,Width,MakeLParam(iDropdownHeight,0));
end;

Unfortunately, size is always about 100px, no matter how many items there are. Settingt th DropdownCount property has no affect. Rendering the items works great, but users have to scroll a lot. When rendering my items, there is a MeasureItem() procedure that I implemented myself, but I could'nt find anything like that for the flyout menu.


Solution

  • The CB_SETDROPPEDWIDTH message is used to set the width of the drop down list:

    An application sends the CB_SETDROPPEDWIDTH message to set the minimum allowable width, in pixels, of the list box of a combo box with the CBS_DROPDOWN or CBS_DROPDOWNLIST style.

    Hence, it will not affect the height.

    To set the height, you use the CB_SETMINVISIBLE message:

    Sets the minimum number of visible items in the drop-down list of a combo box.

    For example,

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      SendMessage(ComboBox1.Handle, CB_SETDROPPEDWIDTH, 200, 0);
      SendMessage(ComboBox1.Handle, CB_SETMINVISIBLE, 50, 0);
    end;
    

    Please note that the width unit is pixels, while the height unit is items.

    Screenshot of large combo box drop down list.

    However, the VCL already provides you with an interface to these messages in its DropDownWidth and DropDownCount properties:

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      ComboBox1.DropDownWidth := 200;
      ComboBox1.DropDownCount := 50;
    end;
    

    So you don't need to send any messages explicitly yourself.

    If this doesn't work for you in your particular application, then you have some strange things going on in this app, which we cannot see.

    One very common cause of malfunctioning VCL GUIs is that the programmer uses VCL styles (or themes) to give the app a non-standard appearance.