Replace always-on-top with foreground activation for game window focus

This commit is contained in:
z060142 2025-05-12 23:52:32 +08:00
parent 59471b62ce
commit a5b6a44164
2 changed files with 37 additions and 18 deletions

View File

@ -606,9 +606,13 @@ Wolf Chat 是一個基於 MCP (Modular Capability Provider) 框架的聊天機
- **`game_monitor.py`** - **`game_monitor.py`**
- 在 `monitor_game_window` 函數的監控循環中,移除了使用 `win32gui.SetWindowPos``win32con.HWND_TOPMOST` 來檢查和設定 `WS_EX_TOPMOST` 樣式的程式碼。 - 在 `monitor_game_window` 函數的監控循環中,移除了使用 `win32gui.SetWindowPos``win32con.HWND_TOPMOST` 來檢查和設定 `WS_EX_TOPMOST` 樣式的程式碼。
- 替換為檢查當前前景視窗 (`win32gui.GetForegroundWindow()`) 是否為目標遊戲視窗 (`hwnd`)。 - 替換為檢查當前前景視窗 (`win32gui.GetForegroundWindow()`) 是否為目標遊戲視窗 (`hwnd`)。
- 如果不是,則調用 `win32gui.BringWindowToTop(hwnd)``win32gui.SetForegroundWindow(hwnd)` 來嘗試將遊戲視窗帶到前景並啟用。 - 如果不是,則嘗試以下步驟將視窗帶到前景並獲得焦點:
- 更新了相關的日誌訊息以反映新的行為。 1. 使用 `win32gui.SetWindowPos` 搭配 `win32con.HWND_TOP` 旗標,將視窗提升到所有非最上層視窗之上。
- **效果**:監控腳本現在會嘗試將失去焦點的遊戲視窗重新激活並帶到前景,而不是強制其覆蓋所有其他視窗。這更符合一般視窗的行為模式。 2. 呼叫 `win32gui.SetForegroundWindow(hwnd)` 嘗試將視窗設為前景並獲得焦點。
3. 短暫延遲後,檢查視窗是否成功成為前景視窗。
4. 如果 `SetForegroundWindow` 未成功,則嘗試使用 `pygetwindow` 庫提供的 `window.activate()` 方法作為備用方案。
- 更新了相關的日誌訊息以反映新的行為和備用邏輯。
- **效果**:監控腳本現在會使用更全面的方法嘗試將失去焦點的遊戲視窗重新激活並帶到前景,包括備用方案,以提高在不同 Windows 環境下獲取焦點的成功率。這取代了之前僅強制視覺覆蓋的行為。
## 開發建議 ## 開發建議

View File

@ -217,28 +217,43 @@ def monitor_game_window():
# monitor_logger.warning(f"Failed to adjust window. Current: {new_pos} {new_size}, Target: {target_pos} {target_size}") # monitor_logger.warning(f"Failed to adjust window. Current: {new_pos} {new_size}, Target: {target_pos} {target_size}")
pass # Keep silent on failure for now pass # Keep silent on failure for now
# 2. Check and Bring to Foreground/Activate # 2. Check and Bring to Foreground/Activate (Improved Logic)
current_foreground_hwnd = win32gui.GetForegroundWindow() current_foreground_hwnd = win32gui.GetForegroundWindow()
if current_foreground_hwnd != hwnd: if current_foreground_hwnd != hwnd:
try: try:
# Attempt to bring to top and set foreground # Use HWND_TOP instead of HWND_TOPMOST to bring it above others without forcing always-on-top
# Note: SetForegroundWindow might fail if the calling process doesn't have foreground rights win32gui.SetWindowPos(hwnd, win32con.HWND_TOP, 0, 0, 0, 0,
win32gui.BringWindowToTop(hwnd) win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)
# Make window the foreground window (with focus)
# Note: This might still fail due to Windows foreground restrictions
win32gui.SetForegroundWindow(hwnd) win32gui.SetForegroundWindow(hwnd)
# Short delay to allow window manager to process
time.sleep(0.1) # Verify window is active by checking foreground window
# Verify if it became the foreground window time.sleep(0.1) # Brief pause to let operation complete
if win32gui.GetForegroundWindow() == hwnd: foreground_hwnd = win32gui.GetForegroundWindow()
current_message += "已將遊戲視窗帶到前景並啟用。(Brought game window to foreground and activated.) "
if foreground_hwnd == hwnd:
current_message += "已將遊戲視窗提升到前景並設為焦點。(Brought game window to foreground with focus.) "
adjustment_made = True adjustment_made = True
else: else:
# Optional: Log if setting foreground failed, might happen if another app steals focus quickly # Optional: Add a fallback for versions of Windows with stricter foreground rules
# monitor_logger.warning("嘗試將視窗設為前景後,它並未成為前景視窗。(Attempted to set window foreground, but it did not become the foreground window.)") monitor_logger.warning("SetForegroundWindow 未能成功,嘗試備用方法 window.activate()。(SetForegroundWindow failed, trying fallback window.activate())")
pass try:
except Exception as fg_err: window.activate() # Try pygetwindow's activate method as backup
# This can happen if the window handle is invalid or other win32 errors occur time.sleep(0.1) # Pause after activate
monitor_logger.warning(f"嘗試將視窗設為前景時出錯: {fg_err} (Error trying to set window foreground: {fg_err})") if win32gui.GetForegroundWindow() == hwnd:
current_message += "已透過備用方法將遊戲視窗設為焦點。(Set game window focus via fallback method.) "
adjustment_made = True
else:
monitor_logger.warning("備用方法 window.activate() 也未能成功。(Fallback window.activate() also failed.)")
except Exception as activate_err:
monitor_logger.warning(f"備用方法 window.activate() 出錯: {activate_err}")
except Exception as focus_err:
# Log errors during the focus attempt
monitor_logger.warning(f"設置視窗焦點時出錯: {focus_err}")
except gw.PyGetWindowException as e: except gw.PyGetWindowException as e:
# Log PyGetWindowException specifically, might indicate window closed during check # Log PyGetWindowException specifically, might indicate window closed during check