【问题标题】:How to detect a mouse click for a button with drop down menu如何检测带有下拉菜单的按钮的鼠标点击
【发布时间】:2009-07-26 07:58:46
【问题描述】:

我的问题来自于 How to create a button with drop-down menu?

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

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

我正在使用 D6。
感谢您的任何建议,
问候,
菲尔W。

澄清:

我现在意识到,当使用 TPopUpMenu 时,答案是微不足道的,因为我错误地理解为一旦显示弹出菜单,它就由主事件循环的命运决定了。我过去很高兴地这样编码。更聪明,有点尴尬(但朋友之间没关系)我的问题应该更具体,并说:

“当我使用对话框表单来充当 TPopUpMenu 时,如何检测鼠标点击?”

很抱歉给您带来了困惑。

【问题讨论】:

    标签: delphi


    【解决方案1】:

    也许我遗漏了一些东西,但至少对于弹出菜单来说这很容易:

    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;
    

    【讨论】:

    • 相反,是我。花了很长时间才理解您的答案,直到我意识到 Popup 语句在(!)之后立即将控制权返回给该行。我已经澄清了我的问题。
    • 太棒了!非常感谢建议和代码。感谢接受。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-06
    • 2018-07-27
    • 1970-01-01
    • 2010-09-19
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多