How to make a keyboard hook global across processes

后端 未结 5 764
-上瘾入骨i
-上瘾入骨i 2020-11-30 08:37

I am trying to create a utility keystroke app so i can do things like kill a preprogrammed process or launch something. I am thinking I should hold cmd in any app, then type

5条回答
  •  刺人心
    刺人心 (楼主)
    2020-11-30 08:59

    For Glopbal Keyboard Hook just for Hot Key's, then Register hotkey is the best (its done by Microsoft):

    https://msdn.microsoft.com/en-us/library/windows/desktop/ms646309(v=vs.85).aspx

    Download the sample winform app and see for yourself:

    https://code.msdn.microsoft.com/CppRegisterHotkey-7bd897a8 C++ https://code.msdn.microsoft.com/CSRegisterHotkey-e3f5061e C# https://code.msdn.microsoft.com/VBRegisterHotkey-50af3179 VB.Net

    Winform App:

    /****************************** Module Header ******************************\
    * Module Name:  MainForm.cs
    * Project:      CSRegisterHotkey
    * Copyright (c) Microsoft Corporation.
    * 
    * This is the main form of this application. It is used to initialize the UI 
    * and handle the events.
    * 
    * This source is subject to the Microsoft Public License.
    * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
    * All other rights reserved.
    * 
    * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
    * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
    * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
    \***************************************************************************/
    
    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace CSRegisterHotkey
    {
        public partial class MainForm : Form
        {
            HotKeyRegister hotKeyToRegister = null;
            Keys registerKey = Keys.None;
            KeyModifiers registerModifiers = KeyModifiers.None;
    
            public MainForm()
            {
                InitializeComponent();
            }
    
            /// 
            /// Handle the KeyDown of tbHotKey. In this event handler, check the pressed keys.
            /// The keys that must be pressed in combination with the key Ctrl, Shift or Alt,
            /// like Ctrl+Alt+T. The method HotKeyRegister.GetModifiers could check whether 
            /// "T" is pressed.
            /// 
            private void tbHotKey_KeyDown(object sender, KeyEventArgs e)
            {
                // The key event should not be sent to the underlying control.
                e.SuppressKeyPress = true;
    
                // Check whether the modifier keys are pressed.
                if (e.Modifiers != Keys.None)
                {
                    Keys key = Keys.None;
                    KeyModifiers modifiers = HotKeyRegister.GetModifiers(e.KeyData, out key);
    
                    // If the pressed key is valid...
                    if (key != Keys.None)
                    {
                        this.registerKey = key;
                        this.registerModifiers = modifiers;
    
                        // Display the pressed key in the textbox.
                        tbHotKey.Text = string.Format("{0}+{1}",
                            this.registerModifiers, this.registerKey);
    
                        // Enable the button.
                        btnRegister.Enabled = true;
                    }
                }
            }
    
    
            /// 
            /// Handle the Click event of btnRegister.
            /// 
            private void btnRegister_Click(object sender, EventArgs e)
            {
                try
                {
                    // Register the hotkey.
                    hotKeyToRegister = new HotKeyRegister(this.Handle, 100,
                        this.registerModifiers, this.registerKey);
    
                    // Register the HotKeyPressed event.
                    hotKeyToRegister.HotKeyPressed += new EventHandler(HotKeyPressed);
    
                    // Update the UI.
                    btnRegister.Enabled = false;
                    tbHotKey.Enabled = false;
                    btnUnregister.Enabled = true;
                }
                catch (ArgumentException argumentException)
                {
                    MessageBox.Show(argumentException.Message);
                }
                catch (ApplicationException applicationException)
                {
                    MessageBox.Show(applicationException.Message);
                }
            }
    
            /// 
            /// Show a message box if the HotKeyPressed event is raised.
            /// 
            void HotKeyPressed(object sender, EventArgs e)
            {
               //Here is the magic!!!!!!!!'
    
               //DO SOMETHING COOL!!! Or Just activate this winform
    
                if (this.WindowState == FormWindowState.Minimized)
                {
                    this.WindowState = FormWindowState.Normal;
                }
                this.Activate();
    
    
    
            }
    
            /// 
            /// Handle the Click event of btnUnregister.
            /// 
            private void btnUnregister_Click(object sender, EventArgs e)
            {
                // Dispose the hotKeyToRegister.
                if (hotKeyToRegister != null)
                {
                    hotKeyToRegister.Dispose();
                    hotKeyToRegister = null;
                }
    
                // Update the UI.
                tbHotKey.Enabled = true;
                btnRegister.Enabled = true;
                btnUnregister.Enabled = false;
            }
    
    
            /// 
            /// Dispose the hotKeyToRegister when the form is closed.
            /// 
            protected override void OnClosed(EventArgs e)
            {
                if (hotKeyToRegister != null)
                {
                    hotKeyToRegister.Dispose();
                    hotKeyToRegister = null;
                }
    
                base.OnClosed(e);
            }
        }
    }
    

    HotKeyRegister.cs

    /****************************** Module Header ******************************\
    * Module Name:  HotKeyRegister.cs
    * Project:      CSRegisterHotkey
    * Copyright (c) Microsoft Corporation.
    * 
    * This class imports the method RegisterHotKey and UnregisterHotKey in 
    * user32.dll to define or free a system-wide hot key.
    * 
    * The method Application.AddMessageFilter is used to add a message filter to 
    * monitor Windows messages as they are routed to their destinations. Before a 
    * message is dispatched, the method PreFilterMessage could handle it. If a 
    * WM_HOTKEY messages was generated by the hot key that was registered by this 
    * HotKeyRegister object, then raise a HotKeyPressed event.
    * 
    * This class also supplies a static method GetModifiers to get the modifiers 
    * and key from the KeyData property of KeyEventArgs.
    * 
    * This source is subject to the Microsoft Public License.
    * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
    * All other rights reserved.
    * 
    * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
    * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
    * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
    \***************************************************************************/
    
    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    using System.Security.Permissions;
    
    namespace CSRegisterHotkey
    {
        public class HotKeyRegister : IMessageFilter, IDisposable
        {
            /// 
            /// Define a system-wide hot key.
            /// 
            /// 
            /// A handle to the window that will receive WM_HOTKEY messages generated by the
            /// hot key. If this parameter is NULL, WM_HOTKEY messages are posted to the 
            /// message queue of the calling thread and must be processed in the message loop.
            /// 
            /// 
            /// The identifier of the hot key. If the hWnd parameter is NULL, then the hot 
            /// key is associated with the current thread rather than with a particular 
            /// window. 
            /// 
            /// 
            /// The keys that must be pressed in combination with the key specified by the 
            /// uVirtKey parameter in order to generate the WM_HOTKEY message. The fsModifiers
            /// parameter can be a combination of the following values.
            /// MOD_ALT     0x0001
            /// MOD_CONTROL 0x0002
            /// MOD_SHIFT   0x0004
            /// MOD_WIN     0x0008
            /// 
            /// The virtual-key code of the hot key.
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool RegisterHotKey(IntPtr hWnd, int id, 
                KeyModifiers fsModifiers, Keys vk);
    
            /// 
            /// Frees a hot key previously registered by the calling thread. 
            /// 
            /// 
            /// A handle to the window associated with the hot key to be freed. This parameter
            /// should be NULL if the hot key is not associated with a window.
            /// 
            /// 
            /// The identifier of the hot key to be freed. 
            /// 
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
    
            /// 
            /// Get the modifiers and key from the KeyData property of KeyEventArgs.
            /// 
            /// 
            /// The KeyData property of KeyEventArgs. The KeyData is a key in combination
            /// with modifiers.
            /// 
            /// The pressed key.
            public static KeyModifiers GetModifiers(Keys keydata, out Keys key)
            {
                key = keydata;
                KeyModifiers modifers = KeyModifiers.None;
    
                // Check whether the keydata contains the CTRL modifier key.
                // The value of Keys.Control is 131072.
                if ((keydata & Keys.Control) == Keys.Control)
                {
                    modifers |= KeyModifiers.Control;
    
                    key = keydata ^ Keys.Control;
                }
    
                // Check whether the keydata contains the SHIFT modifier key.
                // The value of Keys.Control is 65536.
                if ((keydata & Keys.Shift) == Keys.Shift)
                {
                    modifers |= KeyModifiers.Shift;
                    key = key ^ Keys.Shift;
                }
    
                // Check whether the keydata contains the ALT modifier key.
                // The value of Keys.Control is 262144.
                if ((keydata & Keys.Alt) == Keys.Alt)
                {
                    modifers |= KeyModifiers.Alt;
                    key = key ^ Keys.Alt;
                }
    
                // Check whether a key other than SHIFT, CTRL or ALT (Menu) is pressed.
                if (key == Keys.ShiftKey || key == Keys.ControlKey || key == Keys.Menu)
                {
                    key = Keys.None;
                }
    
                return modifers;
            }
    
            /// 
            /// Specify whether this object is disposed.
            /// 
            bool disposed = false;
    
            /// 
            /// This constant could be found in WinUser.h if you installed Windows SDK.
            /// Each windows message has an identifier, 0x0312 means that the mesage is 
            /// a WM_HOTKEY message.
            /// 
            const int WM_HOTKEY = 0x0312;
    
            /// 
            /// A handle to the window that will receive WM_HOTKEY messages generated by the
            /// hot key.
            /// 
            public IntPtr Handle { get; private set; }
    
            /// 
            /// A normal application can use any value between 0x0000 and 0xBFFF as the ID 
            /// but if you are writing a DLL, then you must use GlobalAddAtom to get a 
            /// unique identifier for your hot key. 
            /// 
            public int ID { get; private set; }
    
            public KeyModifiers Modifiers { get; private set; }
    
            public Keys Key { get; private set; }
    
            /// 
            /// Raise an event when the hotkey is pressed.
            /// 
            public event EventHandler HotKeyPressed;
    
    
            public HotKeyRegister(IntPtr handle, int id, KeyModifiers modifiers, Keys key)
            {
                if (key == Keys.None || modifiers == KeyModifiers.None)
                {
                    throw new ArgumentException("The key or modifiers could not be None.");
                }
    
                this.Handle = handle;
                this.ID = id;
                this.Modifiers = modifiers;
                this.Key = key;
    
                RegisterHotKey();
    
                // Adds a message filter to monitor Windows messages as they are routed to
                // their destinations.
                Application.AddMessageFilter(this);
            }
    
    
            /// 
            /// Register the hotkey.
            /// 
            private void RegisterHotKey()
            {
                bool isKeyRegisterd = RegisterHotKey(Handle, ID, Modifiers, Key);
    
                // If the operation failed, try to unregister the hotkey if the thread 
                // has registered it before.
                if (!isKeyRegisterd)
                {
                    // IntPtr.Zero means the hotkey registered by the thread.
                    UnregisterHotKey(IntPtr.Zero, ID);
    
                    // Try to register the hotkey again.
                    isKeyRegisterd = RegisterHotKey(Handle, ID, Modifiers, Key);
    
                    // If the operation still failed, it means that the hotkey was already 
                    // used in another thread or process.
                    if (!isKeyRegisterd)
                    {
                        throw new ApplicationException("The hotkey is in use");
                    }
                }
            }
    
    
            /// 
            /// Filters out a message before it is dispatched.
            /// 
            [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
            public bool PreFilterMessage(ref Message m)
            {
                // The property WParam of Message is typically used to store small pieces 
                // of information. In this scenario, it stores the ID.
                if (m.Msg == WM_HOTKEY
                    && m.HWnd == this.Handle
                    && m.WParam == (IntPtr)this.ID
                    && HotKeyPressed != null)
                {
                    // Raise the HotKeyPressed event if it is an WM_HOTKEY message.
                    HotKeyPressed(this, EventArgs.Empty);
    
                    // True to filter the message and stop it from being dispatched.
                    return true;
                }
    
                // Return false to allow the message to continue to the next filter or 
                // control.
                return false;
            }
    
    
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            /// 
            /// Unregister the hotkey.
            /// 
            protected virtual void Dispose(bool disposing)
            {
                // Protect from being called multiple times.
                if (disposed)
                {
                    return;
                }
    
                if (disposing)
                {
    
                    // Removes a message filter from the message pump of the application.
                    Application.RemoveMessageFilter(this);
    
                    UnregisterHotKey(Handle, ID);
                }
    
                disposed = true;
            }
        }
    }
    

    KeyModifiers.cs:

    /****************************** Module Header ******************************\
    * Module Name:  KeyModifiers.cs
    * Project:      CSRegisterHotkey
    * Copyright (c) Microsoft Corporation.
    * 
    * This enum defines the modifiers to generate the WM_HOTKEY message. 
    * See http://msdn.microsoft.com/en-us/library/ms646309(VS.85).aspx.
    * 
    * This source is subject to the Microsoft Public License.
    * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
    * All other rights reserved.
    * 
    * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
    * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
    * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
    \***************************************************************************/
    
    using System;
    
    namespace CSRegisterHotkey
    {
        [Flags]
        public enum KeyModifiers
        {
            None = 0,
            Alt = 1,
            Control = 2,
            Shift = 4,
    
            // Either WINDOWS key was held down. These keys are labeled with the Windows logo.
            // Keyboard shortcuts that involve the WINDOWS key are reserved for use by the 
            // operating system.
            Windows = 8
        }
    }
    

提交回复
热议问题