BattlefieldChat icon indicating copy to clipboard operation
BattlefieldChat copied to clipboard

全屏输入的一点建议

Open anchurcn opened this issue 3 years ago • 12 comments

前几天我也研究了几天战地的中文输入,做了一个玩具级别的输入工具。因为我没有逆向的相关经验,输入缓冲区的地址往上找了两级就不会了,所以我在每局开始都得先在输入框输入最长字符串,使输入缓冲区地址不再变化,自行搜索地址,然后填入我的小工具。 不过我这个工具也有好的地方,我是通过注册全局热键呼出的,程序接到热键消息后就把窗口激活然后置顶。由于战地1是全屏独占的,失去焦点后会最小化。在工具输入完成发送后,程序模拟按下键盘的 ALT+Tab,自动切回战地。 最大的痛点是不能全屏使用体验都不怎么好,所以找了很多资料,也就找到你这儿了。发现你把窗口化下的解决方案弄得比较完整了。 我分享一下我后面的研究方向: 全屏游戏似乎用 ImmDisableIME 禁用了输入法(自己写程序试过,症状和战地一样),有没有哪个 API 能够重新打开IME功能?(搜索了一段时间,没找到方案) 如果无论如何都不能打开这个窗口的 IME 功能,那么开启新的输入框架 TSF 是否可行?

如果实在不能在游戏内使用输入法,那可不可以在游戏外创建另一个拥有窗口的进程,把游戏内的击键传给这个进程(或者这个进程有办法在后台知道用户的击键)进行 IME 输入,这个进程把 IME 消息通过 SendMessage 发给游戏窗口,游戏内注入的代码就能响应IME消息了。 总之就是要么游戏窗口自己能打开输入法,要么想办法在游戏全屏不失去焦点的同时让另一个窗口能进行输入法输入。不管是谁,能产生IME消息就解决了。接收IME消息自绘输入窗口已经有现成的方案了。

最后有一个更麻烦的方法,就是在游戏内置输入法。游戏内键盘按下是有 WM_Char 消息的。 做这些有一个前提,战地的反外挂程序不会打扰我们吧?

anchurcn avatar Mar 15 '21 15:03 anchurcn

  • 有没有哪个 API 能够重新打开IME功能? 并不是简单的api调用,实现ime非常复杂,全屏下输入法的选词窗口是不能显示的,我赌五毛dice也没实现,因此我们必须下钩子捕获输入消息然后自己在游戏内绘制输入界面

  • 要么游戏窗口自己能打开输入法 目前考虑的研究方向的确是这样的,但是需求不大所以动力不大再加上手头有另一些项目所以暂时咕咕咕(又不是不能用.jpg

  • 要么想办法在游戏全屏不失去焦点的同时让另一个窗口能进行输入法输入 这是不可能的,dx全屏独占输出,windows的其他窗口压根不能显示,选词窗口画不出来

  • 战地的反外挂程序不会打扰我们吧? 目前的外置输入不会,在输入窗口的时候bf是没有焦点的,因此ff并不会进行检测,但更进一步实现全屏势必要直接在游戏里绘制输入法(因为外部绘制不能显示),反作弊必须过掉,不然封号是可以预见的

提供一个文档参考: https://docs.microsoft.com/en-us/windows/win32/dxtecharts/using-an-input-method-editor-in-a-game 虽然很老(甚至是xp时代的),但是很完整并且具有参考意义

目前我这边对全屏的实现大致在考虑两个方向

  1. 兼容全屏: 和你的实现类似的切出游戏弹输入窗口,输入完再切回游戏
  2. 真全屏: 注入进游戏下钩子处理输入法消息,自绘选词窗口实现游戏内原生输入体验

即使真全屏实现了,我也不会将其开源,原因如上,涉及到了过游戏反作弊,开源的话被拿去写进外挂的可能性太大

SakuraKoi avatar Mar 15 '21 17:03 SakuraKoi

嗯,我说的重新打开IME是指和 ImmDisableIME 相反的功能。但并没有ImmEnableIME 这个API,目前的感觉用这个API禁用输入法是不可逆的。 MSDN 对ImmDisableIME 的说明:

在线程中的第一个顶级窗口接收到WM_CREATE消息之前,应用程序必须调用此函数。因此,应用程序必须在以下位置之一调用此函数: 在调用CreateWindow创建第一个顶级窗口之前的任何时间 在第一个顶级窗口的WM_NCCREATE处理程序中

至于有了 IME 消息之后如何绘制选词窗口等不是问题,已经有许多现成的解决方案了,你给的文档算一个,GitHub 也有源码。

anchurcn avatar Mar 16 '21 03:03 anchurcn

ImmDisableIME不是啥大问题, 大不了下个hook直接拦截掉呗(

SakuraKoi avatar Mar 16 '21 04:03 SakuraKoi

对哦,那这样的话理论上是可行的了,就看实际上这么做会不会造成游戏 crashes。毕竟 DICE 禁用可能出于怕和 DirectInput 之类的东西冲突的原因。如果只是因为没实现 IME 而禁用,那完全可以拦截,然后自己捕获消息进行处理。

anchurcn avatar Mar 16 '21 05:03 anchurcn

对哦,那这样的话理论上是可行的了,就看实际上这么做会不会造成游戏 crashes。毕竟 DICE 禁用可能出于怕和 DirectInput 之类的东西冲突的原因。如果只是因为没实现 IME 而禁用,那完全可以拦截,然后自己捕获消息进行处理。

我觉得他们压根就没想过东亚区域是要用输入法的( 但DirectInput的确可能会导致问题, 但不是崩溃, 而是打不进去字之类的

SakuraKoi avatar Mar 16 '21 05:03 SakuraKoi