SendMessage、PostMessage、keybd_event 发送键盘事件 及 虚拟键码表

大致介绍

  • SendMessage 与 PostMessage

  两者从函数结构上看主要区别其实就是返回值不同,SendMessage返回消息被处理后的返回值,而PostMessage则返回消息是否发送成功。

  其次,SendMessage是同步的,而PostMessage是异步的。SendMessage会等待消息被处理完成之后再返回,PostMessage则会将消息放入处理队列中直接返回。另外,再不同线程操作时,最好用PostThreadMessage代替。

  • keybd_event

  Windows提供的一个模拟键盘API函数,该函数能触发一个按键事件,也就是说同样会产生一个WM_KEYDOWN或WM_KEYUP消息。

  • SendKey

  需要 using System.Windows.Forms;功能是 将一个或多个按键消息发送到活动窗口,就如同在键盘上进行输入一样。其中一些字符都有特殊意义,

  语法:SendKeys.Send(string keys);SendKeys.SendWait(string keys);

几个主要函数

  首先,我们来看一下直接点击 Ctrl + S 在 Spy++ 上显示出的命令:SendMessage、PostMessage、keybd_event 发送键盘事件 及 虚拟键码表_第1张图片

  下面介绍几个需要用到的函数,代码在下面已贴出。

  • SendMessage : 发送指定的消息到目标窗口。

   parm1:接收窗口的句柄

   parm2:发送的消息,根据不同的需求和不同的对象,需要填入不同的实参。我们在模拟用户操作时,需要填入 WindowMessage参数(下面代码中有给出)。

   parm3:附加的消息信息,对parm2的补充。这边我们应该填入 键盘操作的虚拟键值(键值表下面有给出)。

   parm4:附加的消息信息,对parm2的补充。此处我们需要填入一个32位的uint参数,具体的定义如下:

0~15位:表示发送的次数,一般就是1次

16~23位:表示键盘的操作的扫描码

24位:表示是左ALT、CTRL还是右ALT、CTRL(通常为0)

25~28位:保留

29位:决定了 消息内容中 fAltDown 的值为1还是0(不知道有什么用…)

30位:表示上一个键的状态KEY DOWN or UP,1为发送前的DOWN状态,0为UP

31位:0为按下,1为释放SendMessage、PostMessage、keybd_event 发送键盘事件 及 虚拟键码表_第2张图片
上图是通过 SendMessage 函数发送相应数据得到的结果。经过对比,spy++确实捕捉到了Ctrl + S 的键盘事件,然而,现象却是,钩子函数没有捕捉到… 很尴尬。(希望有懂的同志能交流下)

  • keybd_event : 模拟键盘事件,向当前活动窗口发送案件信息。

   parm1:键盘虚拟键值

   parm2:键盘键值扫描码(试过之后发现,填0也可以,根本不需要这个值)

   parm3:状态参数:非 KEYEVENTF_KEYUP 即 按下

   parm3:扩展信息(0)
SendMessage、PostMessage、keybd_event 发送键盘事件 及 虚拟键码表_第3张图片
上图为 keybd_event 的结果,可以看到,钩子函数捕捉到了!然鹅,spy++捕捉到的键盘事件却和真实点击出现的事件不完全相同。也就是,用了奇怪的方法却完成了需求… 依旧尴尬。

  • FindWindow : 获取某窗口句柄,parm1:窗口类名(null),parm2:窗口关键字

  • FindWindowEx :获取某窗口下的子窗口句柄,可以用 spy++ 获取到子窗口的类名SendMessage、PostMessage、keybd_event 发送键盘事件 及 虚拟键码表_第4张图片

  • SetForegroundWindow :设置某窗口为当前活动窗口

  • GetForegroundWindow : 获取当前活动窗口

  • ShowWindow :设置窗口,parm2:0:close, 1:normal, 2:min, 3:max

代码

