28

メインフォームでマウスホイールイベントを取得できません。

デモとして、私は簡単な例を思いつきました:

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

Form2でマウスホイールイベントを取得しますが、Form1では取得できません。

乾杯、

ジェームズ

4

7 に答える 7

41

パネルにフォーカスがないにもかかわらず、マウスだけがパネルの上に置かれているときに、OPがスクロールイベントを取得したいと考えています。

この動作を実現する方法は、次のとおりです。

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/6bfb9287-986d-4c60-bbcc-23486e239384/

リンクされたフォーラムから取得したコード スニペットの 1 つ:

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

このコードは、基本的にすべての wm_mousewheel イベントをインターセプトし、マウスが現在ホバリングしているコントロールにリダイレクトします。パネルは、ホイール イベントを受け取るためにフォーカスを持つ必要がなくなりました。

于 2012-04-04T07:42:30.597 に答える
18

あなたの問題は、form1がpanel1ではなくフォーカスを持っているという事実から生じます。...もちろん、これは、panel1のイベントではなく、form1のイベントが発生することを意味します。

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);
    }
}
于 2009-01-26T10:31:42.047 に答える
4

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

  }
}

そこから、MouseWheel を「管理」する必要があるすべてのフォームの Form ではなく、このクラスから Form を継承するだけで済みます。

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

  }
}

これが(私以外の)誰かを助けることを願っています。

于 2014-06-05T18:09:39.843 に答える
0

多分これはあなたのために働くでしょうか?

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);
    }
}
于 2009-01-26T10:13:45.843 に答える
0

パネル自体にフォーカスを設定することはできません。パネル内に配置されたアイテムのみにフォーカスを設定できます。パネルは、何かがパネル内に配置され、その物にフォーカスがある場合にのみ、MouseWheelイベントを受け取ります。パネルにカーソルを合わせてマウスホイールを動かすだけで、イベントはパネルではなくフォームに送信されます。

これが2つの例の違いです。

于 2009-01-26T10:31:56.930 に答える