I want to forward a message (e.g. WM_MOUSEWHEEL) when I am over this control with the mouse, without stealing focus. This problem can be easily solved by intercepting a message using IMessageFilter (which will be added to the application message pump) and forwarding it using P / Invoke (d) SendMessage (). The question is: can I do the same without using P / Invoke (the solutions I found in StackOverflow use P / Invoke)? If not, why?
Below is my solution with P / Invoke. I use it only with 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
}
EDIT : complete solution in my answer
source share