加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何在不窃取焦点和没有P / Invoke的情况下将消息(例如鼠

发布时间:2020-12-15 04:18:02 所属栏目:百科 来源:网络整理
导读:当我用鼠标控制此控件时,我想转发一条消息(例如WM_MOUSEWHEEL),而不会窃取焦点.使用IMessageFilter(要添加到应用程序消息泵)并使用P / Invoke(d)SendMessage()转发消息,可以轻松解决此问题.问题是:我可以不使用P / Invoke做同样的事情(我在StackOverflow中
当我用鼠标控制此控件时,我想转发一条消息(例如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
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读