using System.Runtime.InteropServices;

    class Program
    {
        [DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
        private extern static IntPtr FindWindow(string classname, string captionName);

        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("user32.dll")]
        private static extern int SendMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam);

        [DllImport("user32.dll", EntryPoint = "PostMessage")]
        public static extern bool PostMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);

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

        #region 预定义参数

        #endregion
        // 键盘虚拟键值
        private const int VK_CONTROL = 0X11;
        private const int VK_MENU = 0X12;
        private const int VK_S = 0X53;          // 'S'
        private const int VK_F4 = 0X73;

        private const int KEYEVENTF_EXTENDEDKEY = 0x1;
        private const int KEYEVENTF_KEYUP = 0x2;

        // WindowMessage 参数
        private const int WM_KEYDOWN = 0X100;
        private const int WM_KEYUP = 0X101;
        private const int WM_SYSCHAR = 0X106;
        private const int WM_SYSKEYUP = 0X105;
        private const int WM_SYSKEYDOWN = 0X104;
        private const int WM_CHAR = 0X102;
        private const int WM_DOWN = 0X0028;
        private const int WM_ENTER = 0X000D;
        private const int WM_CLOSE = 0X0010;
        private const int WM_QUIT = 0X0012;

        // keybd_event 状态参数
        public const int WM_SYSCOMMAND = 0x111;
        public const int SC_MINIMIZE = 0xF020;
        public const int SC_MAXIMIZE = 0xF030;

        static void SendMsg(IntPtr hwnd)
        {
            //hwnd = FindWindowEx(hwnd, IntPtr.Zero, "ToolbarWindow32", "");        // 获取子面板的窗口句柄
            Console.WriteLine("进程句柄:    " + hwnd);

            Console.WriteLine("Message : " + PostMessage(hwnd, WM_KEYDOWN, VK_CONTROL, 0x001D0001));                 // Ctrl + S
            Console.WriteLine("Message : " + PostMessage(hwnd, WM_KEYDOWN, VK_S, 0x001F0001));
            Console.WriteLine("Message : " + PostMessage(hwnd, WM_CHAR, 0x13, 0x001F0001));
            Console.WriteLine("Message : " + PostMessage(hwnd, WM_KEYUP, VK_CONTROL, 0xC01D0001));
            Console.WriteLine("Message : " + PostMessage(hwnd, WM_KEYUP, VK_S, 0xC01F0001));

            //Console.WriteLine("Message : " + PostMessage(hwnd, WM_SYSKEYDOWN, VK_MENU, 0x20380001));                 // Alt + F4
            //Console.WriteLine("Message : " + PostMessage(hwnd, WM_SYSKEYDOWN, VK_F4, 0x203E0001));
            //Console.WriteLine("Message : " + PostMessage(hwnd, WM_KEYUP, VK_MENU, 0xE0380001));
            //Console.WriteLine("Message : " + PostMessage(hwnd, WM_KEYUP, VK_F4, 0xE03E0001));
        }

        static void Keybd_event_Msg()
        {
            keybd_event(VK_CONTROL, 0, 0, 0);                   // Ctrl + S
            keybd_event(VK_S, 0, 0, 0);
            keybd_event(VK_S, 0, KEYEVENTF_KEYUP, 0);
            keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);

            //keybd_event(VK_MENU, 0, 0, 0);                   // Alt + F4
            //keybd_event(VK_F4, 0, 0, 0);
            //keybd_event(VK_F4, 0, KEYEVENTF_KEYUP, 0);
            //keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
        }

        static void Main()
        {
            IntPtr mwh1 = IntPtr.Zero;

            while (mwh1 == IntPtr.Zero)
            {
                Console.WriteLine("寻找窗口中...");

                mwh1 = FindWindow(null, "HookReceiverWpf");

                Thread.Sleep(1000);
            }

            //SendMsg(mwh1);
            SetForegroundWindow(mwh1);
            Keybd_event_Msg();

            //System.Windows.Forms.SendKeys

            Console.ReadKey();
        }
    }

虚拟键值表

