当我用鼠标在这个控件上时,我想转发一条消息(例如 WM_MOUSEWHEEL),而不窃取焦点。这个问题可以很容易地解决,使用 IMessageFilter 拦截消息(将添加到应用程序消息泵中)并使用 P/Invoke(d) SendMessage() 转发它。问题是:我可以在不使用 P/Invoke 的情况下做同样的事情吗(我在 StackOverflow 中找到的解决方案使用 P/Invoke)?如果不是,为什么?
下面的代码是我使用 P/Invoke 的解决方案。我只用它new MessageForwarder(control, 0x20A)
。
/// <summary>
/// This class implements a filter for the Windows.Forms message pump allowing a
/// specific message to be forwarded to the Control specified in the constructor.
/// Adding and removing of the filter is done automatically.
/// </summary>
public class MessageForwarder : IMessageFilter
{
#region Fields
private Control _Control;
private Control _PreviousParent;
private HashSet<int> _Messages;
private bool _IsMouseOverControl;
#endregion // Fields
#region Constructors
public MessageForwarder(Control control, int message)
: this(control, new int[] { message }) { }
public MessageForwarder(Control control, IEnumerable<int> messages)
{
_Control = control;
_Messages = new HashSet<int>(messages);
_PreviousParent = control.Parent;
_IsMouseOverControl = false;
control.ParentChanged += new EventHandler(control_ParentChanged);
control.MouseEnter += new EventHandler(control_MouseEnter);
control.MouseLeave += new EventHandler(control_MouseLeave);
control.Leave += new EventHandler(control_Leave);
if (control.Parent != null)
Application.AddMessageFilter(this);
}
#endregion // Constructors
#region IMessageFilter members
public bool PreFilterMessage(ref Message m)
{
if (_Messages.Contains(m.Msg) && _Control.CanFocus && !_Control.Focused
&& _IsMouseOverControl)
{
SendMessage(_Control.Handle, m.Msg, m.WParam, m.LParam);
return true;
}
return false;
}
#endregion // IMessageFilter
#region Event handlers
void control_ParentChanged(object sender, EventArgs e)
{
if (_Control.Parent == null)
Application.RemoveMessageFilter(this);
else
{
if (_PreviousParent == null)
Application.AddMessageFilter(this);
}
_PreviousParent = _Control.Parent;
}
void control_MouseEnter(object sender, EventArgs e)
{
_IsMouseOverControl = true;
}
void control_MouseLeave(object sender, EventArgs e)
{
_IsMouseOverControl = false;
}
void control_Leave(object sender, EventArgs e)
{
_IsMouseOverControl = false;
}
#endregion // Event handlers
#region Support
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
#endregion // Support
}
编辑:我的答案中的完整解决方案