Mouse Wheel Event (C#)

六月ゝ 毕业季﹏ 提交于 2019-11-26 16:08:42

问题


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?

Cheers,

James


回答1:


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.

A way to accomplish this behaviour is explained here:

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/

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.




回答2:


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.

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

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);
    }
}



回答3:


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

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



回答4:


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

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":

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).




回答5:


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);
    }
}



回答6:


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.

This is the difference between your two examples.




回答7:


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

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.

Cheers,

James




回答8:


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ğı
                }
            }


来源:https://stackoverflow.com/questions/479284/mouse-wheel-event-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!