首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

跨進程取得視窗文字:為何 GetWindowText 失效與 WM_GETTEXT 正確用法

     編輯:關於C語言

在 Windows 程式設計中,嘗試讀取其他進程視窗(如編輯框、按鈕、下拉方塊)的文字時,直接呼叫 GetWindowText 常會失敗返回空字串。本文深入解釋原因,並示範正確的跨進程取文字方案:SendMessageTimeout(WM_GETTEXT)。

現象:GetWindowText 的「設計限制」

MSDN 文件明確指出:

若目標視窗屬於不同進程,GetWindowText **不會**發送 WM_GETTEXT 訊息。它僅能取得頂層視窗的標題列文字;若視窗無標題(如子控制項),直接返回空字串。這是「設計使然」。

原因在於 GetWindowText 為了防止當前執行緒因跨進程同步呼叫而無限期阻塞(目標進程可能掛起、死鎖),犧牲了功能完整性換取「不會掛住調用者」的安全性。

正解:直接發送 WM_GETTEXT 訊息

繞過 GetWindowText 的封裝,直接向目標視窗發送訊息:

// C++ / MFC 風格
CWnd* pWnd = GetOtherAppWindow(); // 取得目標 HWND
TCHAR buf[512];
pWnd->SendMessage(WM_GETTEXT, sizeof(buf)/sizeof(TCHAR), (LPARAM)buf);

或使用更安全的超時版本(推薦):

DWORD dwResult;
SendMessageTimeout(hwnd, WM_GETTEXT, STRINGLEN, (LPARAM)s.GetBuffer(STRINGLEN),
    SMTO_ABORTIFHUNG, 1000, &dwResult); // 1 秒超時,目標掛起即放棄

為何 SendMessageTimeout 是最佳實踐?

  • 跨進程能力: 系統負責封送處理,目標進程處理 WM_GETTEXT 並返回文字。
  • 超時保護: SMTO_ABORTIFHUNG 旗標確保目標進程無回應時,調用端在指定毫秒內返回,避免 UI 凍結。
  • 通用性: 適用於所有支援 WM_GETTEXT 的控制項(Edit、ComboBox、Button、Static、ListBox 項目等)。

實戰驗證:GWTTest 範例程式

文章附帶的 GWTTest 程式(CListView 架構)同時顯示 GetWindowText 與 SendMessageTimeout(WM_GETTEXT) 的結果:

  • 頂層視窗標題:兩者均能取得。
  • 其他進程的編輯框內容:GetWindowText 返回空;WM_GETTEXT 正確返回文字。

核心取文字函數 CMyView::AddWindowInfo 程式碼片段:

void CMyView::AddWindowInfo(int iItem, HWND hwnd) {
    CListCtrl& lc = GetListCtrl();
    CWnd* pWnd = CWnd::FromHandle(hwnd);
    int iSub = 1;
    CString s;

    // 類別名
    ::GetClassName(hwnd, s.GetBuffer(STRINGLEN), STRINGLEN);
    lc.SetItemText(iItem, iSub++, s);

    // GetWindowText 結果
    pWnd->GetWindowText(s);
    lc.SetItemText(iItem, iSub++, s);

    // WM_GETTEXT 結果
    DWORD result;
    SendMessageTimeout(hwnd, WM_GETTEXT, STRINGLEN, (LPARAM)s.GetBuffer(STRINGLEN),
        0, 1000, &result);
    lc.SetItemText(iItem, iSub++, s);
    s.ReleaseBuffer();
}

總結

API跨進程子控制項阻塞風險適用場景
GetWindowText❌ 僅標題無 (內部特殊處理)同進程控制項、取頂層視窗標題
SendMessage(WM_GETTEXT)✅ 完整支援高 (目標掛起則永久阻塞)同進程、或確信目標極度響應
SendMessageTimeout(WM_GETTEXT)✅ 完整支援可控 (毫秒級超時)跨進程取文字的標準最佳實踐
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved