Hotkeys abfangen und behandeln

realbora

Mitglied
Hallo,

kann mir jemand verraten, wie ich vordefinierte Hotkeys abfangen und selber behandeln kann?
Zum Beispiel möchte ich den Hotkey "STRG"+"TAB" abfangen.
Damit soll erreicht werden, dass die TabPages immer dann geändert werden, wenn man die Tastenkombination drückt und nicht nur, wenn das TabControl den Focus hat.
Das Überschreiben der OnKeyDown,... -Events habe ich natürlich schon probiert. Problem hierbei ist nur, dass diese Events nicht applikationsweit überschrieben werden, was mich zu der Lösung mit dem Überschreiben von "WndProc" brachte oder mit einem MessageFilter. Beide Ansätze bekomme ich aber leider nicht so umgsetzt wie ich möchte, da ich mit den Eigenschaften WParam, LParam und Msg von "Message" noch nicht heraus bekomme, wann beide Tasten gedrückt sind.

Vielleicht kann mir da mal jemand weiterhelfen.

mfG
 
Habe endlich eine wunderbare Lösung bei Codeproject gefunden.
Hier mal die Klasse unter Verwendung.
Ich denke der Code ist selbsterklärend.

Code:
private void Form1_Load(object sender, EventArgs e)
        {
            m_GlobalKeyboardHook.HookedKeys.Add(Keys.Tab);
            m_GlobalKeyboardHook.HookedKeys.Add(Keys.Q);
            m_GlobalKeyboardHook.HookedKeys.Add(Keys.W);
            m_GlobalKeyboardHook.HookedKeys.Add(Keys.F4);
            m_GlobalKeyboardHook.KeyDown += new KeyEventHandler(m_GlobalKeyboardHook_KeyDown);
        }


Code:
        private void m_GlobalKeyboardHook_KeyDown(Object sender, KeyEventArgs e)
        {
            //offenen Tab schließen
            if (this.m_TabControl_Main.SelectedTab != null)
            {
                //Beim Drücken von STRG
                if (Control.ModifierKeys == Keys.Control)
                {
                    //Maintab schließen
                    if (e.KeyCode == Keys.F4)
                    {
                        this.m_TabControl_Main.Close(this, new CloseEventArgs(this.m_TabControl_Main.SelectedIndex));
                        e.Handled = true;
                    }

                    ////Maintabs wechseln
                    if (e.KeyCode == Keys.Tab)
                    {
                        if (this.m_TabControl_Main.SelectedIndex < this.m_TabControl_Main.TabPages.Count - 1)
                            this.m_TabControl_Main.SelectedIndex += 1;
                        else
                            this.m_TabControl_Main.SelectedIndex = 0;

                        e.Handled = true;
                    }
                    ////Subtabs wechseln
                    if (e.KeyCode == Keys.Q)
                    {
                        if (this.m_TabControl_Main.SelectedTab is TabPage_Kunde)
                        {
                            if (((TabPage_Kunde)this.m_TabControl_Main.SelectedTab).TabControl_Kunde.SelectedIndex < ((TabPage_Kunde)this.m_TabControl_Main.SelectedTab).TabControl_Kunde.TabPages.Count - 1)
                                ((TabPage_Kunde)this.m_TabControl_Main.SelectedTab).TabControl_Kunde.SelectedIndex += 1;
                            else
                                ((TabPage_Kunde)this.m_TabControl_Main.SelectedTab).TabControl_Kunde.SelectedIndex = 0;
                        }
                        e.Handled = true;
                    }
                    //Subtabs schließen
                    if (e.KeyCode == Keys.W)
                    {
                        if (this.m_TabControl_Main.SelectedTab is TabPage_Kunde)
                            if (((TabPage_Kunde)this.m_TabControl_Main.SelectedTab).TabControl_Kunde.SelectedTab != null)
                                ((TabPage_Kunde)this.m_TabControl_Main.SelectedTab).TabControl_Kunde.TabPages.Remove(((TabPage_Kunde)this.m_TabControl_Main.SelectedTab).TabControl_Kunde.SelectedTab);

                        e.Handled = true;
                    }
                }
            }
        }


Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace CoreUtils
{
    /// <summary>
    /// A class that manages a global low level keyboard hook
    /// </summary>
    public class GlobalKeyboardHook
    {
        #region Constant, Structure and Delegate Definitions
        /// <summary>
        /// defines the callback type for the hook
        /// </summary>
        public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);

        public struct keyboardHookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }

        const int WH_KEYBOARD_LL = 13;
        const int WM_KEYDOWN = 0x100;
        const int WM_KEYUP = 0x101;
        const int WM_SYSKEYDOWN = 0x104;
        const int WM_SYSKEYUP = 0x105;
        #endregion

        #region Instance Variables
        /// <summary>
        /// The collections of keys to watch for
        /// </summary>
        public List<Keys> HookedKeys = new List<Keys>();
        /// <summary>
        /// Handle to the hook, need this to unhook and call the next hook
        /// </summary>
        IntPtr hhook = IntPtr.Zero;
        /// <summary>
        /// 
        /// </summary>
        keyboardHookProc khp;
        #endregion

        #region Events
        /// <summary>
        /// Occurs when one of the hooked keys is pressed
        /// </summary>
        public event KeyEventHandler KeyDown;
        /// <summary>
        /// Occurs when one of the hooked keys is released
        /// </summary>
        public event KeyEventHandler KeyUp;
        #endregion

        #region Constructors and Destructors
        /// <summary>
        /// Initializes a new instance of the <see cref="globalKeyboardHook"/> class and installs the keyboard hook.
        /// </summary>
        public GlobalKeyboardHook()
        {
            khp = new keyboardHookProc(hookProc);
            hook();
        }

        /// <summary>
        /// Releases unmanaged resources and performs other cleanup operations before the
        /// <see cref="globalKeyboardHook"/> is reclaimed by garbage collection and uninstalls the keyboard hook.
        /// </summary>
        ~GlobalKeyboardHook()
        {
            unhook();
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Installs the global hook
        /// </summary>
        public void hook()
        {
            IntPtr hInstance = LoadLibrary("User32");
            hhook = SetWindowsHookEx(WH_KEYBOARD_LL, khp, hInstance, 0);
        }

        /// <summary>
        /// Uninstalls the global hook
        /// </summary>
        public void unhook()
        {
            UnhookWindowsHookEx(hhook);
        }

        /// <summary>
        /// The callback for the keyboard hook
        /// </summary>
        /// <param name="code">The hook code, if it isn't >= 0, the function shouldn't do anyting</param>
        /// <param name="wParam">The event type</param>
        /// <param name="lParam">The keyhook event information</param>
        /// <returns></returns>
        public int hookProc(int code, int wParam, ref keyboardHookStruct lParam)
        {
            if (code >= 0)
            {
                Keys key = (Keys)lParam.vkCode;
                if (HookedKeys.Contains(key))
                {
                    KeyEventArgs kea = new KeyEventArgs(key);
                    if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (KeyDown != null))
                    {
                        KeyDown(this, kea);
                    }
                    else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null))
                    {
                        KeyUp(this, kea);
                    }
                    if (kea.Handled)
                        return 1;
                }
            }
            return CallNextHookEx(hhook, code, wParam, ref lParam);
        }
        #endregion

        #region DLL imports
        /// <summary>
        /// Sets the windows hook, do the desired event, one of hInstance or threadId must be non-null
        /// </summary>
        /// <param name="idHook">The id of the event you want to hook</param>
        /// <param name="callback">The callback.</param>
        /// <param name="hInstance">The handle you want to attach the event to, can be null</param>
        /// <param name="threadId">The thread you want to attach the event to, can be null</param>
        /// <returns>a handle to the desired hook</returns>
        [DllImport("user32.dll")]
        static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);

        /// <summary>
        /// Unhooks the windows hook.
        /// </summary>
        /// <param name="hInstance">The hook handle that was returned from SetWindowsHookEx</param>
        /// <returns>True if successful, false otherwise</returns>
        [DllImport("user32.dll")]
        static extern bool UnhookWindowsHookEx(IntPtr hInstance);

        /// <summary>
        /// Calls the next hook.
        /// </summary>
        /// <param name="idHook">The hook id</param>
        /// <param name="nCode">The hook code</param>
        /// <param name="wParam">The wparam.</param>
        /// <param name="lParam">The lparam.</param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref keyboardHookStruct lParam);

        /// <summary>
        /// Loads the library.
        /// </summary>
        /// <param name="lpFileName">Name of the library</param>
        /// <returns>A handle to the library</returns>
        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);
        #endregion
    }
}
 
