我在Delphi 7中使用TStringGrid时会出现奇怪的行为。 如果弹出式菜单与网格相关联,Delphi不会调用OnMouseUp事件。基本上,当人民币被按下时,菜单的弹出会以某种方式取消/延迟OnMouseUp。实际上,为了100%准确,下次按下鼠标按钮时,OnMouseUp会被调用两次 - 一次用于当前事件,一次用于丢失/延迟事件。TStringGrid - OnMouseUp不被调用!
这将拧紧程序的整个逻辑,因为下次用户按下鼠标按钮时会调用不需要的代码。
我在Delphi 7中使用TStringGrid时会出现奇怪的行为。 如果弹出式菜单与网格相关联,Delphi不会调用OnMouseUp事件。基本上,当人民币被按下时,菜单的弹出会以某种方式取消/延迟OnMouseUp。实际上,为了100%准确,下次按下鼠标按钮时,OnMouseUp会被调用两次 - 一次用于当前事件,一次用于丢失/延迟事件。TStringGrid - OnMouseUp不被调用!
这将拧紧程序的整个逻辑,因为下次用户按下鼠标按钮时会调用不需要的代码。
我已经采取了一个办法以某种方式与Sertac描述的相似:我只是不使用的弹出菜单属性再指定一个弹出菜单到电网。相反,在我的网格内(我的网格是一个从TStringGrid派生的大量修改的字符串网格)我处理鼠标按下事件,并以我想要的方式显示弹出窗口,并在弹出菜单之前执行额外的处理。
上下文菜单的自动弹出是对鼠标右击的响应。同样的点击也触发了OnMouseUp
事件。 VCL开发者可以选择在显示弹出窗口之前或之后触发“OnMouseUp”事件。显然后者是有效的,也就是说,当弹出窗口关闭时(通过鼠标或键盘按'Esc'),该事件被触发。
事件没有加倍,当您按下左键关闭弹出窗口时,您将通过释放左键再次触发'OnMouseUp'事件。
你有几种选择。一种是派生一个新班级,并重写MouseDown
方法来发起你自己的事件。一个例子;
type
TMyStringGrid = class(TStringGrid)
private
FOnRButtonUp: TMouseEvent;
protected
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
published
property OnRButtonUp: TMouseEvent read FOnRButtonUp write FOnRButtonUp;
end;
[...]
procedure TStringGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
if (Button = mbRight) and Assigned(FOnRButtonUp) then
FOnRButtonUp(Self, Button, Shift, X, Y);
inherited;
end;
另一种替代方法可以是处理VM_RBUTTONUP
消息。这可以通过如上导出新的类或者替换网格的WindowProc
来完成。在这个question中有一个替换WindowProc here的例子。
另一种替代方法是单击鼠标悬停事件并在弹出式菜单的OnPopup
事件中执行处理。此事件在弹出窗口显示之前触发。你可以用Mouse.CursorPos
得到鼠标坐标。
不过,另一种选择可以是弹出式菜单的AutoPopup
属性设置为False
,并在OnMouseUp
事件(或更好,但在OnContextMenu
事件)首先做一些处理,然后显示弹出。一个例子;
procedure TForm1.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
Pt: TPoint;
begin
// Do processing
if Button = mbRight then begin
Pt := (Sender as TStringGrid).ClientToScreen(Point(X, Y));
PopupMenu1.Popup(Pt.X, Pt.Y);
end;
end;
“显然后者是有效的”。这是一个直觉,因为OnMouseUp事件不再是鼠标事件。事实上,这是一个“鼠标向下”的事件! +1为您的非常完整的答案。 – Ampere 2010-07-20 02:11:25
@Altar>“...... counter direct ...” - 我同意,考虑到弹出式菜单实际上是对WM_CONTEXTMENU的响应,它不仅用WM_RBUTTONUP生成,而且用WM_NCRBUTTONUP和' Shift + F10'和VK_APPS,并且,例如用VK_APPS,在显示弹出窗口之前触发* OnKeyUp。 – 2010-07-20 14:18:38