简体   繁体   English

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

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

In a C# Windows Form I would like transcode information: when user press CTRL+I, the app detect the key press combination, it takes the code in the clipboard and transcode it. 在C#Windows窗体中,我想转码信息:当用户按CTRL + I时,应用程序检测到按键组合,它将剪贴板中的代码进行转码。

I find out this code: 我发现以下代码:

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

This works fine when windows form has focus. 当Windows窗体具有焦点时,这工作正常。

I would like detect the combination when the app is minimized as tray icon. 当应用程序最小化为任务栏图标时,我想检测组合。

SOLUTION: 解:

keyboardhook.cs: 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 (Form): 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;
        }
    }
}
}

This works just instantiate it, subscibe to the event and you are done. 只需实例化它,订阅事件即可完成。 It s not my script. 这不是我的剧本。 A while ago I searched long for this but I found it and it works great. 不久前,我搜索了很长时间,但发现了它,效果很好。 There were you subscribed to the event you can look if the pressed key (stored in the event args) is your key and when it is you can look with Keyboard.iskeydown(key.lctrl) if control is pressed to and then you can do what the combination should do. 那里有您订阅的事件,您可以查看是否已按下的键(存储在事件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);

then 然后

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