MouseLeave 事件不适用于按下左键单击
MouseLeave event not working with left click pressed
我正在使用 Delphi 测试 VCL 应用程序。我有一个带有标签的空表单,我用表单 FormMouseLeave
事件更改了该标签值。它有效,但如果我在离开表单时按住鼠标左键,则不会触发该事件。
我尝试拦截 WM_MOUSELEAVE
消息,但看起来根本没有触发(好吧,我想 FormMouseLeave
事件是基于该消息)
我不需要触发任何拖放,我只需要在按下左键单击鼠标离开我的表单时触发我的事件,我该怎么做?
这是 WM_MOUSELEAVE
消息的已知行为。您可以通过跟踪鼠标移动来绕过它,当鼠标离开边界时您可以自己触发事件。
当您按下鼠标按钮时,您的 window(表单)已捕获鼠标并且即使鼠标超出范围也会接收 WM_MOUSEMOVE
事件。 WM_MOUSELEAVE
消息用于在您未捕获鼠标时跟踪 window 内的鼠标。
如果您将 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;
当左键按下时,如果鼠标下方的控件在其控件样式中具有 csCaptureMouse
,则 VCL 框架会捕获鼠标。当鼠标被捕获时,WM_MOUSELEAVE
消息不会生成,直到捕获被释放。当左按钮上升时会发生这种情况。
如果您从鼠标下方的控件中删除 csCaptureMouse
,那么一旦鼠标离开 window,就会生成 WM_MOUSELEAVE
消息,因为鼠标不会离开捕获。
procedure TForm1.FormCreate(Sender: TObject);
begin
ControlStyle := ControlStyle - [csCaptureMouse];
end;
当然,为了达到这种效果而改变这种风格肯定不是你应该做的。我只是指出这一点以表明问题是由于鼠标捕获和鼠标跟踪之间的交互造成的。
但是我认为鼠标跟踪和 WM_MOUSELEAVE
并不是您真正想要的。 WM_MOUSELEAVE
当您将鼠标悬停在表单上的控件上时会触发,这肯定不是您想要的。
所以我认为 Dalija 的回答中概述的方法实际上是在任何情况下实现所需行为的正确方法,无论鼠标按钮是否按下。
我正在使用 Delphi 测试 VCL 应用程序。我有一个带有标签的空表单,我用表单 FormMouseLeave
事件更改了该标签值。它有效,但如果我在离开表单时按住鼠标左键,则不会触发该事件。
我尝试拦截 WM_MOUSELEAVE
消息,但看起来根本没有触发(好吧,我想 FormMouseLeave
事件是基于该消息)
我不需要触发任何拖放,我只需要在按下左键单击鼠标离开我的表单时触发我的事件,我该怎么做?
这是 WM_MOUSELEAVE
消息的已知行为。您可以通过跟踪鼠标移动来绕过它,当鼠标离开边界时您可以自己触发事件。
当您按下鼠标按钮时,您的 window(表单)已捕获鼠标并且即使鼠标超出范围也会接收 WM_MOUSEMOVE
事件。 WM_MOUSELEAVE
消息用于在您未捕获鼠标时跟踪 window 内的鼠标。
如果您将 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;
当左键按下时,如果鼠标下方的控件在其控件样式中具有 csCaptureMouse
,则 VCL 框架会捕获鼠标。当鼠标被捕获时,WM_MOUSELEAVE
消息不会生成,直到捕获被释放。当左按钮上升时会发生这种情况。
如果您从鼠标下方的控件中删除 csCaptureMouse
,那么一旦鼠标离开 window,就会生成 WM_MOUSELEAVE
消息,因为鼠标不会离开捕获。
procedure TForm1.FormCreate(Sender: TObject);
begin
ControlStyle := ControlStyle - [csCaptureMouse];
end;
当然,为了达到这种效果而改变这种风格肯定不是你应该做的。我只是指出这一点以表明问题是由于鼠标捕获和鼠标跟踪之间的交互造成的。
但是我认为鼠标跟踪和 WM_MOUSELEAVE
并不是您真正想要的。 WM_MOUSELEAVE
当您将鼠标悬停在表单上的控件上时会触发,这肯定不是您想要的。
所以我认为 Dalija 的回答中概述的方法实际上是在任何情况下实现所需行为的正确方法,无论鼠标按钮是否按下。