扩展回调函数?

时间:2015-10-14 23:26:43

标签: c# lambda keyboard-hook

阅读George Mamaladze c#“全局鼠标键钩”源代码我试图弄清楚一些代码是如何工作的。这里通常是“corazon”

public delegate IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam);

private static Handle HookGlobal(int hookId, Callback callback)
{
    HookProcedure hookProc = (code, param, lParam) => MyProc(code, param, lParam, callback);

    Handle handle = SetWindowsHookEx(
            hookId,
            hookProc,
            Process.GetCurrentProcess().MainModule.BaseAddress,
            0);
    return handle;
}

private static IntPtr MyProc(int nCode, IntPtr wParam, IntPtr lParam, Callback callback)
{            
    var callbackData = new CallbackData(wParam, lParam);
    bool continueProcessing = callback(callbackData);
    if (!continueProcessing) 
    { return new IntPtr(-1); }
    return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);
}

WinApi函数SetWindowsHookEx设置的消息泵将使用消息数据调用MyProc方法。

HHOOK WINAPI SetWindowsHookEx(
  _In_ int       idHook,
  _In_ HOOKPROC  lpfn,
  _In_ HINSTANCE hMod,
  _In_ DWORD     dwThreadId
);
  

根据MSDN,HOOKPROC类型定义了一个指向回调函数的指针。 (示例...)MouseProc是应用程序定义或库定义的函数名称的占位符。 (有几个占位符过程回调...)

LRESULT CALLBACK MouseProc(
    _In_ int    code,
         WPARAM wParam,
    _In_ LPARAM lParam
);

hookProc委托实例是否保留对lambda的引用,从而引用George代码中的MyProc方法?
这是Stephen Taub的MSDN博客中更简单的方法

private delegate IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam);
private static HookProcedure procedure = Callback;
private static IntPtr _hookID = IntPtr.Zero;        

public static void SetHook()
{
    _hookID = SetWindowsHookEx(
        WH_KEYBOARD_LL,
        procedure,
        Process.GetCurrentProcess().MainModule,
        0);        
}

private static IntPtr Callback(int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0)
    {
    }
    return CallNextHookEx(_hookId, nCode, wParam, lParam);
}

他们应该达到同样的目的。乔治对这种扭曲的东西有什么看法?解释可能有助于我的头晕或呼吸急促。

1 个答案:

答案 0 :(得分:2)

  

hookProc委托实例是否保持对lambda的引用,从而引用George代码中的MyProc方法?

不,它没有,hookProc可能有资格进行垃圾收集,一旦函数退出并且你的钩子将不再起作用,你需要像Stepen的代码那样保持对委托的引用以阻止它发生。