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

跨進程選取 ListView 控件指定項目

     編輯:關於VC++

核心原理:跨進程記憶體操作

要在其他進程的 SysListView32 控件中選取特定項目,需發送 LVM_SETITEMSTATE 訊息。但 LVITEM 結構包含指標成員(pszText、lParam),指標在目標進程地址空間無效,因此必須:

  1. 取得目標視窗句柄(FindWindow/FindWindowEx)。
  2. 取得進程 ID 並開啟進程(OpenProcess,需 PROCESS_ALL_ACCESS)。
  3. 在目標進程配置記憶體(VirtualAllocEx)存放 LVITEM 結構。
  4. 寫入結構內容(WriteProcessMemory),設定 state = LVIS_SELECTED、stateMask = LVIS_SELECTED、iItem 為目標索引。
  5. 發送訊息(SendMessage),wParam 為項目索引,lParam 為遠端結構位址。
  6. 釋放資源(VirtualFreeEx、CloseHandle)。

完整範例程式碼

#include <windows.h>
#include <commctrl.h>

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
    HWND hwnd = FindWindow("#32770", "Windows 任務管理器");
    hwnd = FindWindowEx(hwnd, 0, "#32770", 0);
    hwnd = FindWindowEx(hwnd, 0, "SysListView32", 0);
    if (!hwnd) { MessageBox(NULL, "任務管理器未啟動", "錯誤", MB_OK); return 0; }

    DWORD pid; GetWindowThreadProcessId(hwnd, &pid);
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!hProcess) { MessageBox(NULL, "開啟進程失敗", "錯誤", MB_OK); return 0; }

    LVITEM* plvitem = (LVITEM*)VirtualAllocEx(hProcess, NULL, sizeof(LVITEM),
        MEM_COMMIT, PAGE_READWRITE);
    if (!plvitem) { MessageBox(NULL, "記憶體配置失敗", "錯誤", MB_OK); return 0; }

    LVITEM lvitem = {0};
    lvitem.state = LVIS_SELECTED;
    lvitem.stateMask = LVIS_SELECTED;
    int iItem = 5; // 第 6 項(0-based)
    WriteProcessMemory(hProcess, plvitem, &lvitem, sizeof(LVITEM), NULL);
    SendMessage(hwnd, LVM_SETITEMSTATE, (WPARAM)iItem, (LPARAM)plvitem);

    VirtualFreeEx(hProcess, plvitem, 0, MEM_RELEASE);
    CloseHandle(hProcess);
    return 0;
}

關鍵注意事項

  • 目標進程必須具備足夠權限(Win2K/XP 測試通過)。
  • LVITEM 結構大小必須與目標進程一致(同為 32 位元環境)。
  • 若目標控件為虛擬模式或自訂繪製,可能需額外處理。
  • 同樣原理可應用於 LVM_GETITEMTEXT、LVM_SETITEMTEXT 等訊息,只需調整結構欄位與讀寫方向。

本技術常用於自動化測試、外掛工具開發,使用時請注意安全性與相容性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved