2

この記事のコードを使用しています:

private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;

public static void Main()
{
    _hookID = SetHook(_proc);
    //Application.Run();
    //UnhookWindowsHookEx(_hookID);
}

private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
    using (Process curProcess = Process.GetCurrentProcess())
    using (ProcessModule curModule = curProcess.MainModule)
    {
        return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
            GetModuleHandle(curModule.ModuleName), 0);
    }
}

private delegate IntPtr LowLevelKeyboardProc(
    int nCode, IntPtr wParam, IntPtr lParam);

private static IntPtr HookCallback(
    int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
    {
        int vkCode = Marshal.ReadInt32(lParam);
        ***custom code***
    }
    return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
    LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
    IntPtr wParam, IntPtr lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);

少し変更しますが、キーストロークを数回押すのが速すぎると、コンピューターが少し「遅く」なり、「ラグ」が発生することがあります。

そのため、イベント HookCallback が非同期にヒットすると、少しラグが発生することがありますが、このメソッド「HookCallback」のコードがラグを発生させているのでしょうか、それともそれ自体をフックしているのでしょうか? "HookCallback" を入力するたびに新しいスレッドを作成するという考えがありましたが、それは役立つかもしれませんが、キーを押すたびに新しいスレッドを開始したいですか? 私はすでに非同期呼び出しを取得しているので、それ以外に別のスレッドを開始する必要があるかどうかわかりません。

私の質問は簡単です。どこで、なぜコンピューターの速度が低下するのですか? または、カスタム コードを別のスレッドに配置する必要がありますか?

そして、別の質問があります。いくつかのキーを押した後、イベントを「フック解除」したかのように「HookCallback」が呼び出されず、キーストロークがまったくキャプチャされないことがあります。手動で行わない限り、イベントをフック解除しないようにするにはどうすればよいですか?

ありがとうございました。

4

4 に答える 4

2

私はかなりの時間をキーボードフックに費やしてきたので、以下は私自身の経験です。フックは効率的である必要があります。私は数年前に、キーストロークをキャプチャする必要のある小さなPOSアプリを作成しました。これはC#で記述されており、入力が目立つようになるまで遅くなりました。多くの頭痛の種の後で、私はついに大きな遅れがネイティブコードからマネージコードへの変換から来ていることに気づきました。私はC++(ネイティブ)でフックコードの小さな部分を書き直し、「十分に良い」と思う改善を見ました。

速度は、コードの処理にかかる時間によって完全に決定されることを覚えておいてください。それを効率的にするために最善を尽くしてください。

于 2011-07-31T19:00:45.767 に答える
0

「フック解除」の問題には別の要因があります。低レベルのグローバル フック コードが一定時間内に終了できない場合、OS はユーザーに通知せずにフックを自動的に削除します。したがって、コードをできるだけ速く実行してください

乾杯

于 2011-09-25T04:05:18.057 に答える
-1

アプリケーション内でのみキーストロークをキャプチャしたい場合は、処理が速くなります。WH_KEYBOARDの代わりに使用するとWH_KEYBOARD_LL、パフォーマンスが大幅に向上します。

private const int WH_KEYBOARD = 2;
于 2011-07-31T19:13:16.180 に答える
-1

同じ症状がありましたが、問題は Thread.Sleep(); が原因であることが判明しました。最近、アプリケーションをコンソールから Windows アプリケーションに変更しました。私のコードは次のとおりです。

static void Main( string[] args )
{
    hook_keys();
    AppDomain.CurrentDomain.ProcessExit += CurrentDomainOnProcessExit;
    while (true) { System.Threading.Thread.Sleep( new TimeSpan(0,10,0) ); }
}
private static void CurrentDomainOnProcessExit(object sender, EventArgs eventArgs )
{
    unhook_keys();
}

これにより、キーボードが使用されるたびにフックがグローバル変数をインクリメントするだけであるにもかかわらず、ウィンドウが信じられないほど遅くなりました。次のように変更すると、遅延の問題が解決されました。

static void Main( string[] args )
{
    hook_keys();
    var application = new Application();
    application.Run();
    unhook_keys();
}
于 2016-11-27T07:56:31.703 に答える