【问题标题】:Intercept mouse click from other program拦截来自其他程序的鼠标点击
【发布时间】:2013-03-24 09:57:40
【问题描述】:

我正在尝试拦截来自另一个程序的鼠标点击。我正在为程序制作一个插件,它在程序上覆盖一个透明的表单并显示附加信息。当我点击表单的透明部分时,我可以点击main 程序中的内容。我不希望这种情况发生(至少不是每次都 - 有些部分允许您点击,有些部分不允许点击,但这不是问题)

我现在这样做的方式是使用WH_MOUSE_LL,这工作正常,我可以通过返回一个非零值(http://msdn.microsoft.com/en-gb/library/windows/desktop/ms644988(v=vs.85).aspx)来阻止鼠标点击进入程序。

问题是,这使我的主程序滞后,我不需要收到所有鼠标移动的通知,我只想在用户实际点击某些东西时收到通知。有什么办法可以限制WH_MOUSE_LL,让它只在鼠标点击时触发? (延迟不是因为 MouseHookProc 方法中的计算 - 它目前除了调用:CallNextHookEx(hHook, nCode, wParam, lParam) 之外什么都不做。)

我尝试通过使用挂钩 WM_MOUSEACTIVATE 消息的全局挂钩 (http://www.codeproject.com/Articles/18638/Using-Window-Messages-to-Implement-Global-System-H) 来解决此问题。这个想法是在我收到WM_MOUSEACTIVATE 通知时才连接WH_MOUSE_LL。不幸的是,WH_MOUSE_LL 点击通知在WM_MOUSEACTIVATE 之前发送,所以这不起作用。

编辑:

@Nanda 这是过程代码:

public int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
    return WindowUtility.CallNextHookEx(hHook, nCode, wParam, lParam);
}

正如你所看到的,我在 atm 上做的并不多,但它已经滞后了......

@Cody Gray 我为处理消息的表单做了一个非常小的测试:

public class Form1 : Form
{
    private TrackBar m_Trackbar;

    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    public Form1()
    {
        m_Trackbar = new System.Windows.Forms.TrackBar();
        m_Trackbar.LargeChange = 1;
        m_Trackbar.Location = new System.Drawing.Point(5, 10);
        m_Trackbar.Maximum = 100;
        m_Trackbar.Size = new System.Drawing.Size(280, 40);
        m_Trackbar.Value = 100;
        this.Controls.Add(m_Trackbar);

        m_Trackbar.Scroll += new System.EventHandler(this.m_TrackbarScroll);
    }


    private void m_TrackbarScroll(object sender, System.EventArgs e)
    {
        this.Opacity = ((Convert.ToDouble(m_Trackbar.Value)) / 100);
    }

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case 0x201: //WM_LBUTTONDOWN
                Console.WriteLine("MouseButton Down!");
                //I could copy the Message over to the MainProgram with this right?
                //SendMessage(MainProgramHwnd, m.Msg, m.WParam, m.LParam);
                //This will also only work on an opacity higher than 0.
                break;
        }
        base.WndProc(ref m);
    }
}

当你说:“返回它是透明的,让它路由到它下面的窗口?”我可以通过使用 SendMessage 并基本上复制我在 WndProc 方法中收到的消息来做到这一点吗?

为了让事情变得更复杂,我也在使用这个表单http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C。据我了解,这使我能够在表单上绘制具有抗锯齿背景的位图。使用这种形式似乎无法设置不透明度,因为它一直都是透明的。有没有更好的方法在 Form 上绘制位图?

【问题讨论】:

  • 可能是您的钩子 proc 执行了太多操作,甚至在检查事件类型并退出无关事件之前。将您的钩子 proc 仅返回 CallNextHook(...) 并添加进行增量更改。
  • 为什么你的覆盖表单不能只接收发生在它身上的所有鼠标事件并适当地过滤它们?如果它应该处理一个,处理它。如果不是,返回它是透明的并让它路由到它下面的窗口?全局挂钩几乎总是错误的解决方案(尽管如果你必须使用的话,nanda 的建议是一个很好的解决方案)。
  • 感谢两位 cmets,我已经用一些代码和一些附加信息编辑了我的第一个问题。 @Nanda 我不太确定你的意思,我目前只返回 CallNextHookEx 但这已经滞后(我已将我的 proc 代码添加到我的第一篇文章中)。
  • @Cody Gray 如果我的表单不透明度为 1%,这难道不可行吗?因为当我的表单的不透明度为 0% 时,它不能再接收任何鼠标消息。我还在第一篇文章中添加了一些测试代码。
  • 我不知道你的 HookProc 已经是我建议的。我能想到滞后的几个可能原因 - 因为您的钩子 proc 在 .NET 中,可能会出现互操作开销,并且透明窗口(似乎您正在使用它们)最终可能导致嵌套的 WM_NCHITTEST 消息并强调开销。

标签: c# .net winapi hook windows-messages


【解决方案1】:

您可能需要研究 Easyhook (http://easyhook.codeplex.com/),它允许您从单个进程而不是所有进程挂钩 Windows API 调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    • 2022-01-09
    相关资源
    最近更新 更多