Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

全屏输入的一点建议 #11

Open
anchurcn opened this issue Mar 15, 2021 · 12 comments
Open

全屏输入的一点建议 #11

anchurcn opened this issue Mar 15, 2021 · 12 comments
Labels
Priority: Medium Keep normal workflow Status: In Progress We are working on it Type: Enhancement Improvements to the code
Milestone

Comments

@anchurcn
Copy link

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

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

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

@SakuraKoi
Copy link
Owner

SakuraKoi commented Mar 15, 2021

  • 有没有哪个 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 SakuraKoi added Priority: Medium Keep normal workflow Status: Confirmed We confirmed this issue exists or accepted the suggestion, waiting for work on it Type: Enhancement Improvements to the code labels Mar 16, 2021
@anchurcn
Copy link
Author

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

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

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

@SakuraKoi
Copy link
Owner

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

@anchurcn
Copy link
Author

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

@SakuraKoi
Copy link
Owner

SakuraKoi commented Mar 16, 2021

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

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

@SakuraKoi SakuraKoi changed the title 一点建议 全屏输入的一点建议 May 19, 2022
@luojunyuan
Copy link

全屏独占的游戏窗口里。可以通过让输入法窗口失去焦点,使用 BringWindowsToTop 一类win32方法让输入法窗口提前。这样可以显示输入法窗口,但是因为没有焦点是无法直接读取键盘输入的。希望能有所帮助。

@anchurcn
Copy link
Author

anchurcn commented Mar 13, 2023

@luojunyuan 感谢你的回复。在游戏可以使用输入法的前提下,使用你的方法确实可以免去手动实现输入法候选词窗口的麻烦。不过目前需要解决的是游戏不能使用输入法。

@luojunyuan
Copy link

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

有一个奇葩方法。
用 SetParent(https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-setparent) 让InputDialog这个窗口成为BattleField1的子窗口,这样可以显示出选词窗口。

@luojunyuan
Copy link

image

SetParent 前需要移除Qt窗口的POPUP style,添加 CHILD style
SetParent(Qt_hWnd, bf_hWnd)

@anchurcn
Copy link
Author

@luojunyuan 可以的,赞。如果你已经实现,有兴趣的话可以提一个pr。我们很感激你对此做出的研究。

@SakuraKoi SakuraKoi added this to the v9 milestone Mar 26, 2023
@SakuraKoi
Copy link
Owner

SakuraKoi commented Mar 26, 2023

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

有一个奇葩方法。 用 SetParent(https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-setparent) 让InputDialog这个窗口成为BattleField1的子窗口,这样可以显示出选词窗口。

感谢研究, 如测试有效的话将在下一个版本中实现全屏输入
这个实现真的很梨谱x

@SakuraKoi SakuraKoi added Status: In Progress We are working on it and removed Status: Confirmed We confirmed this issue exists or accepted the suggestion, waiting for work on it labels Mar 26, 2023
@SakuraKoi
Copy link
Owner

SakuraKoi commented Jan 15, 2024

SetParent确实可以使得全屏中显示输入窗口调用输入法的同时不弹到桌面上去
但测试过程中遇到了一些问题, 输入窗口绘制不出来, 只在界面更新的时候闪烁显示一瞬间
并且窗口焦点之间的切换也存在一些问题导致较为频繁的发送操作不生效问题

目前全屏支持为可以使用但存在bug的状态, 需要进一步研究

image

SetParent 前需要移除Qt窗口的POPUP style,添加 CHILD style SetParent(Qt_hWnd, bf_hWnd)

能否提供一下这个poc的src以进行测试?

Repository owner deleted a comment from hansa-panot Mar 19, 2024
Repository owner deleted a comment from hansa-panot Mar 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Priority: Medium Keep normal workflow Status: In Progress We are working on it Type: Enhancement Improvements to the code
Projects
None yet
Development

No branches or pull requests

3 participants