C# 扩展回调函数?
通过阅读GeorgeMamaladze c#“全局鼠标键钩子”源代码,我试图了解一些代码是如何工作的。这是“科拉松”号C# 扩展回调函数?,c#,lambda,keyboard-hook,C#,Lambda,Keyboard Hook,通过阅读GeorgeMamaladze c#“全局鼠标键钩子”源代码,我试图了解一些代码是如何工作的。这是“科拉松”号 public delegate IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam); private static Handle HookGlobal(int hookId, Callback callback) { HookProcedure hookProc = (code, param, l
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是应用程序定义或库定义函数名的占位符。(有几个占位符过程回调…)
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);
}
他们应该实现同样的目标。乔治用这些扭曲的东西干什么?一个解释可能有助于缓解我的头晕或呼吸急促
hookProc委托实例是否在George的代码中保留对lambda的引用,从而保留对MyProc方法的引用
不,如果不是这样,
hookProc
可能有资格进行垃圾收集,只要函数退出并且您的钩子不再工作,您需要像Stepen的代码中那样保留对委托的引用,以阻止它发生。George Mamaladze的解决方案看起来不可靠,他如何确保hookProc不会被GC'ed?仅出于这个原因,我更相信Stephen Toub的代码。@Lukazoid现在我确实说了“一般”关于代码**但快速浏览mamaladze代码并不能揭示那种机制,这是lambda的使用我不知道这是一个合理的问题,标题很差,我建议你编辑一下,我看到了内存流失。其他人看到了吗?静态回调不会做同样的事情吗?我正在使用类似stephen的简洁代码,但我也想在hook回调函数参数中公开一个外部回调,如george@code4life不,事实上,我自己也遇到过。如果您确实执行了SetWindowsHookEx(hookId,MyProc,…
),则实际编译为SetWindowsHookEx(hookId,new HookProcedure(MyProc)),…
并且一旦SetWindowsHookEx返回,该隐藏委托可以被垃圾收集。如果SetWindowsHookEx尝试使用回调,则会出现CallbackOnCollectedDelegate
错误。有关更多详细信息,请参阅同一API调用。@JediCommymullah您可以做的是拥有一个静态字典
,其中包含callbacks in.当用户想要取消订阅时,你可以从字典中删除回调。@ScottChamberlain:啊,谢谢你提供的信息,很有意义!
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);
}