目標進程的 `ListView` 記憶體空間不在當前進程,需跨進程配置緩衝區、寫入 `LVITEM` 結構、發送訊息、讀回文字。
void MyGetListViewItem(HWND hWindow, TStrings *strlist)
{
const int nMaxLen = 1023;
char szBuf[nMaxLen+1];
DWORD dwProcessID;
HANDLE hProcess = NULL;
LVITEM lvItemLocal;
LPVOID lpTextRemote = NULL, lpListItemRemote = NULL;
DWORD dwBytesRead, dwBytesWrite;
bool bSuccess, bWriteOK;
GetWindowThreadProcessId(hWindow, &dwProcessID);
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);
if (!hProcess) return;
lpTextRemote = VirtualAllocEx(hProcess, NULL, nMaxLen+1, MEM_COMMIT, PAGE_READWRITE);
lpListItemRemote = VirtualAllocEx(hProcess, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
if (!lpTextRemote || !lpListItemRemote) goto Cleanup;
int nCount = ListView_GetItemCount(hWindow);
strlist->Add("ListView 項目總數: " + IntToStr(nCount));
for (int i = 0; i < nCount; i++) {
ZeroMemory(szBuf, nMaxLen+1);
bWriteOK = WriteProcessMemory(hProcess, lpTextRemote, szBuf, nMaxLen+1, &dwBytesWrite);
if (!bWriteOK) break;
lvItemLocal.iItem = i;
lvItemLocal.iSubItem = 0;
lvItemLocal.mask = LVIF_TEXT;
lvItemLocal.cchTextMax = nMaxLen;
lvItemLocal.pszText = (LPTSTR)lpTextRemote;
bWriteOK = WriteProcessMemory(hProcess, lpListItemRemote, &lvItemLocal, sizeof(LVITEM), &dwBytesWrite);
if (!bWriteOK) break;
SendMessage(hWindow, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)lpListItemRemote);
bSuccess = ReadProcessMemory(hProcess, lpTextRemote, szBuf, nMaxLen+1, &dwBytesRead);
if (!bSuccess) break;
strlist->Add(AnsiString(szBuf));
}
Cleanup:
if (lpListItemRemote) VirtualFreeEx(hProcess, lpListItemRemote, 0, MEM_RELEASE);
if (lpTextRemote) VirtualFreeEx(hProcess, lpTextRemote, 0, MEM_RELEASE);
if (hProcess) CloseHandle(hProcess);
}
若 `ViewStyle = vsReport`,需額外讀取 `LVM_GETCOLUMN` 取得標題,並對每個 `iSubItem` 呼叫 `LVM_GETITEMTEXT`。