Вот так у меня получился ComboBox с автоматической шириной списка, который не выпадает из экрана при выпадении:
TNewComboBox = class(TComboBox)
private
FAutoListWidth: Boolean;
protected
procedure WndProc(var Msg: TMessage); override;
procedure DropDown; override;
procedure SetDropDownCount(const Value: Integer); override;
procedure CreateWnd; override;
public
constructor Create(AOwner: TComponent); override;
published
property AutoListWidth: Boolean read FAutoListWidth write FAutoListWidth default False;
property DropDownCount default 20;
end;
constructor TNewComboBox.Create(AOwner: TComponent);
begin
inherited;
FAutoListWidth:= False;
DropDownCount:= 20;
end;
procedure TNewComboBox.CreateWnd;
begin
if HandleAllocated then SetDropDownCount(DropDownCount);
end;
procedure TNewComboBox.WndProc(var Msg: TMessage);
var ListR, ComboR: TRect;
Wdt, Hgt: Integer;
begin
if (Msg.Msg = WM_CTLCOLORLISTBOX) then begin
GetWindowRect(Handle, ComboR);
GetWindowRect(Msg.LParam, ListR);
Wdt:= ListR.Right - ListR.Left;
Hgt:= ListR.Bottom - ListR.Top;
if ListR.Right > (Screen.Width - 5) then ListR.Left:= Screen.Width - 5 - Wdt
else if ListR.Left < 5 then ListR.Left:= 5;
MoveWindow(Msg.LParam, ListR.Left, ListR.Top, Wdt, Hgt, True);
end;
inherited WndProc(Msg);
end;
procedure TNewComboBox.DropDown;
var I, item_width, max_width: Integer;
begin
max_width:= 0;
if FAutoListWidth then begin
for I:= 0 to Items.Count -1 do begin
item_width:= Canvas.TextWidth(Items[I]) + 10;
if item_width > max_width then max_width:= item_width;
end;
if DropDownCount < Items.Count then
max_width:= max_width + GetSystemMetrics(SM_CXVSCROLL);
end;
SendMessage(Handle, CB_SETDROPPEDWIDTH, max_width, 0);
inherited;
end;
procedure TNewComboBox.SetDropDownCount(const Value: Integer);
begin
inherited;
if HandleAllocated then
SendMessage(Handle, CB_SETMINVISIBLE, WPARAM(Value), 0);
end;
Спасибо за советы!