我的问题从答案中得出 How to create a button with drop-down menu?
我正在尝试复制Mircosoft Office 2007 UI左上角的“Office按钮”的行为;特别是在用户点击按钮的情况下,弹出菜单出现,按钮被重新绘制为“向下”状态。按钮图像保持在Down状态,直到用户单击菜单上的鼠标或表单上的其他位置,甚至是应用程序外部。
我需要检测此鼠标点击,以便我可以重绘正常图像中的按钮,如果我使用自己的对话框作为弹出菜单,则隐藏菜单。
我正在使用D6
谢谢你的建议,
问候,
PhilW。
澄清:
我现在意识到,当使用TPopUpMenu时,答案是微不足道的,因为一旦弹出菜单被显示,它就被错误理解,它留给了主事件循环的命运。我过去很乐意编码。更聪明,有点尴尬(但朋友之间没关系)我的问题应该更具体,并说:
“当我使用对话框表单作为TPopUpMenu时,如何检测此鼠标单击?”
很抱歉这个混乱。
答案 0 :(得分: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;