我在Delphi7中使用TStringGrid有一个奇怪的行为,如果一个弹出式菜单与网格相关联,Delphi就不会调用OnMouseUp事件。基本上,当按下人民币时,菜单的弹出以某种方式取消/延迟OnMouseUp。实际上,为了100%准确,下一次你按下鼠标按钮时,OnMouseUp会被调用两次-一次是针对当前事件,另一次是针对丢失/延迟事件。
这将搞乱整个程序逻辑,因为当用户下一次按下鼠标按键时,不需要的代码将被调用。
发布于 2010-07-20 10:10:30
我已经采用了一种与Sertac描述的方法类似的方法:我只是不再使用PopupMenu属性来为网格分配弹出菜单。相反,在我的网格中(我的网格是一个从TStringGrid派生的经过大量修改的字符串网格),我处理鼠标按下事件,以我想要的方式显示弹出窗口,并在菜单弹出之前执行我想做的额外处理。
发布于 2010-07-20 09:51:39
上下文菜单的自动弹出是对鼠标右键点击的响应。同样的单击也会触发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获取鼠标坐标。
另外,另一种方法是将popup menu的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;https://stackoverflow.com/questions/3285604
复制相似问题