Winforms 带Picturebox的鼠标滚轮事件?

Winforms 带Picturebox的鼠标滚轮事件?,winforms,mousewheel,Winforms,Mousewheel,我想将鼠标悬停在一个picturebox(或所有图片和主窗体)上,然后使用鼠标滚轮滚动。但是我没有运气。我写了pictureBox1.MouseWheel并检查了delta。我为它设置了一个断点!=0到目前为止,无论我做了什么,我都无法让任何事情发生。我也试过mousemove,但没用。然而,破坏if语句是可行的。我就是无法让轮子运转 如何使picturebox(或表单中的任何控件)调用鼠标滚轮事件 -编辑-无需担心。我将事件添加到大多数时间都有该事件的对象中。它工作得很好。我不知道为什么我在写

我想将鼠标悬停在一个picturebox(或所有图片和主窗体)上,然后使用鼠标滚轮滚动。但是我没有运气。我写了pictureBox1.MouseWheel并检查了delta。我为它设置了一个断点!=0到目前为止,无论我做了什么,我都无法让任何事情发生。我也试过mousemove,但没用。然而,破坏if语句是可行的。我就是无法让轮子运转

如何使picturebox(或表单中的任何控件)调用鼠标滚轮事件


-编辑-无需担心。我将事件添加到大多数时间都有该事件的对象中。它工作得很好。我不知道为什么我在写这个问题之前没有想到这一点。我仍然对鼠标+滚轮解决方案持开放态度。

Windows不会将鼠标滚动消息发送到悬停的控件,而是发送到具有焦点的控件。您已经知道如何修复焦点

由于浏览器和Office程序的工作方式,这种行为变得不直观。您将在中的我的答案中找到更改此的代码。请注意,它适用于应用程序中的任何窗口。如果不需要,您必须在句柄值上添加过滤



更新:此行为已在Win10中更改。它有一个名为“当我将鼠标悬停在非活动窗口上时滚动它们”的新系统设置,默认情况下处于启用状态。所以焦点不再重要了,它现在的工作方式和它在浏览器中的行为非常相似。测试应用程序很重要,您可以通过临时禁用系统选项来查看旧版本Windows上发生的情况。

说明了如何执行此操作。简而言之,在图片框上创建一个MouseEnter事件,该事件仅聚焦图片框。然后,图片框将接收鼠标滚轮事件。这里的答案对我不起作用。 我有一个可滚动的窗格中的picturebox,没有多少工作要做才能正常工作

您需要做的是覆盖表单中的
onmouseheel()
函数。 在这里,您将获得wheel事件,您必须检查鼠标是否在picturebox中。但这还不够。假设您在一个只显示图像一小部分的可滚动窗格中显示5000 x 5000像素的图像。然后,您还必须检查鼠标是否位于窗格及其所有父项上。下面的代码独立于pictureBox的任何父控件的滚动条的滚动位置

/// <summary>
/// This must be overridden in the Form because the pictureBox never receives MouseWheel messages
/// </summary>
protected override void OnMouseWheel(MouseEventArgs e)
{
    // Do not use MouseEventArgs.X, Y because they are relative!
    Point pt_MouseAbs = Control.MousePosition; 
    Control i_Ctrl = pictureBox;
    do
    {
        Rectangle r_Ctrl = i_Ctrl.RectangleToScreen(i_Ctrl.ClientRectangle);
        if (!r_Ctrl.Contains(pt_MouseAbs))
        {
            base.OnMouseWheel(e);
            return; // mouse position is outside the picturebox or it's parents
        }
        i_Ctrl = i_Ctrl.Parent;
    }
    while (i_Ctrl != null && i_Ctrl != this);

    // here you have the mouse position relative to the pictureBox if you need it
    Point pt_MouseRel = pictureBox.PointToClient(pt_MouseAbs);

    // Do your work here
    ....
}
//
///由于pictureBox从不接收鼠标滚轮消息,因此必须在表单中覆盖此项
/// 
MouseWheel上的受保护覆盖无效(MouseEventArgs e)
{
//不要使用MouseEventArgs.X,Y,因为它们是相对的!
点pt_MouseAbs=Control.MousePosition;
控件i_Ctrl=pictureBox;
做
{
矩形r_Ctrl=i_Ctrl.RectangleToScreen(i_Ctrl.ClientRectangle);
如果(!r_Ctrl.包含(pt_MouseAbs))
{
底轮(e);
return;//鼠标位置在picturebox或其父对象之外
}
i_Ctrl=i_Ctrl.Parent;
}
while(i_Ctrl!=null&&i_Ctrl!=this);
//如果需要,这里有相对于pictureBox的鼠标位置
Point pt_mouseerl=pictureBox.PointToClient(pt_MouseAbs);
//你在这里工作吗
....
}

只需覆盖表单的鼠标滚轮,检查e.X和e.Y是否在PictureBox的位置区域内

  protected override void OnMouseWheel(MouseEventArgs e)
    {
        if (e.X >= soundGraph.Location.X && e.X <= soundGraph.Location.X + soundGraph.Width
            &&
            e.Y >= soundGraph.Location.Y && e.Y <= soundGraph.Location.Y + soundGraph.Height)
        { // do what you have to
        }
        base.OnMouseWheel(e);
    }
鼠标滚轮上的受保护覆盖无效(MouseEventArgs e) {
如果(e.X>=soundGraph.Location.X&&e.X=soundGraph.Location.Y&&e.Y,如果picturebox不在表单中的0,0位置,此功能也有效

' =====================================================================================
'  Windows10 has a new system setting 
'   named "Scroll inactive windows when I hover over them", turned on by default.
' -------------------------------------------------------------------------------------
'  The following correction does the same for Windows 8 / 7 / XP
' =====================================================================================
Protected Overrides Sub OnMouseWheel(ByVal e As MouseEventArgs)
    Dim p As Point
    p = pbox_Graph.PointToClient(Me.PointToScreen(e.Location))
    If pbox_Graph.ClientRectangle.Contains(p) Then
        pbox_TimeGraph_MouseWheel(Me, e)
    Else
        MyBase.OnMouseWheel(e)
    End If
End Sub

回答得很好。你真的帮了我所有的GUI需求。你不应该因为鼠标被移动而从用户那里拿走键盘焦点!这真是一个非常丑陋的解决方法。不要这样做!除此之外,它对我不起作用。即使我将焦点设置为pictureBox,我也不会得到wheel事件。我知道这个问题很老了。但Windows 10的情况已更改。在Windows 10中,鼠标悬停的所有控件都会接收鼠标滚轮事件。