我在Delphi 7中对TStringGrid有一种奇怪的行为。 如果弹出菜单与网格关联,Delphi不会调用OnMouseUp事件。基本上,当人民币被按下时,菜单的弹出以某种方式取消/延迟OnMouseUp。实际上,为了100%准确,下次按下鼠标按钮时,OnMouseUp会被调用两次 - 一次用于当前事件,一次用于丢失/延迟事件。
这将搞砸程序的整个逻辑,因为下次当用户按下鼠标按钮时会调用不需要的代码。
答案 0 :(得分:4)
自动弹出上下文菜单是对鼠标右键单击的响应。同样的点击也会触发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
来完成。有一个替换此here中的WindowProc question的示例。
另一种选择可以是单独留下鼠标添加事件,并在弹出菜单的OnPopup
事件中进行处理。在弹出窗口显示之前触发此事件。您可以使用Mouse.CursorPos
获取鼠标坐标。
另外,另一种方法是将弹出菜单的AutoPopup
属性设置为False
,并设置在OnMouseUp
事件中(或更好地在{{} 1}} event)首先进行一些处理,然后显示弹出窗口。一个例子;
OnContextMenu
答案 1 :(得分:0)
我已经采用了与Sertac描述的方法类似的方法:我只是不再使用PopupMenu属性来为网格分配弹出菜单。相反,在我的网格内(我的网格是一个从TStringGrid派生的大量修改的字符串网格)我处理鼠标按下事件并以我想要的方式显示弹出窗口并在菜单弹出之前执行我想要做的额外处理。