gpt4 book ai didi

delphi - TStringGrid - OnMouseUp 未被调用!

转载 作者:行者123 更新时间:2023-12-02 06:12:10 25 4
gpt4 key购买 nike

我在 Delphi 7 中的 TStringGrid 有一个奇怪的行为。如果弹出菜单与网格关联,Delphi 不会调用 OnMouseUp 事件。基本上,当按下人民币时,菜单的弹出会以某种方式取消/延迟 OnMouseUp。实际上,为了 100% 准确,下次按下鼠标按钮时,OnMouseUp 会被调用两次 - 一次针对当前事件,一次针对丢失/延迟事件。

这将搞乱程序的整个逻辑,因为下次用户按下鼠标按钮时将调用不需要的代码。

最佳答案

自动弹出上下文菜单是对鼠标右键单击的响应。同一次单击还会触发 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 来完成。有一个替换 WindowProc here 的示例在这个question .


另一种选择是单独保留鼠标释放事件,并在弹出菜单的 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;

关于delphi - TStringGrid - OnMouseUp 未被调用!,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3285604/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com