在我的C#3.5 Windows窗體應用程序中,我有幾個SplitContainers。每個(碼頭填充)都有一個列表控件。當焦點在這些控件之一,我移動鼠標滾輪,列表中,這是現在的重點,滾動。鼠標滾輪事件與懸停控件一起工作
我的任務是滾動列表,這是當前鼠標懸停,而不是被選中的。在Windows窗體中可能嗎?如果沒有,是否可以使用PInvoke?
在我的C#3.5 Windows窗體應用程序中,我有幾個SplitContainers。每個(碼頭填充)都有一個列表控件。當焦點在這些控件之一,我移動鼠標滾輪,列表中,這是現在的重點,滾動。鼠標滾輪事件與懸停控件一起工作
我的任務是滾動列表,這是當前鼠標懸停,而不是被選中的。在Windows窗體中可能嗎?如果沒有,是否可以使用PInvoke?
它看起來像你可以使用IMessageFilter
和PInvoke來處理這個。在VB的例子可以在Redirect Mouse Wheel Events to Unfocused Windows Forms Controls找到。你應該能夠輕鬆地將其轉換爲C#。
興趣點
的這個類使用給定的任務以下技術:
使用a VB.NET to C# converter,這是你到底是什麼了:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public class MouseWheelRedirector : IMessageFilter
{
private static MouseWheelRedirector instance = null;
private static bool _active = false;
public static bool Active
{
get { return _active; }
set
{
if (_active != value)
{
_active = value;
if (_active)
{
if (instance == null)
{
instance = new MouseWheelRedirector();
}
Application.AddMessageFilter(instance);
}
else
{
if (instance != null)
{
Application.RemoveMessageFilter(instance);
}
}
}
}
}
public static void Attach(Control control)
{
if (!_active)
Active = true;
control.MouseEnter += instance.ControlMouseEnter;
control.MouseLeave += instance.ControlMouseLeaveOrDisposed;
control.Disposed += instance.ControlMouseLeaveOrDisposed;
}
public static void Detach(Control control)
{
if (instance == null)
return;
control.MouseEnter -= instance.ControlMouseEnter;
control.MouseLeave -= instance.ControlMouseLeaveOrDisposed;
control.Disposed -= instance.ControlMouseLeaveOrDisposed;
if (object.ReferenceEquals(instance.currentControl, control))
instance.currentControl = null;
}
private MouseWheelRedirector()
{
}
private Control currentControl;
private void ControlMouseEnter(object sender, System.EventArgs e)
{
var control = (Control)sender;
if (!control.Focused)
{
currentControl = control;
}
else
{
currentControl = null;
}
}
private void ControlMouseLeaveOrDisposed(object sender, System.EventArgs e)
{
if (object.ReferenceEquals(currentControl, sender))
{
currentControl = null;
}
}
private const int WM_MOUSEWHEEL = 0x20a;
public bool PreFilterMessage(ref System.Windows.Forms.Message m)
{
if (currentControl != null && m.Msg == WM_MOUSEWHEEL)
{
SendMessage(currentControl.Handle, m.Msg, m.WParam, m.LParam);
return true;
}
else
{
return false;
}
}
[DllImport("user32.dll", SetLastError = false)]
private static extern IntPtr SendMessage(
IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
}
使用Control.MouseEnter Event將焦點設置爲控件。例如。使用ActiveControl Property
有時,如果沒有**對焦,可以方便地滾動控件**,例如,如果它將焦點從文本字段中移開。 – Nyerguds
我有類似的問題,發現這個線程...所以我發佈遲來的答案爲別人誰可能會發現這個線程。在我的情況下,我只想讓鼠標滾輪事件進入光標下的任何控件......就像右鍵單擊一樣(如果右鍵單擊到焦點控件而不是光標下的控件,將會令人困惑......我認爲這同樣適用於鼠標滾輪正確的,除了我們已經習慣了它)。
無論如何,答案是非常容易的。只是PreFilterMessage添加到您的應用程序,並把它重定向鼠標滾輪事件鼠標下的控制:
public bool PreFilterMessage(ref Message m)
{
switch (m.Msg)
{
case WM_MOUSEWHEEL: // 0x020A
case WM_MOUSEHWHEEL: // 0x020E
IntPtr hControlUnderMouse = WindowFromPoint(new Point((int)m.LParam));
if (hControlUnderMouse == m.HWnd)
return false; // already headed for the right control
else
{
// redirect the message to the control under the mouse
SendMessage(hControlUnderMouse, m.Msg, m.WParam, m.LParam);
return true;
}
default:
return false;
}
}
這裏有一點遺漏。您需要DllImport WindowFromPoint()和SendMessage: '[DllImport(「user32.dll」)] static extern IntPtr WindowFromPoint(Point p); [DllImport(「user32.dll」,CharSet = CharSet.Auto)] static extern IntPtr SendMessage(IntPtr hWnd,UInt32 Msg,IntPtr wParam,IntPtr lParam);' 另外,PreFilterMessage()來自IMessageFilter,並且該實現需要傳遞給ApplicationAddMessageFilter()。 一旦完成,我的應用程序中的所有面板都可以在鼠標下滾動。但是,雙擊不再突出顯示文字。奇。 –
這是布賴恩·肯尼迪的回答與漢克·舒爾茨評論完成:
第一你應該做一個類實現IMessageFilter:
public class MessageFilter : IMessageFilter
{
private const int WM_MOUSEWHEEL = 0x020A;
private const int WM_MOUSEHWHEEL = 0x020E;
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(Point p);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
public bool PreFilterMessage(ref Message m)
{
switch (m.Msg)
{
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
IntPtr hControlUnderMouse = WindowFromPoint(new Point((int)m.LParam));
if (hControlUnderMouse == m.HWnd)
{
//Do nothing because it's already headed for the right control
return false;
}
else
{
//Send the scroll message to the control under the mouse
uint u = Convert.ToUInt32(m.Msg);
SendMessage(hControlUnderMouse, u, m.WParam, m.LParam);
return true;
}
default:
return false;
}
}
}
實例:
public partial class MyForm : Form
{
MessageFilter mf = null;
private void MyForm_Load(object sender, EventArgs e)
{
mf= new MessageFilter();
Application.AddMessageFilter(mf);
}
private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
Application.RemoveMessageFilter(mf);
}
}
看起來他們在Windows 10的標準行爲中「滾動鼠標光標所在的位置」。實際上,在大多數情況下,這是一種煩人的行爲。 – Nyerguds