2013-07-10 9 views
9

私の友人は盲目で、私は彼がブラインドタイピング法と音声フィードバックの助けを借りてPCを使うことができるプログラムを開発する考えがあります。私のアプリケーションが、キーボード入力が開始されるとすぐにキーボード入力全体を強制的に完全に制御することができれば、経験はより豊かになり(特定の機能にはより多くのキーを使用する)、完璧に(時折のフォーカス損失を防ぐように)彼のためのスタートアップで)。私はWinForms C#.NET開発者ですので、この特定のフレームワークと言語(WinAPI呼び出しをラップしても構いません)を使用してアプリケーションに実装したいと思います。すべてのキーボードイベントをインターセプトし、WinFormsアプリケーションでフォーカスを失うことを防ぐには?

PS:Ctrl + Ald + Delの組み合わせでシステムを制御しても構いませんが、Windowsロゴや標準のアプリケーションランチャーボタンなど、他のすべてのキーと組み合わせを制御したいと思います。

+4

あなたの盲目の友人のために入れている努力のために帽子を外してください... – Kurubaran

+0

確かに地獄ではありません私は人が私はウイルスを書くと思うように目的を指定しなかった場合、盲人用のUIシェル。 – Ivan

+0

私は実際に彼が(MS音声APIを通して)メッセージを読んで読んで聞かせるためにオーディオブックと音楽を選択し、ニュース、気象データなどを要求するプログラムを作りたがっています。おそらく彼は何かにコードを書くことさえできるでしょうBASIC方言のように。 – Ivan

答えて

6

低レベルキーボードフックの実装posted hereを使用できます。それはどんなプログラムからでも離れて焦点を奪うべきではありませんが、あなたのプログラムはキーが押されたときに通知されます。これは、リンクが機能しなくなった場合のポストのコードです。

using System; 
using System.Diagnostics; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

class InterceptKeys 
{ 
    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); 
      Console.WriteLine((Keys)vkCode); 
     } 
     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イベントのキーの押下を処理することができます。

+0

面白いですが、他のアプリケーションやシステムがフォーカスや入力を取得して、時折キーを押したり、ショートカットキー(Windowsのロゴやマルチメディアキーボードのアプリケーションランチャーボタンなど)を表示しないようにしたいのですが標準的な行動を引き起こす。 – Ivan

3

私はこのトピックが古いと知っていますが、解決策が見つかりました。あなたは最後の答えを使用して、それを少し編集することができます。

代わりにこの

だけ-1を返し、他のコントロールに任意のハンドルをproceding停止する

private static IntPtr HookCallback(
    int nCode, IntPtr wParam, IntPtr lParam) 
{ 
    if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) 
    { 
     int vkCode = Marshal.ReadInt32(lParam); 
     Console.WriteLine((Keys)vkCode); 
    } 
    return -1; 
} 

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

を次のフックを呼び出します素敵じゃないけど働いている。これに注意してください!

+0

ありがとうございます! – Ivan

関連する問題