为什么WM_LBUTTONUP消息在Delphi中消失?

时间:2014-08-11 18:11:55

标签: delphi message

当我这样写时,MouseDownMouseUp会运行:

procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
    Label1.Caption:='ddddddd';
end;

procedure TForm1.Edit1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
    ShowMessage('mouseup');
end;

但是当我这样写的时候,WM_LBUTTONUP dispear和Edit1MouseUp将无法运行,为什么?

procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
    ShowMessage('mousedown');
end;

procedure TForm1.Edit1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
    ShowMessage('mouseup');
end;

2 个答案:

答案 0 :(得分:1)

当您致电ShowMessage时,会显示模态窗口。在模态窗口关闭之前,对ShowMessage的调用不会返回。模态窗口运行自己的消息循环,然后吃掉鼠标消息。因此,消息队列中已经或即将放置在消息队列中的WM_LBUTTONUP实际上是由消息框而不是您的Delphi表单处理的。

该邮件究竟是如何处理的?这得看情况。如果在显示模式窗口之前发布了消息,那么它将被分派到所有者窗口,该窗口被禁用。如果在显示模态窗口后发布,则可以将其分派到模态窗口。

这是通过鼠标向上而不是向下鼠标调用操作的原因之一。也许你还没有注意到,但是尝试点击任何常见应用程序中的按钮,并注意只有在鼠标上升时才会出现响应。实际上,如果您按下鼠标按钮,将光标移离按钮,然后松开按钮,动作就不会触发。

现在尝试与您的第二个代码示例类似的东西。在编辑控件中按下鼠标但不要立即释放它。请注意,鼠标停止的结果是现在显示模态窗口。它运行自己的消息循环,表单被禁用。现在释放鼠标按钮。很明显,WM_LBUTTONUP消息将被模态窗口的消息循环从队列中拉出。

答案 1 :(得分:0)

在您的第二个方案中,编辑控件永远不会发布WM_LBUTTONUP,因此不会触发OnMouseUp事件。

当您在ShowMessage中致电OnMouseDown时,会启动一个对话框。这不仅会从编辑控件中释放鼠标捕获,还会禁用表单。使用这两个消息时,无法发布消息:不是带有捕获的窗口,而是指向光标下的窗口(参见documentation)。

您可以使用此代码模拟行为,而不显示消息:

procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Assert(GetCapture = Edit1.Handle);
  ReleaseCapture;
  Enabled := False;
end;

procedure TForm1.Edit1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  ShowMessage('mouseup'); // will not fire.
end;


道德是:不要使用ShowMessage来调试涉及激活/焦点的情况。因为在这种情况下可能不太明显,所以通常不要将它用作调试工具。