2013-07-10 2 views
9

Ein Freund von mir ist blind und ich habe eine Idee, ein Programm zu entwickeln, das es ihm erlauben würde, einen PC mit Hilfe einer blinden Tippmethode und auditiver Rückmeldung zu benutzen. Die Erfahrung wäre viel reicher (die Verwendung von mehr Tasten für bestimmte Funktionen) und fehlerlos (wie das Verhindern von gelegentlichem Fokusverlust), wenn meine Anwendung gewaltsam die totale Kontrolle über die gesamte Tastatureingabe übernehmen könnte, sobald sie gestartet wird (ich würde es sagen) im Start-up für ihn). Ich bin ein WinForms C# .Net-Entwickler, also möchte ich dies in einer Anwendung implementieren, die dieses spezielle Framework und diese spezielle Sprache verwendet (verwickelte WinAPI-Aufrufe beachten).Wie abfangen alle Tastaturereignisse und verhindern, den Fokus in einer WinForms-Anwendung zu verlieren?

PS: Ich habe nichts dagegen, dass das System die Kontrolle über die Kombination Strg + Ald + Entf behält, aber ich möchte die Kontrolle über alle anderen Tasten und Kombinationen übernehmen, einschließlich des Windows-Logos und der Standard-Anwendungsstarter.

+4

Hut ab für die Mühe, die Sie für Ihren blinden Freund setzen ... – Kurubaran

+0

Natürlich würde ich eine Handvoll Downvotes bekommen, wenn ich nicht den Zweck angegeben hätte, da die Leute denken würden, ich schreibe lieber einen Virus eine UI-Shell für blinde Menschen. – Ivan

+0

Ich möchte tatsächlich ein Programm machen, das ihn schreiben und lesen lässt (durch MS-Sprach-API) Nachrichten, Hörbücher und Musik auswählen, Nachrichten, Wetterdaten usw. anfragen. Vielleicht wird er sogar in der Lage sein, etwas zu schreiben wie ein BASIC-Dialekt. – Ivan

Antwort

6

Sie können die Low-Level-Tastatur-Hook-Implementierung posted here verwenden. Es sollte nicht Fokus weg von irgendwelchen Programmen stehlen, aber Ihr Programm kann benachrichtigt werden, wenn Schlüssel gedrückt werden. Dies ist der Code aus dem Post, falls die Verbindung nicht mehr funktioniert.

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

Sie können die Tastendrücke im HookCallback Ereignis (oder weiter abstrakt die wichtigsten Teile in eine separate Klasse und ein Ereignis auslösen) behandeln.

+0

Interessant, aber ich möchte verhindern, dass die anderen Anwendungen und das System den Fokus und jede Eingabe erhalten, so dass eine gelegentliche Tastenkombination gedrückt oder eine Tastenkombination (wie das Windows-Logo oder eine Multimedia-Tastatur Application Launcher-Taste) nicht triggern Sie die Standardaktion. – Ivan

3

Ich weiß, dass dieses Thema alt ist, aber ich fand eine mögliche Lösung. Sie können die letzte Antwort verwenden und es ein wenig bearbeiten:

stattdessen den nächsten Haken des Aufrufs

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

nur -1 zurück zum Anhalten jeder Handgriff auf andere Kontrollen 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; 
} 

Diese ist nicht nett, aber es funktioniert. Sei vorsichtig damit!

+0

Vielen Dank für Ihren Beitrag! – Ivan

Verwandte Themen