鼠标滚轮事件 (C#)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/479284/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 04:59:53  来源:igfitidea点击:

Mouse Wheel Event (C#)

c#winformsmousewheel

提问by

I can't get the Mouse Wheel event in the main form.

我无法在主窗体中获取鼠标滚轮事件。

As a demo I came up with a simple example:

作为演示,我想出了一个简单的例子:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        this.panel1.MouseWheel += new MouseEventHandler(panel1_MouseWheel);
        this.panel1.MouseMove += new MouseEventHandler(panel1_MouseWheel);

        Form2 f2 = new Form2();
        f2.Show(this);
    }

    private void panel1_MouseWheel(object sender, MouseEventArgs e)
    {
        if(e.Delta != 0)
        Console.Out.WriteLine(e.Delta);
    }
}

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();

        this.MouseMove += new MouseEventHandler(Form2_MouseMove);
        this.MouseWheel += new MouseEventHandler(Form2_MouseMove);
    }

    private void Form2_MouseMove(object sender, MouseEventArgs e)
    {
        if(e.Delta != 0)
            Console.Out.WriteLine(e.Delta);
    }
}

I get the mouse wheel event in Form2 but not Form1 any ideas?

我在 Form2 中获得了鼠标滚轮事件,但在 Form1 中没有获得任何想法?

Cheers,

干杯,

James

詹姆士

回答by

Maybe this will work for you?

也许这对你有用?

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
        Form2 f2 = new Form2();
        f2.MouseWheel += new MouseEventHandler(panel1_MouseWheel);
        f2.MouseMove += new MouseEventHandler(panel1_MouseWheel);
        f2.Show(this);
    }

    private void panel1_MouseWheel(object sender, MouseEventArgs e)
    {
        if(e.Delta != 0) Console.Out.WriteLine(e.Delta);
    }
}

回答by

I think you have slightly misunderstood my issue. On my main form with the below code I don'g get the MouseWheel event:

我想你有点误解了我的问题。在使用以下代码的主窗体上,我没有收到 MouseWheel 事件:

public Form1()
    {
        InitializeComponent();

        this.panel1.MouseWheel += new MouseEventHandler(panel1_MouseWheel);
        this.panel1.MouseMove += new MouseEventHandler(panel1_MouseWheel);    
    }

But I do get the event with:

但我确实得到了这个事件:

public Form1()
    {
        InitializeComponent();
        this.MouseWheel += new MouseEventHandler(panel1_MouseWheel);

    }

I hope that is clearer without the Form2 confusion. I am simply trying to get MouseWheel events on a Panel in my main form.

我希望在没有 Form2 混淆的情况下更清楚。我只是想在我的主窗体中的面板上获取 MouseWheel 事件。

Cheers,

干杯,

James

詹姆士

回答by Presidenten

Your problem arises from the fact that form1 has focus, not panel1. ...which ofcourse means that it is form1's events that will be fired, not panel1's events.

您的问题源于 form1 具有焦点,而不是 panel1。...这当然意味着将触发 form1 的事件,而不是 panel1 的事件。

I recreated your scenario with the following changes to the constructor in Form1 and verified that it fires the scroll wheel event.

我通过对 Form1 中的构造函数进行以下更改重新创建了您的场景,并验证它是否触发了滚轮事件。

public Form1()
{
        InitializeComponent(); 

        /*  --- Old code that don't work ---
            this.panel1.MouseWheel += new MouseEventHandler(panel1_MouseWheel);
            this.panel1.MouseMove += new MouseEventHandler(panel1_MouseWheel);
        */

        this.MouseWheel += new MouseEventHandler(panel1_MouseWheel);
        this.MouseMove += new MouseEventHandler(panel1_MouseWheel);

        Form2 f2 = new Form2();
        f2.Show(this);
    }
}

回答by Sam Meldrum

The Panel can't have the focus itself, only an item placed inside the panel can have the focus. The panel will only receive the MouseWheel event once something is placed inside it and that thing has the focus. Simply hoevering over the panel and moving the mouse wheel will send the event to the form, not to the panel.

面板本身不能拥有焦点,只有放置在面板内的项目才能拥有焦点。面板将仅在将某物放入其中并且该物具有焦点时才会接收 MouseWheel 事件。简单地悬停在面板上并移动鼠标滚轮会将事件发送到表单,而不是面板。

This is the difference between your two examples.

这是您的两个示例之间的区别。

回答by Sam Meldrum

Add another event of panel MouseEnterand in its Callback function get the input focus:

添加另一个面板事件MouseEnter并在其回调函数中获取输入焦点:

void MouseEnterEvent()
{
   this.Panel.Focus();
}

回答by nitrogenycs

I suspect the OP wants to get scroll events when just the mouse is hovering over the panel even though the panel does not have the focus.

我怀疑 OP 想要在鼠标悬停在面板上时获得滚动事件,即使面板没有焦点。

A way to accomplish this behaviour is explained here:

此处解释了一种完成此行为的方法:

