如何使ComboBox下拉列表比ComboBox本身“更窄” [英] How to make ComboBox drop-down list be *Narrower* than the ComboBox itself

查看:88
本文介绍了如何使ComboBox下拉列表比ComboBox本身“更窄”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以使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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