Feedback

C# - Globale KeyHook

Veröffentlicht von am 12/13/2007
(4 Bewertungen)
Mit dieser Klasse kann man eine systemweite KeyboardHook setzen. Dabei werden alle Tasten in die List KeyCodes geschrieben.
public class KeyHook
    {
        private delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

        //Declare hook handle as int.
        static int hHook = 0;

        public static List<Keys> KeyCodes = new List<Keys>();

        //Declare keyboard hook constant.
        //For other hook types, you can obtain these values from Winuser.h in Microsoft SDK.
        const int WH_KEYBOARD_LL = 13;

        HookProc KeyboardHookProcedure;

        [StructLayout(LayoutKind.Sequential)]
        private class keyboardHookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }

        //Import for SetWindowsHookEx function.
        //Use this function to install thread-specific hook.
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        private static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
        IntPtr hInstance, int threadId);

        //Import for UnhookWindowsHookEx.
        //Call this function to uninstall the hook.
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        private static extern bool UnhookWindowsHookEx(int idHook);

        //Import for CallNextHookEx.
        //Use this function to pass the hook information to next hook procedure in chain.
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        private static extern int CallNextHookEx(int idHook, int nCode,
        IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);

        public KeyHook()
        {
            Hook();
        }

        ~KeyHook()
        {
            UnHook();
        }

        public int Hook()
        {
            KeyboardHookProcedure = new HookProc(KeyHook.KeyboardHookProc);

            hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, (IntPtr)LoadLibrary("User32"), 0);
            return hHook;
        }

        public bool UnHook()
        {
            bool ret = UnhookWindowsHookEx(hHook);
            if (ret)
                hHook = 0;
            return ret;
        }

        private static int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode < 0)
            {
                return CallNextHookEx(hHook, nCode, wParam, lParam);
            }
            else
            {

                if (((int)wParam == 256) || ((int)wParam == 260))
                {
                    keyboardHookStruct MyKeyboardHookStruct = (keyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(keyboardHookStruct));
                    KeyCodes.Add((Keys)MyKeyboardHookStruct.vkCode);
                }
                return 1;
            }
        }

    }
Abgelegt unter Hook, Keyboard.

5 Kommentare zum Snippet

Macximilian schrieb am 5/4/2008:
Wenn ich die Keys mitprotokolliere, indem ich bei KeyCodes.Add((Keys)MyKeyboardHookStruct.vkCode); die KeyCodes in eine Listbox schreibe, bemerke ich gerade, dass die Tasten zwar abgefangen, aber nicht normal geschrieben werden. D.h. wenn ich im Editor "Hallo" schreibe, steht in meiner Listbox zwar H A L L O, aber im Editor nichts...

Kann man das irgendwie verändern, dass die Tasten auch wirklich von Windows "ausgeführt" und nicht nur protokolliert werden?

PS: Die einzigen Tasten, die protokolliert und ausgeführt werden, sind die Power und die Sleep-Tasten, durch die mein PC in den Standby bzw. Ruhezustand versetzt werden.
Greenberet schrieb am 5/4/2008:
ersetz das "return 1" durch "return CallNextHookEx(hHook, nCode, wParam, lParam);"
in der methode: private static int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
das return 1 sorgt dafür, dass der hook abgefangen wird und windows ihn nicht mehr verarbeitet.
Macximilian schrieb am 5/5/2008:
Achja, hab ich vergessen zu sagen:
Das hab ich schon probiert!
Es trat allerdings, als ich eine Taste drückte folgender Fehler bei obigem Befehlssatz auf:
"Für den von der Garbage Collection gesammelten Delegaten vom Typ "WindowsChiiks!WindowsChiiks.KeyHook+HookProc::Invoke" wurde ein Rückruf durchgeführt. Dies kann Anwendungsabstürze, Datenbeschädigung und -verlust zur Folge haben. Beim Übergeben von Delegaten an nicht verwalteten Code müssen die Delegaten von der verwalteten Anwendung beibehalten werden, bis sichergestellt ist, dass sie nie aufgerufen werden."

Kenn mich mit Delegaten nicht so aus... Was muss ich verändern?
makue schrieb am 2/3/2009:
Hallo, im Forum habe ich keinen Thread darüber gefunden und wollte wegen einer Frage auch nichts anlegen. Es funktioniert alles perfekt, ich würde nun aber gern für eine abgefangene Taste mehrere andere Tastendrücke simulieren. Ist das irgendwie machbar? Danke!
DMsRising schrieb am 9/8/2013:
entschuldigt mich bitte, wenn ich dieses alte Thema wieder hochpushe, aber ich habe grade glaub ich ein Brett vorm Kopf: Wenn ich obenstehenden code im release ausführe und tasten drücke, werden diese manchmal doppelt oder dreifach ausgewertet.
"NumPad1
NumPad2
NumPad1
NumPad3
NumPad2
NumPad4
NumPad3
NumPad5
NumPad4
NumPad6
NumPad5
NumPad6
NumPad7
NumPad8
NumPad7
NumPad9
NumPad8
NumPad9"
kommt da z.B. raus wenn ich 123456789 auf dem Numpad eingebe.
Was kann ich tun, um die auswertung auf eins zu begrenzen?
 

Logge dich ein, um hier zu kommentieren!