我想更改下拉列表的宽度以适合项目文本。这样做可能会使列表扩展到屏幕之外。我想做的是在屏幕内移动下拉列表,使其再次可见。
该问题在this article中进行了描述。但我尝试过,但不起作用。我从没有收到WM_CTLCOLORLISTBOX
消息。我还尝试将MoveWindow
方法与ComboBox.ListHandle
一起使用,但是列表是在默认位置绘制的。
答案 0 :(得分:1)
这就是我要创建一个具有自动列表宽度的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;
感谢您的提示!
答案 1 :(得分:0)
您可以使用GetComboBoxInfo:
const
WM_AFTER_DROPDOWN = WM_USER + 123;
type
TForm2 = class(TForm)
ComboBox1: TComboBox;
procedure ComboBox1DropDown(Sender: TObject);
private
procedure WMAfterDropDown(var Msg: TMessage); message WM_AFTER_DROPDOWN;
procedure MoveListWindow;
end;
var
Form2: TForm2;
implementation
procedure TForm2.MoveListWindow;
var
cbi: TComboBoxInfo;
r: TRect;
begin
cbi.cbSize := SizeOf(cbi);
GetComboBoxInfo(Combobox1.Handle, cbi);
GetWindowRect(cbi.hwndList, r);
MoveWindow(cbi.hwndList, 0, 0, r.Width, r.Height, true);
end;
procedure TForm2.WMAfterDropDown(var Msg: TMessage);
begin
MoveListWindow;
end;
procedure TForm2.ComboBox1DropDown(Sender: TObject);
begin
PostMessage(Handle, WM_AFTER_DROPDOWN, 0, 0);
end;