本文介绍了我可以以编程方式设置 ComboBox 下拉列表的位置吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

普通 Windows 组合框(csDropDowncsDropDownList 样式)将打开其下方的下拉列表,如果下方没有空格,则在组合上方打开.我可以控制这个列表的位置(至少通过 Y 坐标)吗?

Ordinary Windows ComboBox (csDropDown or csDropDownList style) will open its dropdown list right below or, if no space left below, above the combo. Can I control the position of this list (at least by Y coordinate)?

推荐答案

发布一个代码示例,该示例将正确显示下拉列表动画并强制显示ComboBox1 上方的下拉列表.此代码子类 ComboBox hwndList:

Posting a code example that will show drop-down list animation correctly and will force showing the drop-down list above ComboBox1. this code subclasses ComboBox hwndList:

TForm1 = class(TForm)
  ComboBox1: TComboBox;
  procedure FormCreate(Sender: TObject);
  procedure FormDestroy(Sender: TObject);
private
  FComboBoxListDropDown: Boolean;
  FComboBoxListWnd: HWND;
  FOldComboBoxListWndProc, FNewComboBoxListWndProc: Pointer;
  procedure ComboBoxListWndProc(var Message: TMessage);
end;

....

procedure TForm1.FormCreate(Sender: TObject);
var
  Info: TComboBoxInfo;
begin
  ZeroMemory(@Info, SizeOf(Info));
  Info.cbSize := SizeOf(Info);
  GetComboBoxInfo(ComboBox1.Handle, Info);
  FComboBoxListWnd := Info.hwndList;
  FNewComboBoxListWndProc := MakeObjectInstance(ComboBoxListWndProc);
  FOldComboBoxListWndProc := Pointer(GetWindowLong(FComboBoxListWnd, GWL_WNDPROC));
  SetWindowLong(FComboBoxListWnd, GWL_WNDPROC, Integer(FNewComboBoxListWndProc));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  SetWindowLong(FComboBoxListWnd, GWL_WNDPROC, Integer(FOldComboBoxListWndProc));
  FreeObjectInstance(FNewComboBoxListWndProc);
end;

procedure TForm1.ComboBoxListWndProc(var Message: TMessage);
var
  R: TRect;
  DY: Integer;
begin
  if (Message.Msg = WM_MOVE) and not FComboBoxListDropDown then
  begin
    FComboBoxListDropDown := True;
    try
      GetWindowRect(FComboBoxListWnd, R);
      DY := (R.Bottom - R.Top) + ComboBox1.Height + 1;
      // set new Y position for drop-down list: always above ComboBox1
      SetWindowPos(FComboBoxListWnd, 0, R.Left, R.Top - DY , 0, 0,
        SWP_NOOWNERZORDER or SWP_NOZORDER or SWP_NOSIZE  or SWP_NOSENDCHANGING);
    finally
      FComboBoxListDropDown := False;
    end;
  end;
  Message.Result := CallWindowProc(FOldComboBoxListWndProc,
    FComboBoxListWnd, Message.Msg, Message.WParam, Message.LParam);
end;

注意事项:

  1. 我完全同意 David 和其他人的观点,即更改 TComboBox 的这一特定默认行为是一个坏主意.OP 尚未回应为什么他想要这种行为.
  2. 以上代码已使用 D5/XP 进行测试.
  1. I totally agree with David, and others that this is a bad idea to change this specific default behavior for TComboBox. OP did not yet respond to why he wanted such behavior.
  2. The code above was tested with D5/XP.

这篇关于我可以以编程方式设置 ComboBox 下拉列表的位置吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-26 10:25