用 SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)str) 修改他程序灰色(禁用)EditBox,內容被清空但新文本未寫入。自寫程序同樣操作卻成功。這涉及UIPI(用戶界面權限隔離)、控制項子類化攔截、只讀/禁用狀態處理差異。
SendMessage(WM_SETTEXT) → 原文本清空,新文本未顯示SendMessage 被攔截/過濾SetWindowSubclass 或 SetWindowLong(GWL_WNDPROC) 掛鉤WM_SETTEXT、WM_CHAR、EM_REPLACESEL 等消息DefWindowProc 未被調用,或調用前清空內容、調用後恢復ES_READONLY 仍接受 WM_SETTEXT;WS_DISABLED 也接受WM_SETTEXT 中判斷狀態拒絕更新
EnableWindow(hEdit, TRUE);
SendMessage(hEdit, WM_SETTEXT, 0, (LPARAM)newText);
EnableWindow(hEdit, FALSE);
若目標程序在 WM_ENABLE 中重繪,可能閃爍但通常有效。
// 先全選
SendMessage(hEdit, EM_SETSEL, 0, -1);
// 發送每個字符
for (int i = 0; newText[i]; i++) {
PostMessage(hEdit, WM_CHAR, newText[i], 0);
}
或用 SendInput / keybd_event 全域模擬(需前台焦點)。
OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid)VirtualQueryEx 定位 Edit 控制項內存緩衝區WriteProcessMemory 直接寫入字串WM_PAINT / InvalidateRect 觸發重繪風險:極不穩定,目標程序更新即失效,可能觸發反作弊/防篡改。
WM_SETTEXT 觀察:是否到達?是否被 DefWindowProc 處理?返回值?SetWindowText、SendMessage 調用堆疊
// 發送前獲取窗口信息
TCHAR className[256];
GetClassName(hEdit, className, 256); // 確認是否 "Edit" 或自定義類
LONG style = GetWindowLong(hEdit, GWL_STYLE);
BOOL enabled = IsWindowEnabled(hEdit);
BOOL readonly = (style & ES_READONLY);
TRACE(_T("Class: %s, Style: 0x%X, Enabled: %d, ReadOnly: %d\n"), className, style, enabled, readonly);
// 發送後檢查返回值
LRESULT lr = SendMessage(hEdit, WM_SETTEXT, 0, (LPARAM)newText);
TRACE(_T("WM_SETTEXT returned: %d\n", lr));
DWORD err = GetLastError();
if (err) TRACE(_T("LastError: %d\n", err));
灰色 EditBox WM_SETTEXT 失敗,優先檢查 UIPI 權限隔離(以同權限運行)、目標程序子類化攔截(Spy++ 追蹤)、自定義控制項邏輯。繞過方案依序:EnableWindow 切換 → 模擬 WM_CHAR → 內存寫入(最後手段)。切記:操作他程序 UI 屬灰色地帶,穩定性無保障,盡量尋找官方 API/自動化接口替代。