小井盖面板全程压制:不再放回、关控制台后关闭并抑制 2.5 秒

- 触发条件改为「面板真的可见」而不是「窗口存在」,避免隐藏缓存的旧面板被当成点击
- 控制台打开期间面板一露头就 SW_HIDE,关控制台时关面板并在 2.5 秒内持续压制、最多再请 4 次关闭
- 轮询从 250ms 提到 40/60ms,消除旧页面闪现
- 服务端指纹回绑 CE86D4DF… (1258496)
This commit is contained in:
hanfuit committed 2026-11-05 13:26:06 +08:00
1 parent 32469e4341
commit 0c7ef6d645
3 files changed
+63 -48

No files matched your search

+3 -2
View File
@@ -4,14 +4,15 @@ enabled=1
; 1 = 点小井盖时弹出我们自己的窗口(推荐,中文输入正常)
; 0 = 老行为:仍然用游戏内嵌的 IE,只把页面跳转到下面的 url
external=1
; 我们自己的窗口开着的时候,把游戏内嵌的面板藏起来;关掉窗口后自动放回去
; 原面板全程压制:只要它露头就立刻藏起来,玩家永远看不到游戏自带的旧页面
suppress=1
; 控制台默认置顶显示。本服客户端全屏=无边框窗口最大化,已实测置顶窗口能正常盖在
; 游戏画面上,所以一般不用开。
; 只有换成真·独占全屏(DirectX 独占、窗口压在画面下看不见)时才改成 1:开控制台前先把
; 游戏最小化,关掉控制台再自动还原全屏。
minimize_game=0
; 关掉我们自己的窗口时:0 = 把游戏面板放回去(安全),1 = 直接把面板关掉
; 关掉我们自己的窗口时:1 = 直接关闭游戏原面板,并在之后 2.5 秒内继续压制它
; (推荐,原面板不会残留、也不会再露面);0 = 把面板放回去(老行为,会看到旧 IE 页面)
close_action=1
; 我们自己的窗口尺寸
width=1040
+59 -45
View File
@@ -631,24 +631,31 @@ DWORD WINAPI WorkerThread(void*)
HWND imeHwnd = nullptr;
unsigned imeTick = 0;
HWND hiddenPanel = nullptr;
HWND consumedPanel = nullptr;
bool ownShown = false;
int mode = g_cfg.external ? MODE_GM_WINDOW : MODE_INLINE;
DWORD lastPoll = 0;
DWORD lastLaunch = 0;
// 玩家关掉控制台之后的抑制期:这段时间里面板只要露头就继续藏、继续请它关闭,
// 免得游戏的关闭动画把旧页面又画出来(残留)。
DWORD suppressUntil = 0;
int closeAttempts = 0;
for (;;) {
if (InterlockedCompareExchange(&g_stop, 0, 0) != 0) break;
// WebView2 要靠消息泵跑起来,窗口开着时必须泵得勤,否则页面会顿。
GmPumpMessages(ownShown ? 50 : 250);
const DWORD now = GetTickCount();
if (now - lastPoll < 250) continue;
const bool suppressing = suppressUntil && now < suppressUntil;
// WebView2 要靠消息泵跑起来,窗口开着时必须泵得勤,否则页面会顿。
GmPumpMessages((ownShown || suppressing) ? 40 : 120);
// 原面板绝不能出现在画面上,所以轮询要快;空闲时放宽一点省 CPU。
const DWORD interval = (ownShown || suppressing) ? 40 : 60;
if (now - lastPoll < interval) continue;
lastPoll = now;
const HWND panel = FindWebPanelWindow();
const bool panelVisible = panel != nullptr && IsWindowVisible(panel) != FALSE;
if (mode == MODE_INLINE) {
HWND ieHwnd = FindIeServerWindow();
@@ -666,49 +673,59 @@ DWORD WINAPI WorkerThread(void*)
continue;
}
if (!panel) {
// 面板被游戏关掉了:把我们自己的窗口也收起来,状态归零
if (mode == MODE_GM_WINDOW && GmWindowIsVisible()) GmWindowHide();
RestoreGameFromConsole();
hiddenPanel = nullptr;
consumedPanel = nullptr;
// 控制台开着:原面板全程压制,一露头就藏,绝不让旧 IE 页面出现在画面上。
if (ownShown) {
if (!OwnWindowVisible(mode)) {
// 玩家把控制台关了:直接把原面板关掉并进入抑制期,不再放回游戏,
// 这样游戏自己的关闭动画不会把旧页面又画出来(残留)。
ownShown = false;
continue;
}
const bool mine = OwnWindowVisible(mode);
// 玩家把我们的窗口关了:把面板放回去(或直接关掉),交回游戏
if (ownShown && !mine) {
ownShown = false;
HWND target = (hiddenPanel && IsWindow(hiddenPanel)) ? hiddenPanel : panel;
if (panel) {
if (panelVisible) ShowWindow(panel, SW_HIDE);
if (g_cfg.closePanel) {
PostMessageW(target, WM_CLOSE, 0, 0);
LogLine("web window: own window closed, panel closed hwnd=%p", (void*)target);
PostMessageW(panel, WM_CLOSE, 0, 0);
suppressUntil = now + 2500;
closeAttempts = 1;
LogLine("web window: console closed, panel closed hwnd=%p", (void*)panel);
} else {
if (!IsWindowVisible(target)) ShowWindow(target, SW_SHOW);
LogLine("web window: own window closed, panel restored hwnd=%p", (void*)target);
ShowWindow(panel, SW_SHOW);
LogLine("web window: console closed, panel restored hwnd=%p", (void*)panel);
}
}
consumedPanel = target;
hiddenPanel = nullptr;
RestoreGameFromConsole();
continue;
}
if (mine) {
ownShown = true;
if (panelVisible) {
ShowWindow(panel, SW_HIDE);
LogLine("web window: panel suppressed hwnd=%p", (void*)panel);
}
// 全屏游戏会抢窗口栈,每轮确认一次置顶
GmWindowAssertTop();
if (g_cfg.suppress && IsWindowVisible(panel)) {
ShowWindow(panel, SW_HIDE);
hiddenPanel = panel;
LogLine("web window: panel hidden hwnd=%p", (void*)panel);
}
continue;
}
// 这一块面板玩家已经关过一次了,别再自动弹,等他重新点小井盖
if (consumedPanel == panel) continue;
// 抑制期:面板只要还露着就继续藏、继续请它关闭,期间不重新弹控制台。
if (suppressUntil) {
if (!panel || now > suppressUntil) {
suppressUntil = 0;
closeAttempts = 0;
} else {
if (panelVisible) {
ShowWindow(panel, SW_HIDE);
if (g_cfg.closePanel && closeAttempts < 4) {
PostMessageW(panel, WM_CLOSE, 0, 0);
++closeAttempts;
}
LogLine("web window: panel re-hidden after close hwnd=%p attempts=%d",
(void*)panel, closeAttempts);
}
continue;
}
}
// 面板不存在,或者存在但被游戏自己藏着 —— 都不该弹控制台。
// 只有「玩家点了小井盖、面板真的显示出来」才算一次打开请求。
if (!panelVisible) continue;
if (mode == MODE_GM_WINDOW) {
if (GmWindowFailed()) {
@@ -716,16 +733,15 @@ DWORD WINAPI WorkerThread(void*)
mode = MODE_APP_WINDOW;
continue;
}
// 先藏面板再建窗口,避免旧页面在中间闪一下
ShowWindow(panel, SW_HIDE);
if (GmWindowShow(g_cfg.url.c_str(), g_cfg.width, g_cfg.height)) {
ownShown = true;
if (g_cfg.suppress && IsWindowVisible(panel)) {
ShowWindow(panel, SW_HIDE);
hiddenPanel = panel;
LogLine("web window: panel hidden while showing hwnd=%p", (void*)panel);
}
// 独占全屏时先让游戏让位,否则控制台会被游戏画面压住
MakeRoomForConsole();
LogLine("web window: gm window shown");
LogLine("web window: gm window shown, panel suppressed hwnd=%p", (void*)panel);
} else {
LogLine("web window: gm window show failed hwnd=%p", (void*)panel);
}
continue;
}
@@ -733,12 +749,10 @@ DWORD WINAPI WorkerThread(void*)
// MODE_APP_WINDOW
if (now - lastLaunch > 3000) {
lastLaunch = now;
ShowWindow(panel, SW_HIDE);
if (LaunchOwnWindow()) {
ownShown = true;
if (g_cfg.suppress && IsWindowVisible(panel)) {
ShowWindow(panel, SW_HIDE);
hiddenPanel = panel;
}
LogLine("web window: app window launched");
} else {
mode = MODE_INLINE;
@@ -10,7 +10,7 @@ const (
boundMovieSHA256 = "D62E3623C39CD9FCED5F6C4C7F5E6E18BEB69EB269ABF5D713EDE08EE8C926A1"
boundMovieBytes = int64(22846532)
boundDllSHA256 = "7A179B1BE8348F4582F0DF89E6E493AEA105FAD0C19D8AC09517EA850788F1E3"
boundDllSHA256 = "CE86D4DF60BC3F8CB33F31D8D2FFE94512FA0E3B7D2EF24B13E142507787CC42"
boundDllBytes = int64(1258496)
)