GM 页:修复内嵌 IE 输入法 + 物品分类浏览

- 90CN.dll:给 IE 控件窗口链重新关联 IME 上下文,中文输入不再只能打字母
- gmweb:页面加 ime-mode:active,focus 时再主动要一次
- 物品页加分组/类型/等级筛选,不依赖中文输入也能定位物品
- 服务端指纹回绑新 DLL(1223680 / 26633404…)
This commit is contained in:
hanfuit committed 2026-11-05 12:37:03 +08:00
1 parent c4ffa57bf2
commit e9a3952a9d
5 files changed
+176 -17

No files matched your search

+49 -1
View File
@@ -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);
}