【问题标题】:MouseLeave event not working with left click pressedMouseLeave 事件在按下左键时不起作用
【发布时间】:2016-07-20 22:20:12
【问题描述】:
我正在用 Delphi 做一个测试 VCL 应用程序。我有一个带有标签的空表单,我使用FormMouseLeave 事件的形式更改了该标签值。它可以工作,但是如果我在离开表单时按住鼠标左键,则不会触发事件。
我尝试拦截WM_MOUSELEAVE 消息,但看起来它根本没有触发(好吧,我猜FormMouseLeave 事件是基于该消息)
我不需要触发任何拖放,我只需要鼠标左键离开表单时的事件,我该怎么做?
【问题讨论】:
标签:
windows
delphi
winapi
mouseevent
vcl
【解决方案1】:
这是WM_MOUSELEAVE 消息的已知行为。您可以通过跟踪鼠标移动来规避它,当鼠标离开表单边界时,您可以自己触发事件。
当您按下鼠标按钮时,您的窗口(窗体)已经捕获了鼠标,并且即使鼠标超出了边界也会收到WM_MOUSEMOVE 事件。 WM_MOUSELEAVE 消息用于在您没有捕获鼠标时跟踪窗口内的鼠标。
如果您将MouseEnter、MouseLeave 和MouseMove 事件分配给您的表单,您可以执行以下操作:
procedure TForm1.FormMouseEnter(Sender: TObject);
begin
Label1.Caption := '';
end;
procedure TForm1.FormMouseLeave(Sender: TObject);
begin
Label1.Caption := 'left';
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
if not PtInRect(ClientRect, TPoint.Create(x, y)) then Label1.Caption := 'left move';
end;
【解决方案2】:
当左键按下时,如果鼠标下方的控件在其控件样式中具有csCaptureMouse,则 VCL 框架会捕获鼠标。捕获鼠标时,直到释放捕获后才会生成WM_MOUSELEAVE 消息。当左键上升时会发生这种情况。
如果您从鼠标下方的控件中删除了csCaptureMouse,那么一旦鼠标离开窗口就会生成WM_MOUSELEAVE 消息,因为鼠标不会被捕获。
procedure TForm1.FormCreate(Sender: TObject);
begin
ControlStyle := ControlStyle - [csCaptureMouse];
end;
当然,为了达到这种效果而改变这种风格肯定不是你应该做的。我只是指出这一点是为了表明问题是由于鼠标捕获和鼠标跟踪之间的交互造成的。
但我认为鼠标跟踪和WM_MOUSELEAVE 并不是您真正想要的。当您将鼠标悬停在表单上的控件上时会触发 WM_MOUSELEAVE,这肯定不是您想要的。
所以我认为 Dalija 的答案中概述的方法实际上是在任何情况下实现所需行为的正确方法,无论鼠标按钮是否按下。