2013-07-10 11 views
9

Un mio amico è cieco e ho l'idea di sviluppare un programma che gli permetta di usare un PC con l'aiuto di un metodo di battitura cieco e feedback auditivo. L'esperienza sarebbe molto più ricca (facendo uso di più tasti per funzioni particolari) e impeccabile (come la prevenzione di occasionali perdite di messa a fuoco) se la mia applicazione potesse forzatamente assumere il controllo totale sull'intero input della tastiera non appena viene avviata (lo direi in start-up per lui). Sono uno sviluppatore C# .Net di WinForms, quindi mi piacerebbe implementarlo in un'applicazione che usa questo particolare framework e linguaggio (non mi dispiace però chiamare WinAPI).Come intercettare tutti gli eventi della tastiera e impedire di perdere la concentrazione in un'applicazione WinForms?

PS: Non mi dispiace che il sistema mantenga il controllo sulla combinazione Ctrl + Ald + Canc, ma mi piacerebbe prendere il controllo di tutti gli altri tasti e combinazioni, incluso il logo Windows ei pulsanti di avvio delle applicazioni standard.

+4

cappelli spenti per lo sforzo che stai facendo per il tuo amico cieco ... – Kurubaran

+0

Certo che avrei avuto una manciata di downvotes se non avessi specificato lo scopo in quanto la gente penserebbe che sto scrivendo un virus piuttosto che una shell dell'interfaccia utente per non vedenti. – Ivan

+0

In realtà voglio creare un programma che gli consenta di scrivere e leggere (attraverso i messaggi API MS), selezionare audiolibri e musica da ascoltare, richiedere notizie, dati meteorologici, ecc. Forse sarà anche in grado di scrivere codice su qualcosa come un dialetto BASIC. – Ivan

risposta

6

È possibile utilizzare l'implementazione di aggancio della tastiera di livello basso posted here. Non dovrebbe rubare l'attenzione lontano da qualsiasi programma, ma il tuo programma può essere avvisato quando i tasti vengono premuti. Questo è il codice del post nel caso in cui il collegamento smette di funzionare.

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

È possibile gestire le pressioni di tasti in caso HookCallback (o ulteriori astratte le principali parti in una classe separata e generare un evento).

+0

Interessante, ma vorrei impedire alle altre applicazioni e al sistema di ottenere il focus e qualsiasi input in modo che una combinazione di tasti occasionale o un tasto di scelta rapida (come il logo di Windows o un pulsante di avvio dell'applicazione per tastiera multimediale) non innescare l'azione standard. – Ivan

3

So che questo argomento è vecchio, ma ho trovato una possibile soluzione. È possibile utilizzare l'ultima risposta e modificarlo un po ':

invece di chiamare la prossima gancio

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

solo tornare -1 per l'arresto di procedere qualsiasi maniglia per altri controlli

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

Questo non è bello ma funziona. Stai attento con questo!

+0

Grazie per aver contribuito! – Ivan

Problemi correlati