在一个特定场景下,需要读取目标进程中树形控件中各个HTREEITEM的文字信息和区域信息,在查找一些资料后调试成功!
void CSysTreeView32_DemoDlg::OnBnClickedBtnTvmGetitem()
{
TCHAR dbgInfo[128]; //用于OutputDebugString()
// hWnd是另外一个进程中的SysTreeview32控件的窗口句柄
//HWND hWnd = (HWND) 0x1017b2;
HWND hWnd = (HWND) 0xf1b1c;
//HWND hWnd = (HWND) 0x3b1078;
TCHAR szItemText[128]; //用于获取tree item的文字
TVITEM tvi;
memset (&tvi, 0, sizeof(TVITEM));
tvi.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_CHILDREN;
tvi.pszText = szItemText;
tvi.cchTextMax = 128;
HTREEITEM hRoot = TreeView_GetRoot(hWnd);
/*
HTREEITEM hRoot2 = TreeView_GetNextItem(hWnd, NULL, TVGN_ROOT);
//以上两句功能相同
*/
tvi.hItem = hRoot;
//跨进程可以起作用
TreeView_SelectItem(hWnd, hRoot);
TreeView_GetItem(hWnd, &tvi); //获取title失败。也就是因为跨进程了的原因。
//跨进程可以起作用,取下一节点
HTREEITEM hItem = TreeView_GetNextItem(hWnd, hRoot, TVGN_NEXT);
TreeView_SelectItem(hWnd, hItem);
TreeView_EnsureVisible(hWnd, hItem);
//获取item的矩形,失败!!!
RECT rc;
BOOL bRes = TreeView_GetItemRect(hWnd, hItem, &rc, FALSE);
//以下为跨进程处理的必要逻辑。
{
DWORD dwProcessID = NULL;
GetWindowThreadProcessId(hWnd, &dwProcessID);
HANDLE hProcess = NULL;
hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
ASSERT(hProcess);
TVITEM * pItem = NULL;
pItem = (TVITEM *) VirtualAllocEx(hProcess, NULL, sizeof(TVITEM), MEM_COMMIT, PAGE_READWRITE);
tvi.pszText = (LPTSTR) VirtualAllocEx(hProcess, NULL, sizeof(TCHAR) * 128, MEM_COMMIT, PAGE_READWRITE);
//遍历另一个进程中的树形控件代码。
do
{
bRes = WriteProcessMemory(hProcess, pItem, &tvi, sizeof(tvi), NULL);
bRes = TreeView_GetItem(hWnd, pItem);//跨进程取title成功!
bRes = ReadProcessMemory(hProcess, pItem, &tvi, sizeof(tvi), NULL);
bRes = ReadProcessMemory(hProcess, tvi.pszText, szItemText, 128, NULL);
_stprintf_s (dbgInfo, 128, _T("hItem=0x%x nChild=%d title=%s\n"), tvi.hItem, tvi.cChildren, szItemText);
OutputDebugString(dbgInfo);
//遍历的思路(目标树形控件只有两级节点):
//如果有子节点,就取第一个子节点
//如果没有子节点,就取兄弟节点
//如果没有子,也没有兄弟,说明当前这一层级的节点已遍历完毕,应回到父节点的兄弟节点
//如果没有父节点就退出(最后一个一级子节点没有子节点), 如果父节点没有兄弟(最后一个一级子节点具有子节点)也退出
//遍历完毕
if (tvi.cChildren > 0){
hItem = TreeView_GetChild(hWnd, tvi.hItem);
}
else {
hItem = TreeView_GetNextSibling(hWnd, tvi.hItem);
}
if (!hItem)
{
hItem = TreeView_GetParent(hWnd, tvi.hItem);
if (!hItem){
break;
}
else{
hItem = TreeView_GetNextSibling(hWnd, hItem);
if (!hItem){
break;
}
}
}
tvi.hItem = hItem;
} while(1);
VirtualFreeEx(hProcess, tvi.pszText, NULL, MEM_RELEASE);
VirtualFreeEx(hProcess, pItem, NULL, MEM_RELEASE);
CloseHandle(hProcess);
}
}