如何检测在PictureBox上按住鼠标按钮的操作?

10

当鼠标已经被点击并按住时,我需要在鼠标位于 PictureBox 上时触发一个事件。

问题:

MouseDown 和 MouseEnter 事件处理程序不太兼容。

例如,一旦鼠标按钮被点击并保持按下状态,C# 将触发 MouseDown 事件处理程序,但当光标移动到 PictureBox 上时,MouseEnter 事件不会触发,直到鼠标按钮被释放。

8个回答

13

鼠标事件

使用MouseDown事件来检测鼠标按键的按下,并将this.Capture设置为true,以便在鼠标离开控件时也可以获取其他鼠标事件(即您不会收到MouseLeave事件,因为您捕获了鼠标)。当MouseUp发生时,通过将this.Capture设置为false来释放捕获。

仅检查鼠标状态

这可能并不相关,但您可以检查System.Windows.Control.MousePosition是否在PictureBox.ClientRectangle中,然后检查Control.MouseButtons静态属性以查看任何时间可能按下的按钮。

例如:

if  (pictureBox.ClientRectangle.Contains(pictureBox.PointToClient(Control.MousePosition)))
{
   if ((Control.MouseButtons & MouseButtons.Left) != 0)
   {
     // Left button is down.
   }
}

非常接近了!清除 this.capture 对于 MouseLeave 可行,但对于另一个 PictureBox 的 MouseEnter 不可行。 - Justin Tanner
我并没有完全理解你想要实现什么,所以很遗憾,这个方法不可行。 - Jeff Yates

13

当鼠标按下时,大多数控件都会使用Control.Capture捕获鼠标输入。这意味着所有的MouseMove事件都会被发送到原始控件而不是鼠标所在的控件。这种情况会一直持续到鼠标失去捕获,通常发生在鼠标抬起时。

如果您确实需要知道鼠标何时落在您的控件上,即使另一个控件已经捕获了鼠标输入,那么只有一种办法。你需要窃听应用程序内其他控件的Windows消息。为此,您需要添加一个消息过滤器...

Application.AddMessageFilter(myFilterClassInstance);

接下来,您需要在合适的类上实现IMessageFilter...

public class MyFilterClass : IMessageFilter
{
    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_MOUSEMOVE)
            // Check if mouse is over my picture box!

        return false;
    }
}

然后你需要监听鼠标移动事件,并检查它们是否在你的图片框上,然后执行你想做的任何操作。


5
在PictureBox控件内设置MouseMove事件:
this.myPictureBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.myPictureBox_MouseMove);

然后,在您的MouseMove事件处理程序中,检查左鼠标按钮(或其他按钮)是否被按下:

private void myPictureBox_MouseMove(object sender, MouseEventArgs e)
{  
     if (e.Button == MouseButtons.Left)
         // Do what you want to do
}

注意:这是一个WinForms API,而不是WPF(无论如何+1!) - Li3ro

3
如果您想要实现某种拖放操作,那么您需要使用接收方图片框上的“拖动...事件”(如DragEnter、DragDrop等)。基本上,您可以使用源控件的DoDragDrop方法来启动拖动操作,然后拖动到任何控件时都会触发其拖动事件。请在MSDN上搜索“DoDragDrop”以了解如何实现此操作。

从听起来的情况来看,这可能是正确的方法。如果UI不是拖放导向的,那么为什么我们要寻找在一个控件中开始并在另一个控件中结束的鼠标事件呢? :) - John Rudy

1
你可以使用预览事件
比如说我想检测我的按钮上的鼠标按下事件。MouseDown事件不能起作用,因为正如这里的一个答案所说,鼠标捕获被发送到主控件,但是你可以使用鼠标预览事件。
以下是一段代码示例
我想在我的按钮上检查当左键鼠标按下时,因此我使用PreviewMouseLeftButtonDown。
    private void MyButton_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        // code here
    }

WPF有许多其他事件的预览事件,您可以在此处阅读有关它们的信息

预览事件 - 它特别讨论了按钮及其与鼠标事件的交互方式,因此我强烈建议您阅读它


0

根据鼠标位置移动窗体并控制相对位置的最佳方法类似于Ian Campbell发布的内容。

    private void imgMoveWindow_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            Form1.ActiveForm.Left = Control.MousePosition.X - imgMoveWindow.Left - (imgMoveWindow.Size.Width/2);
            Form1.ActiveForm.Top = Control.MousePosition.Y - imgMoveWindow.Top - (imgMoveWindow.Size.Height/2); 
        }

    }

其中imgMoveWindow是一个PictureBox控件。

Bruno Ratnieks

Sniffer Networks


0
你应该尝试使用图片框的MouseMove事件而不是MouseEnter事件,因为MouseMove事件通常会在鼠标按钮状态下触发。

-1

在鼠标按下时设置一个标志或状态。当鼠标悬停于图片框时,检查您的状态。现在您可以检测到用户是否正在拖动某些内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接