在我的C#3.5的Windows窗体应用程序,我有几个SplitContainers。 有每个(码头填充)内的列表控件。 当焦点在这些控件之一,我移动鼠标滚轮,列表中,这是现在的重点,滚动。
我的任务是滚动列表,目前由鼠标,而不是该选择一个徘徊。 是否有可能在Windows窗体? 如果没有,是否有可能与PInvoke的?
在我的C#3.5的Windows窗体应用程序,我有几个SplitContainers。 有每个(码头填充)内的列表控件。 当焦点在这些控件之一,我移动鼠标滚轮,列表中,这是现在的重点,滚动。
我的任务是滚动列表,目前由鼠标,而不是该选择一个徘徊。 是否有可能在Windows窗体? 如果没有,是否有可能与PInvoke的?
它看起来像您可以使用IMessageFilter
和PInvoke的处理这个问题。 在VB中的一个例子,可以发现重定向鼠标滚轮事件到没有重点的Windows窗体控件 。 你应该能够很容易地将此转换为C#。
兴趣点
这个类使用给定的任务以下技术:
使用一个VB.NET到C#转换器 ,这是你到底是什么了:
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);
}
我有类似的问题,发现这个线程...所以我发布迟来的答案为别人谁可能会发现这个线程。 就我而言,我只是想鼠标滚轮事件去到任何控制光标下...就像右键单击它(这将是令人困惑的,如果右击去聚焦控制,而不是光标下的控制......我认为这同样适用于鼠标滚轮正确的,除了我们已经习惯了它)。
无论如何,答案是超级容易。 只是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;
}
}
使用Control.MouseEnter事件将焦点设置到该控件。 例如,使用ActiveControl属性
这是布赖恩·肯尼迪的回答与汉克·舒尔茨评论完成:
首先,你应该做一个类实现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);
}
}