您的组合框 (CB) 请求没有简单的解决方案。我记得 Windows CB 的下拉列表是屏幕的子项,而不是 CB。这样做的原因是能够在客户端窗口之外显示下拉列表,如下图所示。如果你问我,这很好。
建议的解决方案
这是尝试使用现有的 TComboBox 的尝试。TLama 的“丑陋代码”比我的更优雅,因为他使用了拦截器类。但是,我在下面的建议确实解决了另一种情况,即当鼠标向上移动并越过 ListBox 回到 Combobox 之间的边界时,列表框不会卷起。
unit main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.AppEvnts;
type
TFormMain = class(TForm)
ComboBox1: TComboBox;
Label1: TLabel;
Label2: TLabel;
procedure ComboBox1MouseEnter(Sender: TObject);
procedure ComboBox1CloseUp(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
FActiveCb : TComboBox; //Stores a reference to the currently active CB. If nil then no CB is in use
FActiveCbInfo : TComboBoxInfo; //stores relevant Handles used by the currently active CB
procedure ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
public
{ Public declarations }
end;
var
FormMain: TFormMain;
implementation
{$R *.dfm}
procedure TFormMain.FormCreate(Sender: TObject);
begin
FActiveCb := nil;
FActiveCbInfo.cbSize := sizeof(TComboBoxInfo);
Application.OnIdle := Self.ApplicationEvents1Idle;
end;
procedure TFormMain.ComboBox1CloseUp(Sender: TObject);
begin
FActiveCb := nil;
end;
procedure TFormMain.ComboBox1MouseEnter(Sender: TObject);
begin
FActiveCb := TComboBox(Sender);
FActiveCb.DroppedDown := true;
GetComboBoxInfo(FActiveCb.Handle, FActiveCbInfo); //Get CB's handles
end;
procedure TFormMain.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
var w : THandle;
begin
//Check if the mouse cursor is within the CB, it's Edit Box or it's List Box
w := WindowFromPoint(Mouse.CursorPos);
with FActiveCbInfo do
if Assigned(FActiveCb) and (w <> hwndList) and (w <> hwndCombo) and (w <> hwndItem) then
FActiveCb.DroppedDown := false;
end;
end.
如何添加额外的 CB
- 在表单上放置一个新的组合框。
- 将 ComboBox1MouseEnter proc 分配给 OnMouseEnter 事件
- 将 ComboBox1CloseUp proc 分配给 OnCloseUp 事件
问题
但仍有一些问题有待解决:
- 用户单击时列表框消失
- 无法使用鼠标选择 CB 中的文本
- 当然还有更多问题...