Windows虚拟键盘开发日志(一)

一直想在win平板上玩各种经典的游戏,比如什么《金庸群侠传》呀之类的。但是苦于平板没有键盘,系统自带的虚拟键盘并不能好好地玩游戏,于是就有了自己做一个虚拟键盘的想法。

之前尝试过用简单的winform来开发,因为游戏大多数使用DirectInput,直接与硬件驱动打交道,会绕过系统的事件机制,因此普通的按键事件并不能传送到游戏里面,后来看到了这个文章:
http://www.cnblogs.com/Loofah/p/4167615.html
知道了winio这个第三方库,决定学习一下。
(但是这个库有一个很大的缺陷,后面会说到)

这篇日志也便是一个开始。也是这个blog的第一篇文章,日后会将csdn上的一些小小的文章都搬运过来。希望这个项目有出头的一天。


 

注意:WinIo32.dll或者WinIo64.dll并不能在引用中直接浏览添加,因为这两个dll并不是.net的dll,会提示以下错误:

QQ截图20160406220306

一开始我还以为是VS的版本问题,还专门下载了VS2010,结果发现并不是这个问题,我使用VS2015没有任何问题。

至于网上说到的InitializeWinio()这个函数会总返回false的问题,一个是签名的问题,需要注意,这个网上说了很多,另外一个需要注意的是要用管理员身份打开Visual Studio就行了。


 

WinIO这个库虽然可以使用,但是其最大的问题在于其64位下的系统签名是一个测试版签名,因此需要更改系统的设置才能使用。这就给发布带来很大的问题,如果我们做了一个软件要给别人用,却需要别人改自己电脑的设置,这显然有些不太合理。

于是后来就又发现了winring0(数字零而不是字母o)这个库。这个库可以实现与其完全相同的功能,不过可惜这个库的主页已经不在了,好像最新的版本是1.3.1b,不过我用的是1.3.0。这个库的签名是完好的,可以在64位下完美使用,而且官方封装好了C#下的接口调用,使用起来也非常方便。官方带有文档,也非常清晰。

另外值得一提的是关于chm打开看不到内容的问题。这个问题网上也很容易搜到,需要在chm的属性里面,勾选“解除锁定”的选项。
微信截图_20160410143206
再打开就可以看到了。


 

网上流传比较多的按键模拟的版本都手写出了每个按键的虚拟键值,其实这个键值c#中是有的,不需要自己写出来。需要注意的是有两种按键enum,一种是Key,另一种是Keys。其中前者是System.Windows.Input里面的,后者是System.Windows.Forms里面的。如果再普通winform下面应该是用Keys,而在WPF中则用Key比较多一些。Keys和Key之间可以通过一个KeyInterop类相互转换。这个类提供了两个静态方法,这个类被描述为

Provides static methods to convert between Win32 Virtual-Keys and the WPF key enumerations.

它提供了两个静态方法,分别为VirtualKeyFromKey(Key key)和KeyFromVirtualKey(int virtualKey)。前者用于将WPF Key转换为Win32 Key,后者则反过来。使用起来就像这样子

int btScancode = MapVirtualKey((uint)KeyInterop.VirtualKeyFromKey(wpfKey), 0);

这样就有了虚拟按键码,接着通过user32.dll中提供的一个辅助函数MapVirtualKey(uint Ucode, uint uMapType)就可以将其转换为键盘扫描码,便可以通过winring0的端口读写函数来写进端口,实现模拟按键。


 

2017年10月18日更新

一直没有更新,因为之前使用winring0出现了问题,在开发电脑上猜测没有问题,但是放到平板上却不能正常工作。

这次更新是发现了一个新的点击键盘而不转移焦点的方法,是在StackOverflow(链接)发现的,其也是引用自一篇讨论屏幕键盘的文章 。其核心思想是重写WindProc,来过滤掉处理焦点的事件,使窗体不接受鼠标激活焦点。不过存在的问题是,以前创建的Button控件,本身是可以接受焦点的,因此这里不使用Button控件,转而使用Label或者其他不带焦点的控件,然后为这些控件添加点击效果。

下面是过滤窗体焦点事件的代码,放到form代码就可以了:

 

发表评论

邮箱地址不会被公开。 必填项已用*标注