Würde es nicht auch reichen bei einer Form, KeyPrevie=true und dann
Code:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
        if (e.Control && e.KeyCode == Keys.Tab)
        {
                if (!tabControl1.Focused)
                {
                    if (tabControl1.SelectedIndex + 1 < tabControl1.TabCount)
                        tabControl1.SelectedIndex++;
                    else
                        tabControl1.SelectedIndex = 0;
                }
        }
}
 
Hy,

dein Vorschlag klappt glaube ich leider nicht, da sobald ein anderes Control im TabControl den Focus hat, wird der KeyDown-Event nicht mehr abgefangen. Deshalb habe ich ja auch nach einer Lösung gesucht, die auch das unterstützt, was ich gesucht habe.

mfG
 
Habs mit Focus auf anderen Controls getestet und da hats funktioniert, hab aber nicht explizit getestet ob es auch mit Controls in TabPages funktioniert.
Bin nicht zu hause und kanns jetzt nicht testen, aber bin eigentlich fast überzeugt davon das es funktionieren sollte da das KeyDown Event beim Formular abgefragt wird.

Wie gesagt bei der Form die Eigenschaft KeyPreview auf true setzen.
 
Genau das ist ja das Problem.
Wenn die Controls in den TabPages den Focus haben, dann wird der Event nicht ausgelöst.
Teste das mal und sag bescheid.
Bei mir hatte das alles nicht funktioniert.

mfG
 
Also habs mit TextBox, ListBox und DataGridView in einer TabPage probiert und hat alles funktioniert (nur beim DataGridView musste ich 2 mal drücken).

Und wie gesagt KEyDown wurde nur vom Formular direkt ausgewertet.
 
Hy,

ich kann nur von meinen Erfahrungen berichten und da hat das, was du vorschlägst nie funktioniert.
Vielleicht hilft das ja mal jemandem weiter, der das selbe Problem hat.
Vielen Dank für deine Antworten.

mfG
 
Hy,

ich kann nur von meinen Erfahrungen berichten und da hat das, was du vorschlägst nie funktioniert.
Vielleicht hilft das ja mal jemandem weiter, der das selbe Problem hat.
Vielen Dank für deine Antworten.

mfG
 
Zurück