跨进程遍历目标进程中树形控件的例子源码

在一个特定场景下,需要读取目标进程中树形控件中各个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);
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值