簡體   English   中英

檢測按鈕上的鼠標滾輪

[英]Detect Mouse Wheel on a button

我有以下控制層次結構

    Form
        TabControl
            Panel
                Button

我正在嘗試檢測按鈕上的鼠標滾輪事件。 我知道要讓控件捕獲鼠標滾輪事件,它必須處於焦點狀態,而我的按鈕當前未處於焦點位置?

我首先將滾輪事件附加到面板,然后附加到按鈕,但是在這兩種情況下它都不會檢測到該事件,可能是因為它不在焦點上。

現在我已將偶數附加到表單上,並且表單檢測到輪事件

this.MouseWheel +=Form1_MouseWheel;

然后我嘗試使用以下代碼檢測鼠標下的孩子

private void Form1_MouseWheel(object sender, MouseEventArgs e) {
        if (e.Delta > 0) {
            Debug.WriteLine("SCROLL UP..." + e.Delta);
        } else {
            Debug.WriteLine("SCROLL DOWN..." + e.Delta);
        }

        Control ctrl = this.GetChildAtPoint(e.Location);

        if (ctrl != null) {
            Debug.WriteLine("Wheeling Over " + ctrl.Name);
        }
}

但是,代碼僅打印tabControl1

有沒有一種方法可以讓孩子更深入層次結構,並在鼠標滾輪處於活動狀態時獲得當前位於鼠標下方的正確Control

Button 必須是 Active Control 才能引發MouseWheel事件。
Control.GetChildAtPoint返回 Control 的直接子級,從中調用方法,包含 Mouse position(這也可能取決於使用的系統版本)。

如果可以 PInvoke,則可以使用WindowFromPoint檢測當前位於鼠標指針 position 下的 Control。 考慮您可以在文檔中找到的注釋:

返回值是包含該點的 window 的句柄。 如果給定點不存在 window,則返回值為 NULL。 如果該點位於 static 文本控件上方,則返回值是 static 文本控件下的 window 的句柄。

▲ 不適用於 WinForms 標簽,這些確實返回一個句柄。

注意: WindowFromPoint不會返回所有控件的句柄:

  • function 不返回不可見或禁用的控件句柄。

  • 如果可以滾動的控件(TextBoxes、RichTextBoxes)具有捕獲(控件處於活動狀態並包含插入符號),您將不會收到 MouseWheel 事件,因為這些事件是由控件接收的,而不是由窗體接收的。

  • 某些控件無法返回句柄:ComboBox 的 TextBox 與DropDownStyle = DropDown和 ToolStripProgressBar(例如)。

您可能還想看看ChildWindowFromPointExRealChildWindowFromPoint


[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr WindowFromPoint(Point point);

internal const int WM_MOUSEMOVE = 0x0200;
internal const int WM_MOUSEWHEEL = 0x020A;
internal const int WM_MOUSEHWHEEL = 0x020E;
internal const int WM_MOUSEHOVER = 0x02A1

使用返回的句柄WindowFromPoint覆蓋表單的WndProc並使用Control.FromFandle()獲取鼠標指針下的控件。
鼠標指針的當前屏幕 position 由MousePositionCursor.Position返回(兩者都返回與位置相關的相同值)。

我還添加了WM_MOUSEHWHEEL以及WM_MOUSEMOVEWM_MOUSEHOVER ,注釋掉了:您可能需要它們。

[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    switch (m.Msg) {
        case WM_MOUSEWHEEL:
        case WM_MOUSEHWHEEL:
            Point pos = MousePosition;
            Console.WriteLine($"Position: {pos}");
            Console.WriteLine($"Delta: {(short)(m.WParam.ToInt32() >> 16)}");
            Console.WriteLine($"Mouse Button: {(short)m.WParam.ToInt32()}");

            IntPtr hWnd = WindowFromPoint(pos);
            if (hWnd != IntPtr.Zero) {
                var control = Control.FromHandle(hWnd);
                Console.WriteLine($"Handle: {hWnd}");
                Console.WriteLine($"Control Name: " + control?.Name);
            }
            m.Result = IntPtr.Zero;
            break;
        //case WM_MOUSEMOVE:
        //    //Console.WriteLine($"{Control.ModifierKeys}");
        //    m.Result = IntPtr.Zero;
        //    break;
        //case WM_MOUSEHOVER:
        //    //Console.WriteLine($"{Control.ModifierKeys}");
        //    m.Result = IntPtr.Zero;
        //    break;
}

您是否確保將 MouseEventHandler 附加到按鈕? 我嘗試了以下代碼,它按預期工作。 (此代碼包括所描述的 Form > TabControl > Panel > Button。)

    public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        button1.MouseWheel += new MouseEventHandler(Button1_MouseWheel);
    }

    public void Button1_MouseWheel(object sender, MouseEventArgs e)
    {
        Debug.WriteLine("ButtonWheel");
        MessageBox.Show("ButtonWheel");
    }
}

表單布局截圖

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM