GM 页:修复内嵌 IE 输入法 + 物品分类浏览
- 90CN.dll:给 IE 控件窗口链重新关联 IME 上下文,中文输入不再只能打字母 - gmweb:页面加 ime-mode:active,focus 时再主动要一次 - 物品页加分组/类型/等级筛选,不依赖中文输入也能定位物品 - 服务端指纹回绑新 DLL(1223680 / 26633404…)
This commit is contained in:
1 parent
c4ffa57bf2
commit
e9a3952a9d
5 files changed
+176
-17
No files matched your search
@@ -25,6 +25,7 @@
|
||||
// ============================================================================
|
||||
|
||||
#include <windows.h>
|
||||
#include <imm.h>
|
||||
#include <ole2.h>
|
||||
#include <oleacc.h>
|
||||
#include <mshtml.h>
|
||||
@@ -159,6 +160,40 @@ HWND FindIeServerWindow()
|
||||
return ctx.found;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- 输入法
|
||||
//
|
||||
// 症状:页面里的输入框只能打字母,切不到中文。
|
||||
// 原因:IME 上下文是窗口级的,DNF 主窗口把它握在自己手里,内嵌 IE 控件
|
||||
// 这条窗口链上没有上下文,输入法候选项压根不会出现。
|
||||
// 做法:给控件窗口及其子窗口重新关联线程默认 IME 上下文。这个调用是幂等
|
||||
// 的,每次轮询顺手做一遍,防止游戏在切图/进出聊天时把它重置掉。
|
||||
|
||||
bool AttachIme(HWND hwnd)
|
||||
{
|
||||
if (!hwnd) return false;
|
||||
if (ImmAssociateContextEx(hwnd, nullptr, IACE_DEFAULT | IACE_CHILDREN)) return true;
|
||||
// 退化路径:某些环境不给默认上下文,那就自己建一个挂上去。
|
||||
HIMC context = ImmCreateContext();
|
||||
if (!context) return false;
|
||||
if (ImmAssociateContext(hwnd, context)) return true;
|
||||
ImmDestroyContext(context);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EnsureImeChain(HWND hwnd)
|
||||
{
|
||||
if (!hwnd) return false;
|
||||
// 只给 IE_Server 挂还不够:焦点落在父窗口(Browser Example)时,
|
||||
// 输入法又会被游戏主窗口抢回去,所以父链一起处理。
|
||||
HWND chain[3] = { hwnd, GetParent(hwnd), nullptr };
|
||||
if (chain[1]) chain[2] = GetParent(chain[1]);
|
||||
bool any = false;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (chain[i] && AttachIme(chain[i])) any = true;
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
// 取文档对象。WM_HTML_GETOBJECT 的返回值经 ObjectFromLresult 还原成接口指针。
|
||||
IHTMLDocument2* GetDocument(HWND hwnd)
|
||||
{
|
||||
@@ -216,10 +251,20 @@ DWORD WINAPI WorkerThread(void*)
|
||||
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||
|
||||
HWND lastHandled = nullptr;
|
||||
HWND imeHwnd = nullptr;
|
||||
for (;;) {
|
||||
if (InterlockedCompareExchange(&g_stop, 0, 0) != 0) break;
|
||||
|
||||
HWND hwnd = FindIeServerWindow();
|
||||
if (hwnd) {
|
||||
// 每轮都重挂一次输入法:游戏在切图、进出聊天时会把上下文收回去。
|
||||
// 日志只在窗口变化时写,避免把 trace 刷满。
|
||||
const bool imeOk = EnsureImeChain(hwnd);
|
||||
if (hwnd != imeHwnd) {
|
||||
LogLine("web ime: attach %s hwnd=%p", imeOk ? "ok" : "failed", (void*)hwnd);
|
||||
imeHwnd = hwnd;
|
||||
}
|
||||
}
|
||||
if (hwnd && hwnd != lastHandled) {
|
||||
LogLine("web redirect: IE_Server window found hwnd=%p, waiting %dms", (void*)hwnd, g_cfg.delayMs);
|
||||
// 等原生导航把文档对象建好,太早拿会拿到 about:blank。
|
||||
@@ -257,7 +302,10 @@ DWORD WINAPI WorkerThread(void*)
|
||||
}
|
||||
}
|
||||
|
||||
if (!hwnd) lastHandled = nullptr; // 窗口被销毁后允许下次重新接管
|
||||
if (!hwnd) { // 窗口被销毁后允许下次重新接管
|
||||
lastHandled = nullptr;
|
||||
imeHwnd = nullptr;
|
||||
}
|
||||
for (int waited = 0; waited < 700 && !g_stop; waited += 100) {
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user