wpf 虚拟键盘 对外部程序

对外部程序,以记事本为例,xaml中设置模拟按键的控件 Focusable="False":

/// <summary>
        /// 发送按键
        /// </summary>
        /// <param name="asiiCode">键盘ascii码</param>
        private void SendKey(byte asiiCode)
        {
            try
            {
                int getFocus = 0;
                AttachThreadInput(true, ref getFocus);
                Win32API.SetForegroundWindow((IntPtr)getFocus);

                Win32API.Keybd_event(asiiCode, 0x45, 0x1 | 0, 0);//keydowm
                Win32API.Keybd_event(asiiCode, 0x45, 0x1 | 0x2, 0);//keyup
                AttachThreadInput(false, ref getFocus); //取消线程亲和的关联
            }
            catch (Exception ex)
            {
                MessageBox.Show("SendKey:" + ex.ToString());
            }
        }


/// <summary>
        /// 设置线程亲和,附到前台窗口所在线程,只有在线程内才可以获取线程内控件的焦点
        /// </summary>
        /// <param name="b">是否亲和</param>
        private void AttachThreadInput(bool b,ref int hwnd)
        {
            try
            {
                Process[] processes = Process.GetProcessesByName("notepad");
                if (processes.Length == 0)
                {
                    return;
                }
                int processId = processes[0].Id;
                hwnd = processes[0].MainWindowHandle.ToInt32();
                
                Win32API.AttachThreadInput(
                       processId,
                       Win32API.GetCurrentThreadId(), Convert.ToInt32(b));
            }
            catch (Exception ex)
            {
                MessageBox.Show("AttachThreadInput:" + ex.ToString());
            }
        }

对内部窗口(可引用该虚拟键盘组件的),不用考虑焦点问题(焦点在哪就在哪输出),做好Keybd_event就行了

不推荐SendMessage、PostMessage等方法发送按键,实在不行推荐使用SendWait

以上相关底层调用方法:

        [DllImport("user32.dll", EntryPoint = "keybd_event")]
        public static extern void Keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);


        [DllImport("user32.dll")]
        public static extern int AttachThreadInput(
             int idAttach,
             int idAttachTo,
             int fAttach);


        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();


        [DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

 

posted @ 2018-08-14 13:54  dyfisgod  阅读(265)  评论(0编辑  收藏  举报