C# C Registerhotkey()无法读取某些键代码

C# C Registerhotkey()无法读取某些键代码,c#,visual-studio,hotkeys,registerhotkey,C#,Visual Studio,Hotkeys,Registerhotkey,在尝试使用VisualStudio Windows窗体创建自动点击器应用程序时,我遇到了一个问题,该窗体允许您选择所需的热键 当用户输入诸如~或/之类的键时,热键将不起作用,但是,如果我输入0xC0表示tilde或0xDC表示slash,而不是int[tilde]或int'/,它将起作用 除此之外,字母必须大写,但这没关系,因为我可以用ToUpper来大写 允许用户选择字符的部分很好,它将字母作为字符串返回 在这里,我实现了RegisterHotKey和UnregisterHotKey,并为表单

在尝试使用VisualStudio Windows窗体创建自动点击器应用程序时,我遇到了一个问题,该窗体允许您选择所需的热键

当用户输入诸如~或/之类的键时,热键将不起作用,但是,如果我输入0xC0表示tilde或0xDC表示slash,而不是int[tilde]或int'/,它将起作用

除此之外,字母必须大写,但这没关系,因为我可以用ToUpper来大写

允许用户选择字符的部分很好,它将字母作为字符串返回

在这里,我实现了RegisterHotKey和UnregisterHotKey,并为表单设置了事件:

    [DllImport("user32.dll")]
    public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
    [DllImport("user32.dll")]
    public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

    protected override void WndProc(ref Message m) {
                if (m.Msg == 0x0312 && m.WParam.ToInt32() == 1)
                {

                    toggleClicker(); //This turns my autoclicker off and on
                }
                base.WndProc(ref m);
    }
    public Form1(){
                InitializeComponent();
                /* Ignore this:
                VersionText.Text = "Version " + version;
                comboBox1.SelectedIndex = 0;
                */
                RegisterHotKey(this.Handle, 1, 0x0002, (int)Keys.P); //This is the default and it works just fine
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
                UnregisterHotKey(this.Handle, 1);
    }
这是用户选择所需密钥的代码

    private void button2_Click(object sender, EventArgs e)
    {
        /*Ignore this
        if (isClickerRunning)
        {
            //Console.WriteLine("Stopping...");
            clickerThread.Abort();
            isClickerRunning = false;
        }
        */
        int Prefix = 0;
        //Set Prefix to the value chosen in the combobox
        if (comboBox1.SelectedIndex == 1) { Prefix = 0x0002; } //Ctrl
        if (comboBox1.SelectedIndex == 2) { Prefix = 0x0004; } //Shift
        if (comboBox1.SelectedIndex == 3) { Prefix = 0x0001; } //Alt
        if (comboBox1.SelectedIndex == 4) { Prefix = 0x0002 + 0x0004; } //Ctrl + Shift
        if (comboBox1.SelectedIndex == 5) { Prefix = 0x0002 + 0x0001; } //Ctrl + Alt
        if (comboBox1.SelectedIndex == 6) { Prefix = 0x0002 + 0x0001 + 0x0004; } //Ctrl + Alt + Shift


        bool Success1 = UnregisterHotKey(this.Handle, 1);
        bool Success2 = RegisterHotKey(this.Handle, 1, prefix, (int)KeyCharacter); //KeyCharacter is the key that the user has selected
        //Test if RegisterHotKey and UnregisterHotKey failed
        if(Success1 == false || Success2 == false)
        {
            //Set the hotkey back to default if it failed
            Success1 = UnregisterHotKey(this.Handle, 1);
            Success2 = RegisterHotKey(this.Handle, 1, 0x0002, (int)Keys.P);
        }

        //Test if it failed again
        if(Success1 == false || Success2 == false)
        {
            MessageBox.Show("FATAL ERROR!\nCould not register hotkey. Quiting...", "FATAL ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            Application.Exit();
        }
    }
程序启动时,我有一个默认热键CTL+p设置 默认热键工作正常,但当我在热键选择文本框中键入/之类的键并通过单击按钮进行设置时,默认热键将停止工作,但当我按下热键时,我只是将其设置为无效。但它在资本A等方面运作良好

基本上,我要问的是如何将~转换为0xC0或/转换为0xDC

非常感谢您的帮助

您需要使用VkKeyScan Win32 API函数来获取角色的虚拟密钥代码

在您的情况下,您将在调用RegisterHotKey之前,使用KeyCharacter调用下面的VirtualKeyCodeFromChar函数

实际上,使用该功能更好,因为键盘布局不同,因此OEM键可能会因布局不同而为同一字符生成不同的键代码。但是我会让你自己去探索如何使用这个函数。同时

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

namespace ConsoleApp1
{
    class Program
    {
        [DllImport("user32.dll")] static extern short VkKeyScan(char c);

        static void Main(string[] args)
        {
            var s = "~|-.";
            foreach(var c in s)
            {
                var key = VirtualKeyCodeFromChar(c);
                Console.WriteLine($"{c}, {key}, 0x{key:X}\n");
            }

            Console.ReadKey();
        }

        static int VirtualKeyCodeFromChar(char c)
        {
            var composite = VkKeyScan(c);

            byte keyCode = (byte)(composite & 255);
            byte shiftState = (byte)((composite >> 8) & 255);

            Keys key = (Keys)keyCode;

            if ((shiftState & 1) != 0) key |= Keys.Shift;
            if ((shiftState & 2) != 0) key |= Keys.Control;
            if ((shiftState & 4) != 0) key |= Keys.Alt;

            return (int)key;
        }
    }
}

它们是很棘手的钥匙,因为它们不一定有专用钥匙。0xC0是美国键盘上的VK_OEM_3反斜线或平铺线,0xDC是美国键盘上的VK_OEM_5反斜线或竖线。OEM表示制造商可以省略它们或将它们放在他喜欢的任何地方。正如在国外布局上通常所做的那样。我想你实际上想要0xBC VK_OEM_减号得到破折号,0xBF VK_OEM_2得到斜线。这是一个非常好的理由,不使用它们作为热键。