所謂「按鍵突破」實為啟用被停用的視窗控制項。核心 API 僅需 EnableWindow(hWnd, TRUE),關鍵在於如何即時取得滑鼠所指控制項的 HWND。本文完整實作從座標轉換、子視窗遞迴搜尋到多執行緒輪詢的完整流程。
BOOL EnableWindow(
HWND hWnd, // 目標視窗/控制項
BOOL bEnable // TRUE=啟用, FALSE=停用
);
WindowFromPoint - 取得最上層視窗POINT pt;
GetCursorPos(&pt); // 螢幕座標
HWND hTop = WindowFromPoint(pt); // 含透明/無回應視窗
ScreenToClient - 座標系轉換ScreenToClient(hParent, &pt); // 螢幕座標 → 客戶區座標
RealChildWindowFromPoint - 子視窗點擊測試HWND RealChildWindowFromPoint(
HWND hParent, // 父視窗
POINT ptClientCoords // 客戶區座標
);
限制:僅回傳第一層子視窗,無法穿透重疊視窗取得最深層控制項。
void GetRealWindow(HWND* phWnd)
{
POINT pt;
GetCursorPos(&pt); // 1. 取得螢幕座標
HWND hTop = WindowFromPoint(pt); // 2. 最上層視窗
HWND hParent = GetParent(hTop); // 3. 取得頂層父視窗
ScreenToClient(hParent, &pt); // 4. 轉為客戶區座標
// 5. 遞迴向下尋找最深層子視窗
while (TRUE)
{
HWND hChild = RealChildWindowFromPoint(hParent, pt);
if (hChild && hChild != hParent)
hParent = hChild; // 繼續往下
else
break;
}
*phWnd = hParent;
}
DWORD WINAPI BreakThread(LPVOID lpParam)
{
HWND hTarget = NULL;
while (g_bRunning) // 全域旗標控制
{
GetRealWindow(&hTarget);
if (hTarget)
EnableWindow(hTarget, TRUE); // 啟用控制項
Sleep(100); // 降低 CPU 佔用
}
return 0;
}
// 啟動按鈕處理
void CMyDlg::OnStartBreak()
{
g_bRunning = TRUE;
CreateThread(NULL, 0, BreakThread, NULL, 0, &g_dwThreadId);
}
// 停止按鈕處理
void CMyDlg::OnStopBreak()
{
g_bRunning = FALSE;
// 可選:WaitForSingleObject(hThread, INFINITE);
}
| 函數 | 用途 | 備註 |
|---|---|---|
WindowFromPoint | 螢幕點 → 最上層視窗 | 含透明/禁用視窗 |
ChildWindowFromPoint | 父視窗客戶區點 → 子視窗 | 不遞迴,含隱藏/禁用 |
RealChildWindowFromPoint | 同上,但跳過隱藏/禁用/透明 | 較實用 |
GetParent | 取得父視窗 | 單層 |
GetAncestor(hWnd, GA_ROOT) | 取得頂層視窗 | 跨進程亦可 |
需安裝 Windows SDK (含 windows.h 更新版、lib、dll),並將 include/lib 目錄加入 VC++ 專案設定。SDK 提供 RealChildWindowFromPoint 等較新 API。
原理:取得滑鼠下的 頂層父視窗,遞迴 EnumChildWindows 將所有停用子視窗啟用:
BOOL CALLBACK EnableAllChildren(HWND hChild, LPARAM lParam)
{
EnableWindow(hChild, TRUE);
return TRUE; // 繼續列舉
}
void EnableAllDisabledInWindow(HWND hWnd)
{
EnumChildWindows(hWnd, EnableAllChildren, 0);
}
在輪詢執行緒中呼叫 EnableAllDisabledInWindow(hParent) 即可達到同樣效果。
按鍵突破核心技術鏈:GetCursorPos → WindowFromPoint → ScreenToClient → 遞迴 RealChildWindowFromPoint → EnableWindow(TRUE)。配合多執行緒輪詢即可即時生效。理解此原理不僅能自製工具,更能深入掌握 Windows 視窗階層與座標系統。