如何使ComboBox下拉列表比ComboBox本身“更窄” [英] How to make ComboBox drop-down list be *Narrower* than the ComboBox itself
问题描述
是否可以使ComboBox下拉列表比Combobox本身更窄 ?
有很多示例可以设置宽度使用
SendMessage(Handle,CB_SETDROPPEDWIDTH,100,200);
但最小值是从组合框本身获取的,无论此处指定了什么。
所有这些示例都使其变得更大。
在下降之前-down列表将被绘制,一个
您可以通过创建中介程序类来进行小技巧。要么将其放在单独的单元中,然后在 vcl.StdCtrls
之后声明,要么将其置于表单单元中。
type
TComboBox = class(vcl.StdCtrls.TComboBox)
private
FDropDownWidth:Integer;
函数GetDropDownWidth:整数;
受保护的
过程WndProc(var Mess:TMessage);覆盖
public
构造函数Create(aOwner:TComponent);覆盖
属性DropDownWidth:整数读取GetDropDownWidth写入FDropDownWidth;
结尾;
构造函数TComboBox.Create(aOwner:TComponent);
开始
继承;
DropDownWidth:= -1; //默认状态
end;
函数TComboBox.GetDropDownWidth:整数;
如果FDropDownWidth = -1开始
,则//只保留默认状态
结果:= Self.Width
否则
结果:= FDropDownWidth;
结尾;
过程TComboBox.WndProc(var Mess:TMessage);
var
lbr:TRect;
开始
如果Mess.Msg = WM_CTLCOLORLISTBOX然后
开始
//列表框矩形
GetWindowRect(Mess.LParam,lbr);
//缩小窗口宽度
MoveWindow(Mess.LParam,
lbr.Left,
lbr.Top,
DropDownWidth,
lbr.Bottom-lbr .top,
false);
结束
否则
如果Mess.Msg = CB_SETDROPPEDWIDTH然后
DropDownWidth:= Mess.WParam;
继承的WndProc(Mess);
结尾;
都可以使用 cb设置下拉宽度。Perform(CB_SETDROPPEDWIDTH,newWidth ,0);
或 cb.DropDownWidth:= newWidth;
Is it possible to make a ComboBox Drop-down list be Narrower than the Combobox itself?
There are plenty of examples setting the width using
SendMessage(Handle, CB_SETDROPPEDWIDTH, 100, 200);
but the minimum value is taken from the combobox itself, regardless of what is specificed here.
All these examples make it bigger.
Before the drop-down list is to be painted, a WM_CTLCOLORLISTBOX message is issued.
By overriding the combobox WindowProc
it is possible to shrink the drop down list width.
The WM_CTLCOLORLISTBOX
message is detected and since the message supplies the handle of the list window, we can grab the list bounds and call MoveWindow
with a shrinked width.
type
TMyForm = class(TForm)
...
ComboBox1 : TComboBox;
procedure FormCreate(Sender: TObject);
...
private
{ Private declarations }
ComboBox1WindowProcORIGINAL : TWndMethod;
procedure ComboBox1WindowProc(var Message: TMessage);
...
end;
procedure TMyForm.ComboBox1WindowProc(var Message: TMessage);
var
lbr: TRect;
begin
//drawing the list box with combobox items
if Message.Msg = WM_CTLCOLORLISTBOX then
begin
//list box rectangle
GetWindowRect(Message.LParam, lbr);
//Shrink window width
MoveWindow( Message.LParam,
lbr.Left,
lbr.Top,
50, // New width
lbr.Bottom-lbr.Top,
false);
end;
ComboBox1WindowProcORIGINAL(Message);
end;
procedure TMyForm.FormCreate(Sender: TObject);
begin
//attach custom WindowProc for ComboBox1
ComboBox1WindowProcORIGINAL := ComboBox1.WindowProc;
ComboBox1.WindowProc := ComboBox1WindowProc;
end;
You can make a small hack by creating an interposer class. Either put it in a separate unit and declare it after vcl.StdCtrls
, or put it in your form unit.
type
TComboBox = class(vcl.StdCtrls.TComboBox)
private
FDropDownWidth : Integer;
function GetDropDownWidth : Integer;
protected
procedure WndProc(var Mess: TMessage); override;
public
Constructor Create( aOwner: TComponent ); override;
property DropDownWidth : Integer read GetDropDownWidth write FDropDownWidth;
end;
constructor TComboBox.Create(aOwner: TComponent);
begin
inherited;
DropDownWidth := -1; // Default state
end;
function TComboBox.GetDropDownWidth: Integer;
begin
if FDropDownWidth = -1 then // Just keep a default state
Result := Self.Width
else
Result := FDropDownWidth;
end;
procedure TComboBox.WndProc(var Mess: TMessage);
var
lbr: TRect;
begin
if Mess.Msg = WM_CTLCOLORLISTBOX then
begin
//list box rectangle
GetWindowRect(Mess.LParam, lbr);
//Shrink window width
MoveWindow( Mess.LParam,
lbr.Left,
lbr.Top,
DropDownWidth,
lbr.Bottom-lbr.Top,
false);
end
else
if Mess.Msg = CB_SETDROPPEDWIDTH then
DropDownWidth := Mess.WParam;
Inherited WndProc(Mess);
end;
Either set the drop-down width with cb.Perform(CB_SETDROPPEDWIDTH,newWidth,0);
or cb.DropDownWidth := newWidth;
这篇关于如何使ComboBox下拉列表比ComboBox本身“更窄”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!