是否可以在C#中捕获键控事件并随后取消此事件?

是否可以在C#中捕获键控事件并随后取消此事件?,c#,winapi,keyboard-events,C#,Winapi,Keyboard Events,我想把拉丁键盘翻译成另一种键盘,比如维语或类似的语言。有一个维语键盘,但按键的编码是如此复杂,以至于普通的PC用户无法轻松地键入维语 所以我的目标是为这个问题创建一个软件解决方案,比如中文输入系统。在这个系统中,你可以从各种键盘输入汉字。这是一种聪明的解决方案,这样每个人都可以少用它来解决问题 因此,我的目标是编写一个Windows服务应用程序,它捕获每个按键敲击(仅字母表)并将按下的键转换为目标(Unicode)字母表,然后使用此转换的字母表再次模拟按键敲击。因此,目标字母表将显示在光标点上。

我想把拉丁键盘翻译成另一种键盘,比如维语或类似的语言。有一个维语键盘,但按键的编码是如此复杂,以至于普通的PC用户无法轻松地键入维语

所以我的目标是为这个问题创建一个软件解决方案,比如中文输入系统。在这个系统中,你可以从各种键盘输入汉字。这是一种聪明的解决方案,这样每个人都可以少用它来解决问题

因此,我的目标是编写一个Windows服务应用程序,它捕获每个按键敲击(仅字母表)并将按下的键转换为目标(Unicode)字母表,然后使用此转换的字母表再次模拟按键敲击。因此,目标字母表将显示在光标点上。最后,我的应用程序会放弃/停止按下向下键的原始键

这样就不会再出现了

