【问题标题】:How to change the position of dropdown list of a combo box?如何更改组合框下拉列表的位置?
【发布时间】:2018-10-08 10:55:48
【问题描述】:

我想更改下拉列表的宽度以适合项目文本。这样做时,列表可能会扩展到屏幕之外。我想要做的是在屏幕内移动下拉列表以使其再次可见。

this article 中描述了该问题。但我试过了,它不起作用。我从未收到WM_CTLCOLORLISTBOX 消息。我还尝试将MoveWindow 方法与ComboBox.ListHandle 一起使用,但列表是在其默认位置绘制的。

【问题讨论】:

  • 您可以查看this 了解如何缩小下拉宽度,并根据您的目的进行调整。
  • 我不想缩小它,我想改变它的位置。
  • 我说过要根据您的目的对其进行调整。它展示了如何接收WM_CTCOLORLISTBOX 消息以及如何使用MoveWindow 方法。你还想要什么?
  • 哦,对不起!我没看好。好的,但是真的有必要挂钩 WindowProc 吗?仅使用procedure WMCtlColorListBox(var Msg: TMessage); message WM_CTLCOLORLISTBOX 不起作用?
  • 不,这不起作用。 Peter 下面回答了long time agoLook at the source. TCustomCombobox.WndProc does this: WM_CTLCOLORMSGBOX..WM_CTLCOLORSTATIC: begin SetTextColor(WParam, ColorToRGB(Font.Color)); SetBkColor(WParam, ColorToRGB(Brush.Color)); Result := Brush.Handle; Exit; end; There is no call to inherited, which means the message never reaches Dispatch and so your handler is never called. There is probably a reason for that but i don't know which.

标签: delphi combobox delphi-2009


【解决方案1】:

这就是我如何拥有一个具有自动列表宽度的组合框,它在下拉时不会出现在屏幕之外:

  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;

感谢您的提示!

【讨论】:

    【解决方案2】:

    您可以使用 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;
    

    【讨论】:

    • OnDropDown,但它不起作用。我认为手柄是错误的。
    • 我已经编辑了我的答案,你应该使用 PostMessage 让列表窗口首先被创建
    • 还是不行。列表移动成功,但动画出现在其默认位置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 2016-11-14
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多