最近软件有个需求:从软件中点击按钮实现外部 wps 或 office 打开的 ppt 翻页功能。软件可以得到 ppt 窗口的句柄,因此可以向窗口发送按键消息实现ppt翻页。
总结:
使用::PostMessage
::PostMessage(hWnd, WM_KEYDOWN, MAKEWPARAM(VK_LEFT, 0), NULL);
::PostMessage(hWnd, WM_KEYUP, MAKEWPARAM(VK_LEFT, 0), NULL);
补充:
以上方法在win7系统上测试正常,但在win10上测试不正常,win10下窗口可以收到发送的键盘消息但是不处理。后来发送消息之前用setforegroundwindow(hWnd)把窗口置顶激活了就处理正常了,但是这样把ppt置顶又不符合软件要求。
再后来又尝试发送WM_LBUTTONDOWN鼠标消息窗口发现可以正常处理。
这样可以猜测win10键盘消息不处理可能是因为窗口没有处于激活状态吧。但是使用了setcapture setfocus setactivewindow等方法使窗口获取焦点都不管用,不知道为啥。
走的弯路:
开始测试时使用wps打开ppt,使用sendmessage可以实现翻页功能。
::SendMessage(hWnd, WM_KEYDOWN, MAKEWPARAM(VK_LEFT, 0), NULL);
::SendMessage(hWnd, WM_KEYUP, MAKEWPARAM(VK_LEFT, 0), NULL);
但是用office打开ppt后测试发现不能正常翻页,使用spy++(64位)(64位程序必须使用64位的spy++,不然捕获不到消息)捕获消息如下图。
框选 1 部分是office ppt正常按下 → 键时捕获到的消息,框选 2 部分是自己的软件发送消息时窗口捕获到的消息。
一开始时不知道前面的P/S/R字母代表什么意思,以为是后面的cRepeat ScanCode等参数不同造成的,参考了https://blog.csdn.net/plutus_sutulp/article/details/17488515 使用以下代码将参数变成了和正常按键参数一模一样,除了前面的P/S/R字母,可是还是不行。
::SendMessage(hWnd, WM_KEYDOWN, VK_RIGHT, 0x1 | ((KF_EXTENDED | MapVirtualKey(VK_RIGHT, MAPVK_VK_TO_VSC)) << 16));
::SendMessage(hWnd, WM_KEYUP, VK_RIGHT, 0x1 | ((KF_EXTENDED | KF_REPEAT | KF_UP | MapVirtualKey(VK_RIGHT, MAPVK_VK_TO_VSC)) << 16));
然后注意到参考里面用的是PostMessage,试了一下office也终于可以正常翻页了。在wps打开ppt的情况的使用PostMessage也可以正常翻页。
想了一下 P/S/R 应该是代表 PostMessage/SendMessage/Return 吧。