例如:

  • 按K
  • 捕获K并将其转换为Unicode格式,如
    0xFEBD
    ,然后发送回光标点
  • 取消或放弃K的键向下事件。在光标点不应看到此字符
  • 到目前为止,第1步和第2步工作正常。我的问题是,在我捕获按键按下事件后,我无法放弃/取消/停止此按键按下事件的最后一个按键按下事件

    我不确定我的想法是否足够好/有效以实现我的想法。现在我只是在努力。也许你有个更好的主意,可以向我推荐。以下是我的代码:

    public class Simulate
    {
        [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
        static extern UInt32 SendInput(UInt32 numberOfInputs, INPUT[] input, Int32 sizeOfInputStructure);
    
        [StructLayout(LayoutKind.Sequential, Size = 24)]
        struct KEYBDINPUT
        {
            public UInt16 Vk;
            public UInt16 Scan;
            public UInt32 Flags;
            public UInt32 Time;
            public UInt32 ExtraInfo;
        }
    
        [StructLayout(LayoutKind.Explicit)]
        private struct INPUT
        {
            [FieldOffset(0)]
            public int Type;
            [FieldOffset(4)]
            public KEYBDINPUT ki;
        }
        public static void UnicodeInput(UInt16 unicode)
        { 
                INPUT down = new INPUT();
                down.Type = 1; //INPUT_KEYBOARD
                down.ki.Vk = 0;
                down.ki.Scan = unicode;
                down.ki.Time = 0;
                down.ki.Flags = 0x0004; //KEYEVENTF_UNICODE
                down.ki.ExtraInfo = 0;
    
                INPUT up = new INPUT();
                up.Type = 1; //INPUT_KEYBOARD
                up.ki.Vk = 0;
                up.ki.Scan = unicode;
                up.ki.Time = 0;
                up.ki.Flags = 0x0004; //KEYEVENTF_UNICODE
                up.ki.ExtraInfo = 0;
    
                INPUT[] input = new INPUT[2];
                input[0] = down;
                input[1] = up;
                SendInput(1, input, Marshal.SizeOf(typeof(INPUT))); 
        }
    
    }    
    
    /// Capture any window key
    /// 
    public static class WinKeyCapture
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WH_CALLWNDPROC = 4;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_CHAR = 0x0102;
        const int VK_A = 0x08;// 0x41; //up key
        const int VK_DOWN = 0x28;  //down key
        const int VK_LEFT = 0x25;
        const int VK_RIGHT = 0x27;
        const uint KEYEVENTF_KEYUP = 0x0002;
        const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
    
        const uint KEYEVENTF_CTRL = 0x11;
        const uint KEYEVENTF_ADD = 0x6B;
        const uint VK_LWIN = 0x5b;
        private static LowLevelKeyboardProc _proc = WinKeyCapture.HookCallback; 
        [DllImport("user32.dll")]
        public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
        [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);
        [DllImport("user32.dll", SetLastError = true)]
        private static extern uint SendInput(uint numberOfInputs, INPUT[] inputs, int sizeOfInputStructure);
    
        public static void SetHook()
        {
    
            SetHook(_proc);
        }
    
        public static void UnHook()
        {
            UnhookWindowsHookEx(_hookID);
        }
    
        private static 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 static IntPtr _hookID = IntPtr.Zero;       
    
        public static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            int vkCode = Marshal.ReadInt32(lParam); 
    
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) 
            {         
                // TODO: identify only Alphabets then fire     
               VKcode(vkCode);                  
            }
            //wParam |=   0x4000;
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
    
        private static void VKcode(int code)
        { 
            switch (code) // TODO: Complete all other Alphabet-Tranylations
            {  
                case 0x4B:
                     Simulate.UnicodeInput(0xFEDB);
                    break;  
                case 0x54:
                      Simulate.UnicodeInput(0xFEAD);
                    break;
                case 0x55:
                     Simulate.UnicodeInput(0xFBE7);
                    break;
                case 0x56:    
                     Simulate.UnicodeInput(0xFEE9); 
    
                    break;
                case 0x59:
                    Simulate.UnicodeInput(0xFEE1);
                    break;
                case 0x5a: 
                    break; 
            }  
        }        
    
    
        /// <summary>
        /// simulate key press
        /// </summary>
        /// <param name="keyCode"></param>
        public static void SendKeyPress(KeyCode keyCode)
        {
            INPUT input = new INPUT {
                Type = 1
            };
            input.Data.Keyboard = new KEYBDINPUT() {
                Vk = (ushort)keyCode,
                Scan = 0,
                Flags = 0,
                Time = 0,
                ExtraInfo = IntPtr.Zero,
            };
    
            INPUT input2 = new INPUT {
                Type = 1
            };
            input2.Data.Keyboard = new KEYBDINPUT() {
                Vk = (ushort)keyCode,
                Scan = 0,
                Flags = 2,
                Time = 0,
                ExtraInfo = IntPtr.Zero
            };
            INPUT[] inputs = new INPUT[] { input, input2 };
            if (SendInput(2, inputs, Marshal.SizeOf(typeof(INPUT))) == 0)
                throw new Exception();            
        } 
            /// <summary>
        /// simulate key press
        /// </summary>
        /// <param name="keyCode"></param>
        public static void SendUnicodePress(KeyCode keyCode)
        {
            INPUT input = new INPUT {
                Type = 1
            };
            input.Data.Keyboard = new KEYBDINPUT() {
                Vk = (ushort)keyCode,
                Scan = 0,
                Flags = 0,
                Time = 0,
                ExtraInfo = IntPtr.Zero,
            };
    
            INPUT input2 = new INPUT {
                Type = 1
            };
            input2.Data.Keyboard = new KEYBDINPUT() {
                Vk = (ushort)keyCode,
                Scan = 0,
                Flags = 2,
                Time = 0,
                ExtraInfo = IntPtr.Zero
            };
            INPUT[] inputs = new INPUT[] { input, input2 };
            if (SendInput(2, inputs, Marshal.SizeOf(typeof(INPUT))) == 0)
                throw new Exception();            
        } 
        [StructLayout(LayoutKind.Sequential)]
        internal struct INPUT
        {
            public uint Type;
            public MOUSEKEYBDHARDWAREINPUT Data;
        } 
        [StructLayout(LayoutKind.Explicit)]
        internal struct MOUSEKEYBDHARDWAREINPUT
        {
            [FieldOffset(0)]
            public HARDWAREINPUT Hardware;
            [FieldOffset(0)]
            public KEYBDINPUT Keyboard;
            [FieldOffset(0)]
            public MOUSEINPUT Mouse;
        }
        [StructLayout(LayoutKind.Sequential)]
        internal struct HARDWAREINPUT
        {
            public uint Msg;
            public ushort ParamL;
            public ushort ParamH;
        } 
        [StructLayout(LayoutKind.Sequential)]
        internal struct KEYBDINPUT
        {
            public ushort Vk;
            public ushort Scan;
            public uint Flags;
            public uint Time;
            public IntPtr ExtraInfo;
        } 
        [StructLayout(LayoutKind.Sequential)]
        internal struct MOUSEINPUT
        {
            public int X;
            public int Y;
            public uint MouseData;
            public uint Flags;
            public uint Time;
            public IntPtr ExtraInfo;
        }
    }
    
    公共类模拟
    {
    [DllImport(“USER32.DLL”,CharSet=CharSet.Unicode)]
    静态外部UInt32 SendInput(UInt32 numberOfInputs,INPUT[]INPUT,Int32 SizeOfInput结构);
    [StructLayout(LayoutKind.Sequential,Size=24)]
    结构键输入
    {
    公共UInt16 Vk;
    公共UInt16扫描;
    32面国旗;
    公共UInt32次;
    公共UInt32外部信息;
    }
    [StructLayout(LayoutKind.Explicit)]
    私有结构输入
    {
    [字段偏移量(0)]
    公共int类型;
    [现场偏移(4)]
    公钥输入;
    }
    公共静态输入(UInt16 unicode)
    { 
    输入向下=新输入();
    down.Type=1;//输入键盘
    down.ki.Vk=0;
    down.ki.Scan=unicode;
    down.ki.Time=0;
    down.ki.Flags=0x0004;//KEYEVENTF\u UNICODE
    down.ki.ExtraInfo=0;
    向上输入=新输入();
    up.Type=1;//输入键盘
    up.ki.Vk=0;
    up.ki.Scan=unicode;
    up.ki.Time=0;
    up.ki.Flags=0x0004;//KEYEVENTF\u UNICODE
    up.ki.ExtraInfo=0;
    输入[]输入=新输入[2];
    输入[0]=向下;
    输入[1]=向上;
    SendInput(1,input,封送处理大小(typeof(input)));
    }
    }    
    ///捕获任何窗口键
    /// 
    公共静态类WinKeyCapture
    {
    专用常量int WH_键盘LL=13;
    私有常量int WH_CALLWNDPROC=4;
    私有常量int WM_KEYDOWN=0x0100;
    私有常量int WM_CHAR=0x0102;
    常量int VK_A=0x08;//0x41;//向上键
    const int VK_DOWN=0x28;//向下键
    const int VK_LEFT=0x25;
    常数int VK_RIGHT=0x27;
    consuint keyevent fu KEYUP=0x0002;
    const uint keyevent f_EXTENDEDKEY=0x0001;
    consuint keyevent f_CTRL=0x11;
    consuint keyevent f_ADD=0x6B;
    常数VK_LWIN=0x5b;
    私有静态低层KeyboardProc_proc=WinKeyCapture.HookCallback;
    [DllImport(“user32.dll”)]
    公共静态外部无效keybd_事件(字节bVk、字节bScan、uint dwFlags、uint dwExtraInfo);
    [DllImport(“user32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
    私有静态外部IntPtr SetWindowsHookEx(int idHook,
    低级键盘程序lpfn、IntPtr hMod、uint dwThreadId);
    [DllImport(“user32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
    [返回:Marshallas(UnmanagedType.Bool)]
    私有静态外部bool unhookwindowshookx(IntPtr hhk);
    [DllImport(“user32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
    私有静态外部IntPtr CallNextHookEx(IntPtr hhk,intncode,
    IntPtr wParam、IntPtr lParam);
    [DllImport(“kernel32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
    私有静态外部IntPtr GetModuleHandle(字符串lpModuleName);
    [DllImport(“user32.dll”,SetLastError=true)]
    私有静态外部uint SendInput(uint numberOfInputs、INPUT[]inputs、int SIZEOFINPUT结构);
    公共静态void SetHook()
    {
    SetHook(_proc);
    }
    公共静态void UnHook()
    {
    unhookwindowshookx(_hookID);
    }
    专用静态IntPtr SetHook(低级键盘程序)
    {
    使用(Process curProcess=Process.GetCurrentProcess())
    使用(ProcessModule curModule=curProcess.MainModule)
    { 
    返回SetWindowsHookEx(WH\u KEYBOARD\u LL,proc,GetModuleHandle(curModule.ModuleName),0);
    }
    }
    私有静态IntPtr _hookID=IntPtr.Zero;
    公共静态IntPtr HookCallback(intncode、IntPtr wParam、IntPtr lParam)
    {
    int vkCode=Marshal.ReadInt32(LPRAM);
    如果(nCode>=0&&wParam==(IntPtr)WM\u KEYDOWN)
    {         
    //待办事项:只识别字母,然后开火
    VKcode(VKcode);
    }
    //wParam |=0x4000;
    返回CallNextHookEx(_hookID,nCode,wParam,lParam);
    }
    私有静态void VKcode(int代码)
    { 
    开关(代码)//TODO:完成所有其他字母转换
    {  
    案例0x4B:
    模拟输入(0xFEDB);
    打破
    案例0x54:
    模拟单输入(0xFEAD);
    打破
    案例0x55:
    模拟输入(0xFBE7);
    布雷亚