Delphi 如何通过下拉菜单检测鼠标单击按钮
我的问题是从中的答案接下去的 我试图复制Mircosoft Office 2007 UI左上角的“Office按钮”的行为;特别是当用户点击按钮时,弹出菜单出现,按钮在“向下”状态下被重新绘制。按钮图像保持在关闭状态,直到用户单击菜单上的鼠标,或表单上的其他位置,甚至在应用程序之外 我需要检测这个鼠标点击,这样我可以在正常图像中重新绘制按钮,如果我使用自己的对话框作为弹出菜单,则隐藏菜单 我正在使用D6。Delphi 如何通过下拉菜单检测鼠标单击按钮,delphi,Delphi,我的问题是从中的答案接下去的 我试图复制Mircosoft Office 2007 UI左上角的“Office按钮”的行为;特别是当用户点击按钮时,弹出菜单出现,按钮在“向下”状态下被重新绘制。按钮图像保持在关闭状态,直到用户单击菜单上的鼠标,或表单上的其他位置,甚至在应用程序之外 我需要检测这个鼠标点击,这样我可以在正常图像中重新绘制按钮,如果我使用自己的对话框作为弹出菜单,则隐藏菜单 我正在使用D6。 谢谢你的建议, 问候, 菲尔 澄清: 我现在意识到,当使用TPopUpMenu时,答案是
谢谢你的建议,
问候,
菲尔 澄清: 我现在意识到,当使用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语句在(!)之后立即将控制权返回到行。我已经澄清了我的问题。太棒了!非常感谢您的建议和代码。我感谢地接受了你的回答。