http://social.msdn.microsoft.com/forums/en-US/winforms/thread/eb922ed2-1036-41ca-bd15-49daed7b637c/

http://social.msdn.microsoft.com/forums/en-US/winforms/thread/eb922ed2-1036-41ca-bd15-49daed7b637c/

and here:

和这里:

http://social.msdn.microsoft.com/forums/en-US/winforms/thread/6bfb9287-986d-4c60-bbcc-23486e239384/

http://social.msdn.microsoft.com/forums/en-US/winforms/thread/6bfb9287-986d-4c60-bbcc-23486e239384/

One of the code snippets taken from the linked forum:

来自链接论坛的代码片段之一:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsApplication1 {
  public partial class Form1 : Form, IMessageFilter {
    public Form1() {
      InitializeComponent();
      Application.AddMessageFilter(this);
    }

    public bool PreFilterMessage(ref Message m) {
      if (m.Msg == 0x20a) {
        // WM_MOUSEWHEEL, find the control at screen position m.LParam
        Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16);
        IntPtr hWnd = WindowFromPoint(pos);
        if (hWnd != IntPtr.Zero && hWnd != m.HWnd && Control.FromHandle(hWnd) != null) {
          SendMessage(hWnd, m.Msg, m.WParam, m.LParam);
          return true;
        }
      }
      return false;
    }

    // P/Invoke declarations
    [DllImport("user32.dll")]
    private static extern IntPtr WindowFromPoint(Point pt);
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
  }
}

This code will basically intercept all wm_mousewheel events and redirect them to the control the mouse is currently hovering over. The panel doesn't need to have the focus anymore to receive the wheel events.

此代码将基本上拦截所有 wm_mousewheel 事件并将它们重定向到鼠标当前悬停的控件。面板不再需要焦点来接收滚轮事件。

回答by STremblay

Thanks to @nitrogenycs 's answer, I've wrote a simple generic class to easily address the issue:

感谢@nitrogenycs 的回答,我编写了一个简单的通用类来轻松解决这个问题:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing;

namespace MyNamespace
{
  public class MouseWheelManagedForm : Form, IMessageFilter
  {
    private bool managed;

    public MouseWheelManagedForm () : this (true) {
   }

    public MouseWheelManagedForm (bool start) {
      managed = false;
      if (start)
        ManagedMouseWheelStart();
    }

    protected override void Dispose (bool disposing) {
      if (disposing)
        ManagedMouseWheelStop();
      base.Dispose(disposing);
    }

    /************************************
     * IMessageFilter implementation
     * *********************************/
    private const int WM_MOUSEWHEEL = 0x20a;
    // P/Invoke declarations
    [DllImport("user32.dll")]
    private static extern IntPtr WindowFromPoint (Point pt);
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage (IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);

    private bool IsChild (Control ctrl) {
      Control loopCtrl = ctrl;

      while (loopCtrl != null && loopCtrl != this)
        loopCtrl = loopCtrl.Parent;

      return (loopCtrl == this);
    }

    public bool PreFilterMessage (ref Message m) {
      if (m.Msg == WM_MOUSEWHEEL) {
        //Ensure the message was sent to a child of the current form
        if (IsChild(Control.FromHandle(m.HWnd))) {
          // Find the control at screen position m.LParam
          Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16);

          //Ensure control under the mouse is valid and is not the target control
          //otherwise we'd be trap in a loop.
          IntPtr hWnd = WindowFromPoint(pos);
          if (hWnd != IntPtr.Zero && hWnd != m.HWnd && Control.FromHandle(hWnd) != null) {
            SendMessage(hWnd, m.Msg, m.WParam, m.LParam);
            return true;
          }
        }
      }
      return false;
    }

    /****************************************
     * MouseWheelManagedForm specific methods
     * **************************************/
    public void ManagedMouseWheelStart () {
      if (!managed) {
        managed = true;
        Application.AddMessageFilter(this);
      }
    }

    public void ManagedMouseWheelStop () {
      if (managed) {
        managed = false;
        Application.RemoveMessageFilter(this);
      }
    }

  }
}

From there, you only need to inherit your Form from this class instead of Form for every form you need the MouseWheel to be "managed":

从那里,您只需要从此类继承您的 Form 而不是 Form ,您需要“管理” MouseWheel 的每个表单:

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Windows.Forms;

namespace MyApp
{
  public partial class MyForm : MyNamespace.MouseWheelManagedForm
  {
    public MyForm ()
    {
      InitializeComponent();
    }

  }
}

Hope this will help someone else (than me).

希望这会帮助其他人(除了我)。

回答by ertugrul

this.MouseWheel += pictureBox1_MouseWheel; //tan?mlama
void pictureBox1_MouseWheel(object sender, MouseEventArgs e)
            {
                if (Convert.ToString(e.Delta) == "120")
                {
                    //yukar?
                }
                else if (Convert.ToString(e.Delta) == "-120")
                {
                    //a?a??
                }
            }