【问题标题】:Delphi, how to close TComboBox when mouse leaves?Delphi,鼠标离开时如何关闭TComboBox?
【发布时间】:2014-08-12 12:47:48
【问题描述】:

我正在尝试实现以下功能:

  1. 当鼠标移到组合框上时,它会自动打开。
  2. 当鼠标离开组合框区域(不仅是组合框,还有下拉列表)时,它会自动关闭。

第一点很简单:

procedure TForm1.ComboTimeUnitsMouseEnter(Sender: TObject);
begin
  ComboTimeUnits.DroppedDown := True;
end;

不过,第二点,我做不到。我试过了:

procedure TForm1.ComboTimeUnitsMouseLeave(Sender: TObject);
begin
  ComboTimeUnits.DroppedDown := False;
end;

但是当鼠标在组合框上时,它的行为很奇怪,出现又消失,变得无法使用。

我尝试了 AutoCloseUp 属性,但没有结果。现在我没有想法了,谷歌也帮不上忙。

有人能指出正确的方向吗?

【问题讨论】:

  • 下拉会触发鼠标离开,这不是你想要的——用户无法用鼠标选择任何东西。您最好开发自己的控件,组合框是一个标准控件,应该以标准方式运行。
  • 另外,您必须从打开的下拉列表中跟踪鼠标离开,而不是从组合(这只是 编辑框部分)。否则用户将无法选择任何内容。
  • 除了创建一个新控件别无他法?有没有具有此功能的组合框的库?
  • 这个ugly code 部分地做了你想要的(当用户进入下拉列表然后离开它时它会触发引入的事件),但是你需要采取更多的情况照顾。
  • 您的问题中要求支持该功能的库的部分在这里是题外话(这些类型的问题是不可接受的)。我已编辑删除该段落。

标签: delphi events mouseevent tcombobox


【解决方案1】:

您的组合框 (CB) 请求没有简单的解决方案。我记得 Windows CB 的下拉列表是屏幕的子项,而不是 CB。这样做的原因是能够在客户端窗口之外显示下拉列表,如下图所示。如果你问我,这很好。

建议的解决方案

尝试使用现有的 TComboBox。 TLama 的“ugly code”比我的更优雅,因为他使用了拦截器类。但是,我下面的建议确实解决了另一种情况,即当鼠标向上移动并越过 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.

如何添加额外的 CBs

  1. 在表单上放置一个新的组合框。
  2. 将 ComboBox1MouseEnter proc 分配给 OnMouseEnter 事件
  3. 将 ComboBox1CloseUp proc 分配给 OnCloseUp 事件

问题

但仍有一些问题有待解决:

  1. 用户单击时列表框消失
  2. 无法使用鼠标选择 CB 中的文本
  3. 当然还有更多问题...

【讨论】:

    猜你喜欢
    • 2017-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多