Delphi,鼠标离开时如何关闭TComboBox?

时间:2014-08-12 12:47:49

标签: delphi events mouseevent tcombobox

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

  1. 当鼠标越过组合框时,它会自动打开。
  2. 当鼠标离开组合框区域(不仅是组合,但也是下拉列表)时,它会自动关闭。
  3. 第一点非常简单:

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

    第二点,我不能这样做。我试过了:

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

    但是当鼠标在组合框上方时,它会非常奇怪,出现并消失,变得无法使用。

    我尝试了AutoCloseUp属性,没有结果。现在我没有想法,谷歌无法帮助。

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

1 个答案:

答案 0 :(得分:2)

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

enter image description here

建议的解决方案

这是尝试使用现有的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.

如何添加额外的CB

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

    然而,有些问题仍有待解决:

    1. 当用户点击
    2. 时,ListBox消失
    3. 无法使用鼠标选择CB中的文本
    4. 肯定会有更多问题......