2013-07-10 16 views
9

Mój przyjaciel jest ślepy i mam pomysł opracowania programu, który pozwoliłby mu korzystać z komputera przy pomocy ślepej metody pisania i audialnego sprzężenia zwrotnego. Doświadczenie byłoby znacznie bogatsze (dzięki zastosowaniu większej liczby klawiszy dla poszczególnych funkcji) i bezbłędne (np. Zapobieganie sporadycznemu utracie ostrości), jeśli moja aplikacja mogłaby w sposób wymuszony przejąć całkowitą kontrolę nad całym wprowadzeniem z klawiatury zaraz po jej uruchomieniu (powiedziałabym to w rozruchu dla niego). Jestem programistą WinForms C# .Net, więc chciałbym zaimplementować to w aplikacji używającej tej konkretnej struktury i języka (nie zważaj jednak na zawijane wywołania WinAPI).Jak przechwycić wszystkie zdarzenia na klawiaturze i zapobiec utracie ostrości w aplikacji WinForm?

PS: Nie mam nic przeciwko systemowi utrzymującemu kontrolę nad kombinacją Ctrl + Ald + Del, ale chciałbym przejąć kontrolę nad wszystkimi pozostałymi kluczami i kombinacjami, łącznie z logo Windows i standardowymi przyciskami uruchamiania aplikacji.

+4

Czapki z głów dla wysiłku, który wkładasz do swojego niewidomego przyjaciela ... – Kurubaran

+0

Jasne, do diabła, dostałbym garść notatek, gdybym nie określił celu, jak ludzie pomyśleliby, że piszę wirusa, a nie powłoka interfejsu dla niewidomych. – Ivan

+0

Naprawdę chcę stworzyć program, który pozwoli mu pisać i czytać (poprzez MS speech API) wiadomości, wybierać książki audio i muzykę do słuchania, żądać wiadomości, danych pogodowych itp. Być może będzie on nawet w stanie napisać kod na czymś jak dialekt BASIC. – Ivan

Odpowiedz

6

Można użyć implementacji haka niskiego poziomu posted here. Nie powinien kraść ognisk z dala od jakichkolwiek programów, ale twój program może zostać powiadomiony po naciśnięciu klawiszy. To jest kod z postu na wypadek, gdyby link przestał działać.

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); 
} 

można obsługiwać naciśnięcia przycisków w przypadku HookCallback (lub dalszych abstrakcyjnych głównych części do osobnej klasy i podnieść zdarzenie).

+0

Interesujące, ale chciałbym uniemożliwić innym aplikacjom i systemowi uzyskanie fokusu i dowolnych danych wejściowych, aby sporadyczna kombinacja klawiszy lub przycisk skrótu (np. Logo systemu Windows lub przycisk uruchamiania aplikacji klawiatury multimedialnej) nie wywołać standardowe działanie. – Ivan

3

Wiem, że ten temat jest stary, ale znalazłem możliwe rozwiązanie. Można użyć ostatnią odpowiedź i edytować go trochę:

zamiast dzwonić następny hak

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); 
} 

tylko zwracają -1 do zatrzymania proceding dowolny uchwyt do innych kontroli

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; 
} 

ten nie jest ładny, ale działa. Ostrożnie z tym!

+0

Dziękujemy za Twój wkład! – Ivan

Powiązane problemy