【发布时间】:2014-07-08 23:50:50
【问题描述】:
我有一个在生产中使用的 KeyboardHook。效果很好。昨天我想做一个单元测试来测试我的想法,我创建一个抽象类,该类具有与 HOOKPROC 委托匹配的虚拟方法。像这样..
public abstract class HookRuleBase : IDisposable
{
private readonly IntPtr hookId;
private static KeyboardProc thisDelegate;
public HookRuleBase()
{
thisDelegate = new KeyboardProc(ProcessKey);
IntPtr user = Kernel32.LoadLibrary("User32.dll");
hookId = User32.SetWindowsHookEx(WH_KEYBOARD_LL, thisDelegate, user, 0);
Console.WriteLine(hookId.ToInt32().ToString("X8"));
}
public void Dispose()
{
var disposed = User32.UnhookWindowsHookEx(hookId);
}
/// <summary>
/// If your rule does not need to handle the key or the key's current state then call this base
/// method.
/// </summary>
public virtual int ProcessKey(int code, System.UIntPtr wParam, ref KeyboardHookStruct lParam)
{
return User32.CallNextHookEx(hookId, code, wParam, ref lParam);
}
private const int WH_KEYBOARD_LL = 13;
}
我打算用它来替换我在课堂上的一些名为 KeyboardHook 的静态方法。我认为它遵循策略模式……我认为……任何人。所以我做了一个 NUnit 项目。做了一个非常简单的类来扩展我的 HookRuleBase
private class HookRuleTest : HookRuleBase
{
public override int ProcessKey(int code, UIntPtr wParam, ref KeyboardHookStruct lParam)
{
Console.WriteLine("ProcessKey:code:{0}, wParam:{1:X8}, {2}", code, wParam.ToUInt32(), lParam.ToString());
return base.ProcessKey(code, wParam, ref lParam);
}
}
我在测试中尝试了一些东西。首先我做了一个控制台哔声(我自己的一个音频队列。)然后做了一个线程睡眠 3 秒......什么都没有出现。所以我偷了一些我的代码来测试我的虚拟键盘类。它只不过是在另一个线程中启动的 Winforms 表单。所以我放入了创建所述钩子规则的加载事件,并在关闭时处理了它。运行我的测试输入 hello world 并且在控制台中没有任何内容:/ 所以作为最后的手段,我创建了一个新的 winforms 项目。复制了加载和关闭事件的代码,将项目更改为控制台项目,然后运行我的代码。开始打字,果然我开始将输出输出到我的控制台窗口。所以这让我发疯。我不知道它为什么这样做。该代码有效,但在 Nunit 中无效。有人可以指导我正确的方向,为什么它不起作用。它的作用就像钩子正在接收任何事件,但 SetWindowsHookEx 每次都返回一个有效指针。所以我不知道。请帮忙。
【问题讨论】:
标签: c# winforms nunit keyboard-hook