虚拟键 十六进制值 十进制值 相应键盘或鼠标键
VK_LBUTTON 1 1 鼠标左键
VK_RBUTTON 2 2 鼠标右键
VK_CANCEL 3 3 Ctrl-Break键
VK_MBUTTON 4 4 鼠标中键
VK_BACK 8 8 Backspace键
VK_TAB 9 9 Tab键
VK_CLEAR 0C 12 Clear键
VK_RETURN 0D 13 Enter键
VK_SHIFT 10 16 Shift键
VK_CONTROL 11 17 Ctrl键
VK_MENU 12 18 Alt键
VK_PAUSE 13 19 Pause键
VK_CAPITAL 14 20 Caps Lock键
VK_ESCAPE 1B 27 Esc键
VK_SPACE 20 32 Space键
VK_PRIOR 21 33 Page Up键
VK_NEXT 22 34 Page Down键
VK_END 23 35 End键
VK_HOME 24 36 Home键
VK_LEFT 25 37 ←键
VK_UP 26 38 ↑键
VK_RIGHT 27 39 →键
VK_DOWN 28 40 ↓键
VK_SELECT 29 41 Select键
VK_PRINT 2A 42 Print键
VK_EXECUTE 2B 43 Execute键
VK_SNAPSHOT 2C 44 Print Screen键
VK_INSERT 2D 45 Ins键
VK_DELETE 2E 46 Del键
VK_HELP 2F 47 Help键
VK_0 30 48 0键
VK_1 31 49 1键
VK_2 32 50 2键
VK_3 33 51 3键
VK_4 34 52 4键
VK_5 35 53 5键
VK_6 36 54 6键
VK_7 37 55 7键
VK_8 38 56 8键
VK_9 39 57 9键
VK_A 41 65 A键
VK_B 42 66 B键
VK_C 43 67 C键
VK_D 44 68 D键
VK_E 45 69 E键
VK_F 46 70 F键
VK_G 47 71 G键
VK_H 48 72 H键
VK_I 49 73 I键
VK_J 4A 74 J键
VK_K 4B 75 K键
VK_L 4C 76 L键
VK_M 4D 77 M键
VK_N 4E 78 N键
VK_O 4F 79 O键
VK_P 50 80 P键
VK_Q 51 81 Q键
VK_R 52 82 R键
VK_S 53 83 S键
VK_T 54 84 T键
VK_U 55 85 U键
VK_V 56 86 V键
VK_W 57 87 W键
VK_X 58 88 X键
VK_Y 59 89 Y键
VK_Z 5A 90 Z键
VK_LWIN 5B 91 左Windows键
VK_RWIN 5C 92 右Windows键
VK_APPS 5D 93 应用程序键
VK_SLEEP 5F 95 休眠键
VK_NUMPAD0 60 96 小数字键盘0键
VK_NUMPAD1 61 97 小数字键盘1键
VK_NUMPAD2 62 98 小数字键盘2键
VK_NUMPAD3 63 99 小数字键盘3键
VK_NUMPAD4 64 100 小数字键盘4键
VK_NUMPAD5 65 101 小数字键盘5键
VK_NUMPAD6 66 102 小数字键盘6键
VK_NUMPAD7 67 103 小数字键盘7键
VK_NUMPAD8 68 104 小数字键盘8键
VK_NUMPAD9 69 105 小数字键盘9键
VK_MULTIPLY 6A 106 乘号键
VK_ADD 6B 107 加号键
VK_SEPARATOR 6C 108 分割键
VK_SUBSTRACT 6D 109 减号键
VK_DECIMAL 6E 110 小数点键
VK_DIVIDE 6F 111 除号键
VK_F1 70 12 F1键
VK_F2 71 113 F2键
VK_F3 72 114 F3键
VK_F4 73 115 F4键
VK_F5 74 116 F5键
VK_F6 75 117 F6键
VK_F7 76 118 F7键
VK_F8 77 119 F8键
VK_F9 78 120 F9键
VK_F10 79 121 F10键
VK_F11 7A 122 F11键
VK_F12 7B 123 F12键
VK_F13 7C 124 F13键
VK_F14 7D 125 F14键
VK_F15 7E 126 F15键
VK_F16 7F 127 F16键
VK_F17 80 128 F17键
VK_F18 81 129 F18键
VK_F19 82 130 F19键
VK_F20 83 131 F20键
VK_F21 84 132 F21键
VK_F22 85 133 F22键
VK_F23 86 134 F23键
VK_F24 87 135 F24键
VK_NUMLOCK 90 144 Num Lock键
VK_SCROLL 91 45 Scroll Lock键
VK_LSHIFT A0 160 左Shift键
VK_RSHIFT A1 161 右Shift键
VK_LCONTROL A2 162 左Ctrl键
VK_RCONTROL A3 163 右Ctrl键
VK_LMENU A4 164 左Alt键
VK_RMENU A5 165 右Alt键

最后附上 Spy++ 的链接: https://pan.baidu.com/s/1D3E4N3mRRVwW24i1PonbnA 提取码:azga

你可能感兴趣的:(C#,SendMessage,keybd_event,发送键盘事件)