当我用鼠标控制此控件时,我想转发一条消息(例如WM_MOUSEWHEEL),而不会窃取焦点.使用IMessageFilter(要添加到应用程序消息泵)并使用P / Invoke(d)SendMessage()转发消息,可以轻松解决此问题.问题是:我可以不使用P / Invoke做同样的事情(我在StackOverflow中找到的解决方案使用P / Invoke)吗?如果没有,为什么?
下面的代码是我用P / Invoke的解决方案.我只使用新的MessageForwarder(控件,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
}
编辑:我的答案完全解决方案
解决方法
找到一个方法:你必须继承NativeWindow,在你以任何你喜欢的方式拦截一个消息之后,将所选控件的句柄分配给它,调用受保护的WndProc(在我的例子中,继承的类甚至是一个IMessageFilter所以我可以轻松将其插入应用程序).我使用它与新的MessageForwarder(anycontrol,0x20A)重定向鼠标滚轮.
因此,可以在没有p / invoke的情况下拦截和转发消息到任何控件.虽然这很隐蔽.
/// <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 : NativeWindow,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; AssignHandle(control.Handle); _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) { m.HWnd = _Control.Handle; WndProc(ref m); 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 }