网上的文章大多千篇一律,第一次来简书,就先记录一下自己用C++模拟键盘发送命令时遇到的坑。
最近在银行做as400的开发,用的5250仿真器比我的年龄还要大,实在是用的无比蛋疼。明明IBM有更好用的基于eclipse制作的Rational Developer for i不用,大概是为了省钱吧(ง •̀_•́)ง。没有办法,只能自己动手,丰衣足食了,打算自己实现一个5250开发助手。
目前第一个要实现的功能是先添加滚轮上下翻页的功能(没错这个古老的编辑器是不提供滚轮翻页的),考虑到以后可能会有直接操控内存的操作,所以此次开发语言选型是c++,因为5250要连接公司开发主机才能使用,所以只能在办公电脑进行开发,不能将代码开源到github上面去了。
长话短说,思路很简单,用全局钩子监控鼠标的滚轮操作,然后判断当前句柄是不是5250窗口的句柄,若是的话,将滚轮操作映射为上下翻页键。
在这里遇到了两个坑,一个是如何捕获到滚轮的上下操作信号,一个是模拟page down,page up的按键发送,这两个在网上的资料好像都已经过时了。
捕获鼠标信号自然是用的钩子,关于如何使用,这个博文已经讲的很清楚了:Windows事件监控
这篇博文只讲了如何捕获监控鼠标,但是没讲怎么区分滚轮向前,向后操作,网上的教程大多数都是取wParam的高16位,然而在实际使用当中发现并不靠谱,要通过
LPMSLLHOOKSTRUCT p = (LPMSLLHOOKSTRUCT)lParam;
POINT pt = p->pt;
DWORD mouseData = p->mouseData;
short mouseM = (short) HIWORD(mouseData);
即获取这个mouseData的高16位才能获取的到,向上是120,向下是-120。
另外一个坑就是,如何发送page down,page up这两个按键了。网上通用的是使用sendInput函数,比如这样:
INPUT input = {0};
//VK_PRIOR是page up的虚拟按键
input.ki.wWk = VK_PRIOR;
//表示按键为扩展按键
input.ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
//表示是键盘输入
input.type = INPUT_KEYBOARD;
//获取page up的扫描码,加了扫描码可以模拟驱动级输入。
input.ki.wScan = MapVirtualKey(VK_PRIOR,0);
SendInput(1, &input, sizeof(INPUT));
//表示按键松开,这个值默认为KEYEVENTF_DOWN
input.ki.dwFlags = KEYEVENTF_UP;
SendInput(1, &input, sizeof(INPUT));
KEY | MAKE | BREAK |
---|---|---|
PG UP | E0,7D | E0,F0,7D |
PG DN | E0,7A | E0,F0,7A |
问题就出在下面这一行:
input.ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
基本上我查到的所有的例子中都没有这一行,导致我输入的扫描码被认为是小键盘是page down和page up,只能关掉小键盘才能使用,这样人十分的郁闷,在多方查询之后,我发现一些功能键前面要加e0,比如:
KEY | MAKE | BREAK |
---|---|---|
PG UP | E0,7D | E0,F0,7D |
PG DN | E0,7A | E0,F0,7A |
然而如何才能同时输入两个扫描码呢,经过查询得知,就需要这一条语句,下面贴上地址,诸位想看的就自己去看吧 INPUT structure。
至此,5250开发助手的第一个功能宣告成功。
PS:简书的md表格似乎有bug,写出来会出现两个表格,凑活着看吧,第一次体验感觉并不满意。
网友评论