Delphi 如何通过下拉菜单检测鼠标单击按钮

Delphi 如何通过下拉菜单检测鼠标单击按钮,delphi,Delphi,我的问题是从中的答案接下去的 我试图复制Mircosoft Office 2007 UI左上角的“Office按钮”的行为;特别是当用户点击按钮时,弹出菜单出现,按钮在“向下”状态下被重新绘制。按钮图像保持在关闭状态,直到用户单击菜单上的鼠标,或表单上的其他位置,甚至在应用程序之外 我需要检测这个鼠标点击,这样我可以在正常图像中重新绘制按钮,如果我使用自己的对话框作为弹出菜单,则隐藏菜单 我正在使用D6。 谢谢你的建议, 问候, 菲尔 澄清: 我现在意识到,当使用TPopUpMenu时,答案是

我的问题是从中的答案接下去的

我试图复制Mircosoft Office 2007 UI左上角的“Office按钮”的行为;特别是当用户点击按钮时,弹出菜单出现,按钮在“向下”状态下被重新绘制。按钮图像保持在关闭状态,直到用户单击菜单上的鼠标,或表单上的其他位置,甚至在应用程序之外

我需要检测这个鼠标点击,这样我可以在正常图像中重新绘制按钮,如果我使用自己的对话框作为弹出菜单,则隐藏菜单

我正在使用D6。
谢谢你的建议,
问候,
菲尔

澄清:

我现在意识到,当使用TPopUpMenu时,答案是微不足道的,因为我有一个错误的理解,即一旦显示了弹出菜单,它就被留给了主事件循环的命运。在过去,我很高兴地编写了这样的代码。我的问题应该更具体一些,并说:

“当我使用对话框窗体充当TPopUpMenu时,如何检测此鼠标单击?”


很抱歉给你带来了困惑

也许我遗漏了什么,但至少对于弹出菜单来说,这很容易:

procedure TForm1.FormCreate(Sender: TObject);
begin
  SpeedButton1.AllowAllUp := TRUE;
  SpeedButton1.GroupIndex := 1;
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  CurPos: TPoint;
begin
  CurPos := Mouse.CursorPos;
  PopupMenu1.Popup(CurPos.x, CurPos.y);
  SpeedButton1.Down := FALSE;
end;
这是可行的,因为弹出式菜单是使用辅助消息循环显示的,在弹出式菜单外单击会将其关闭,就像单击菜单项一样

如果要显示表单而不是弹出菜单,只需提供一个包装函数,该函数仅在表单关闭时返回,类似于上面代码中的
popup()
。例如,您可以显示表单非模态,并使用
SetCaptureControl()
方法处理所有鼠标事件,即使鼠标光标位于表单区域之外

编辑:

一些让您开始的代码-它演示了原理,但肯定不是完整的或最佳的。显示的不是弹出菜单,而是表单:

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  PtLeftTop: TPoint;
begin
  PtLeftTop := ClientToScreen(Point(SpeedButton1.Left + SpeedButton1.Width,
    SpeedButton1.Top + SpeedButton1.Height));
  TForm2.ShowFormAsPopup(PtLeftTop);
  SpeedButton1.Down := FALSE;
end;
该表单具有以下代码:

type
  TForm2 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormDeactivate(Sender: TObject);
  public
    class procedure ShowFormAsPopup(ATopLeft: TPoint);
  end;

// boilerplate snipped

class procedure TForm2.ShowFormAsPopup(ATopLeft: TPoint);
var
  Form2: TForm2;
  OldDeactivate: TNotifyEvent;
begin
  Form2 := TForm2.Create(nil);
  try
    OldDeactivate := Application.OnDeactivate;
    try
      Application.OnDeactivate := Form2.FormDeactivate;

      Form2.Left := ATopLeft.x;
      Form2.Top := ATopLeft.y;
      Form2.Show;
      SetCaptureControl(Form2);
      while Form2.Visible do
        Application.ProcessMessages;
    finally
      Application.OnDeactivate := OldDeactivate;
    end;
  finally
    Form2.Release;
  end;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  KeyPreview := TRUE;
end;

procedure TForm2.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = VK_ESCAPE then
    Visible := FALSE;
end;

procedure TForm2.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  ScreenPos: TPoint;
begin
  ScreenPos := ClientToScreen(Point(X, Y));
  if (ScreenPos.X < Left) or (ScreenPos.Y < Top)
    or (ScreenPos.X > Left + Width) or (ScreenPos.Y > Top + Height)
  then begin
    Visible := FALSE;
  end;
end;

procedure TForm2.FormDeactivate(Sender: TObject);
begin
  Visible := FALSE;
end;
类型
TForm2=类别(TForm)
过程表单创建(发送方:ToObject);
过程FormKeyDown(发送方:ToObject;变量关键字:Word;
换档:t换档状态);
程序FormMouseDown(发送方:ToObject;按钮:TMouseButton;
移位:t移位状态;X,Y:整数);
程序表单停用(发送方:TObject);
公众的
课堂程序展示形式(ATopLeft:TPoint);
结束;
//剪样板
类程序TForm2.showFormsPopup(ATopLeft:TPoint);
变量
表2:TForm2;
OldDeactivate:TNotifyEvent;
开始
Form2:=TForm2.Create(nil);
尝试
OldDeactivate:=Application.OnDeactivate;
尝试
Application.OnDeactivate:=Form2.FormDeactivate;
形式2.左:=原子英尺x;
表2.顶部:=原子英尺y;
表2.表演;
SetCaptureControl(表格2);
而Form2.Visible做什么
Application.ProcessMessages;
最后
Application.OnDeactivate:=OldDeactivate;
结束;
最后
表2.发布;
结束;
结束;
过程TForm2.FormCreate(发送方:TObject);
开始
KeyPreview:=真;
结束;
过程TForm2.FormKeyDown(发送方:TObject;变量关键字:Word;
换档:t换档状态);
开始
如果Key=VK_,则退出
可见:=假;
结束;
程序TForm2.FormMouseDown(发送方:ToObject;按钮:TMouseButton;
移位:t移位状态;X,Y:整数);
变量
屏幕位置:TPoint;
开始
ScreenPos:=客户端到屏幕(点(X,Y));
如果(屏幕位置X<左侧)或(屏幕位置Y<顶部)
或(屏幕位置X>左+宽)或(屏幕位置Y>顶+高)
然后开始
可见:=假;
结束;
结束;
程序TForm2.FormDeactivate(发送方:ToObject);
开始
可见:=假;
结束;

相反,是我。花了很长时间才理解您的答案,直到我意识到Popup语句在(!)之后立即将控制权返回到行。我已经澄清了我的问题。太棒了!非常感谢您的建议和代码。我感谢地接受了你的回答。