如何检测鼠标点击一个按钮,下拉菜单

问题描述:

我的问题与答案如下在 How to create a button with drop-down menu?如何检测鼠标点击一个按钮,下拉菜单

我试图复制在左上角发现了“Office按钮”的行为的Mircosoft Office 2007用户界面;特别是在用户点击按钮的地方,弹出菜单出现并且按钮在“下”状态中被重新绘制。按钮图像保持在向下状态,直到用户单击菜单上的鼠标或表单上的其他位置或者甚至在应用程序外部。

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

我正在使用D6。
感谢您的任何建议,
关心,
PhilW。

澄清:

我现在认识到,答案是琐碎当使用TPopUpMenu,已经以曾经在弹出菜单中显示的错误认识,它留给主事件的命运循环。我过去曾愉快地编码。 Wiser,有点尴尬(但朋友之间没关系)我的问题应该是更具体的,并且说:

“当我使用对话框表单来行为像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; 
+0

金恰恰相反,那是我。花了很长时间才能理解你的答案,直到我意识到Popup语句在(!)之后立即返回控制权。我澄清了我的问题。 – PhilW 2009-07-27 07:06:48