繁体   English   中英

如何在C#中随时检测CTRL +快捷键

[英]How to detect CTRL+keypress shortcut at any time in C#

在C#Windows窗体中,我想转码信息:当用户按CTRL + I时,应用程序检测到按键组合,它将剪贴板中的代码进行转码。

我发现以下代码:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        switch (msg.Msg)
        {
            case 0x100:
            case 0x104:
                switch (keyData)
                {
                    case Keys.Control | Keys.I:
                        MessageBox.Show("Ctrl + I pressed");
                        break;
                }
                break;
        }
        return base.ProcessCmdKey(ref msg, keyData);
    }

当Windows窗体具有焦点时,这工作正常。

当应用程序最小化为任务栏图标时,我想检测组合。

解:

keyboardhook.cs:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace TrayIconForm
{
    public static class Constants
    {
    public const int NOMOD = 0x0000;
    public const int ALT = 0x0001;
    public const int CTRL = 0x0002;
    public const int SHIFT = 0x0004;
    public const int WIN = 0x0008;

    public const int WM_HOTKEY_MSG_ID = 0x0312;
    }
public class KeyHandler
{
    [DllImport("user32.dll")]
    private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
    [DllImport("user32.dll")]
    private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

    private int modifier;
    private int key;
    private IntPtr hWnd;
    private int id;
    public KeyHandler(int modifier, Keys key, Form form)
    {
        this.modifier = modifier;
        this.key = (int)key;
        this.hWnd = form.Handle;
        id = this.GetHashCode();
    }
    public override int GetHashCode()
    {
        return modifier ^ key ^ hWnd.ToInt32();
    }
    public bool Register()
    {
        return RegisterHotKey(hWnd, id, modifier, key);
    }
    public bool Unregiser()
    {
        return UnregisterHotKey(hWnd, id);
    }
}
}

Information.cs(表格):

using System;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TrayIconForm
{
public partial class Information : Form
{
    private KeyHandler ghk;

    public Information()
    {
        InitializeComponent();

        ghk = new KeyHandler(Constants.CTRL, Keys.I, this);
        ghk.Register();

    }
    private void HandleHotkey()
    {
        string s = Get_Copy();

        notifyIcon1.BalloonTipText = s;
        notifyIcon1.BalloonTipTitle = "You have pressed CTRL+i";
        notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;

        notifyIcon1.Visible = true;
        notifyIcon1.ShowBalloonTip(500);
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == Constants.WM_HOTKEY_MSG_ID)
            HandleHotkey();
        base.WndProc(ref m);
    }

    private string Get_Copy()
    {
        string r;
        // Retrieves data from Clipboard
        IDataObject iData = Clipboard.GetDataObject();
        // Is Data Text?
        if (iData.GetDataPresent(DataFormats.Text))
            r = (String)iData.GetData(DataFormats.Text);
        else
            r = "nothing";
        return r;
    }
    private void Information_Resize(object sender, EventArgs e)
    {
        if (FormWindowState.Minimized == this.WindowState)
        {
            notifyIcon1.BalloonTipText =  "My application still working...";
            notifyIcon1.BalloonTipTitle = "My Sample Application";
            notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;

            notifyIcon1.Visible = true;
            notifyIcon1.ShowBalloonTip(500);
            this.Hide();
        }
        else if (FormWindowState.Normal == this.WindowState)
        {
            notifyIcon1.Visible = false;
        }
    }
}
}

只需实例化它,订阅事件即可完成。 这不是我的剧本。 不久前,我搜索了很长时间,但发现了它,效果很好。 那里有您订阅的事件,您可以查看是否已按下的键(存储在事件args中)是您的键,如果已按下,则可以按Keyboard.iskeydown(key.lctrl)进行查看(如果已按下控件),则可以组合应该做什么。

using System; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 
using System.Windows.Input;

namespace <yournamespace>
{
    public class LowLevelKeyboardListener
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_SYSKEYDOWN = 0x0104;

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

        public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        public event EventHandler<KeyPressedArgs> OnKeyPressed;

        private LowLevelKeyboardProc _proc;
        private IntPtr _hookID = IntPtr.Zero;

        public LowLevelKeyboardListener()
        {
            _proc = HookCallback;
        }

        public void HookKeyboard()
        {
            _hookID = SetHook(_proc);
        }

        public void UnHookKeyboard()
        {
            UnhookWindowsHookEx(_hookID);
        }

        private 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 IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);

                if (OnKeyPressed != null) { OnKeyPressed(this, new KeyPressedArgs(KeyInterop.KeyFromVirtualKey(vkCode))); }
            }

            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
    }

    public class KeyPressedArgs : EventArgs
    {
        public Key KeyPressed { get; private set; }

        public KeyPressedArgs(Key key)
        {
            KeyPressed = key;
        }
    }
}
[DllImport("user32.dll")]
    public static extern int GetAsyncKeyState(Keys vKeys);

然后

var ctrl = GetAsyncKeyState(Keys.ControlKey) & 0x8000;
var key = GetAsyncKeyState(Keys.F10) & 0x8000; //F10 for example
if(ctrl != 0 && key != 0)
{
    //do sth
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM