跨进程实现在Tree中快速定位节点
跨進程實現在Tree中快速定位節點
--------------------------------------------------------------------------------
?
????? 前些日子寫軟件時,需要實現一個功能,就是在Tree中快速定位節點,比如注冊表編輯器左邊的Tree,
只要給出Tree中的節點路徑(以“/”分隔),就可以快速將樹展開,并將當前節點定位到指定的節點。功能的
實現并不難,但稍有些麻煩。原因在于,如果是本進程中的Tree,只要發消息就可以了,但如果是另外一個進
程中的Tree,就要在那個進程中申請內存,將Tree節點的文字復制到這塊內存,然后再把這塊內存的數據復制
到本進程的一塊內存中,才能與指定的節點路徑相比較。由于這個功能還有一些可一般化的東西,所以就寫了
一個DLL,只要給出Tree的句柄和節點路徑,就可以展開這顆樹并定位節點。
???? DLL源代碼如下:
/********************************************************************/
/* 文件名: Tree.cpp???????????????????????????????????????????????? */
/*????????????????????????????????????????????????????????????????? */
/* 功能: 標準 DLL ---- 跨進程展開 SysTreeView32 中指定的節點??????? */
/*????????????????????????????????????????????????????????????????? */
/* 作者: 盧培培 (goodname008)?????????? 時間: 2005.02.18??????????? */
/*????????????????????????????????????????????????????????????????? */
/* BLOG: http://blog.csdn.net/goodname008?????????????????????????? */
/********************************************************************/
#include "stdafx.h"
#include "Tree.h"
#include "commctrl.h"
#include <string>
using namespace std;
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
???? switch (ul_reason_for_call)
???? {
???????? case DLL_PROCESS_ATTACH:
???????? case DLL_THREAD_ATTACH:
???????? case DLL_THREAD_DETACH:
???????? case DLL_PROCESS_DETACH:
????????????? break;
???? }
??? return TRUE;
}
/********************************************************************/
/* 功? 能: 跨進程展開 SysTreeView32 中指定的節點
/*
/* 參? 數: hTreeWnd???????? SysTreeView32 的句柄
/*????????? lpszPath??????? SysTreeView32 中的節點路徑(忽略大小寫)
/*
/* 返回值: TRUE???????????? 成功
/*???????? FALSE??????????? 失敗(節點路徑不存在時會返回失敗, 但仍然展開)
/*
/* 說? 明: 在節點路徑不存在的情況下, 本函數會盡可能展開存在的節點
/********************************************************************/
TREE_API BOOL APIENTRY ExpandTreeNode(HWND hTreeWnd, LPCSTR lpszPath)
{
???? string szPath = lpszPath;
???? if (szPath.empty())
???????? return FALSE;
???? DWORD dwProcessID = NULL;
???? GetWindowThreadProcessId(hTreeWnd, &dwProcessID);
???? if (!dwProcessID)
???????? return FALSE;
???? HANDLE hProcess = NULL;
???? hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE |
PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
???? if (!hProcess)
???????? return FALSE;
???? TVITEM tvItem, *pItem = NULL;
???? ZeroMemory(&tvItem, sizeof(TVITEM));
???? pItem = (TVITEM *)VirtualAllocEx(hProcess, NULL, sizeof(TVITEM), MEM_COMMIT,
PAGE_READWRITE);
???? tvItem.mask = TVIF_TEXT;
???? tvItem.cchTextMax = 512;
???? tvItem.pszText = (LPSTR)VirtualAllocEx(hProcess, NULL, 512, MEM_COMMIT, PAGE_READWRITE);
???? tvItem.hItem = TreeView_GetRoot(hTreeWnd);
???? if (!tvItem.hItem)
???????? return FALSE;
???? string szPathNode;
???? string::size_type nBackslashPos = -1;
???? char szItemText[512] = {'/0'};
???? do
???? {
???????? szPathNode = szPath.substr(nBackslashPos + 1, szPath.find('//', nBackslashPos + 1) -
nBackslashPos - 1);
???????? do
???????? {
????????????? if (!WriteProcessMemory(hProcess, pItem, &tvItem, sizeof(TVITEM), NULL))
?????????????????? return FALSE;
????????????? if (!TreeView_GetItem(hTreeWnd, pItem))
?????????????????? return FALSE;
????????????? if (!ReadProcessMemory(hProcess, tvItem.pszText, szItemText, 512, NULL))
?????????????????? return FALSE;
????????????? if (lstrcmpi(szPathNode.c_str(), szItemText) == 0)
????????????? {
?????????????????? TreeView_SelectItem(hTreeWnd, tvItem.hItem);
?????????????????? if (TreeView_Expand(hTreeWnd, tvItem.hItem, TVE_EXPAND))
?????????????????? {
?????????????????????? tvItem.hItem = TreeView_GetChild(hTreeWnd, tvItem.hItem);
?????????????????????? if (!tvItem.hItem)
??????????????????????????? return FALSE;
?????????????????? }
????????????? }
????????????? else
????????????? {
?????????????????? tvItem.hItem = TreeView_GetNextSibling(hTreeWnd, tvItem.hItem);
?????????????????? if (!tvItem.hItem)
?????????????????????? return FALSE;
????????????? }
???????? } while(lstrcmpi(szPathNode.c_str(), szItemText) != 0);
???????? nBackslashPos = szPath.find('//', nBackslashPos + 1);
???? } while(nBackslashPos != -1);
???? VirtualFreeEx(hProcess, tvItem.pszText, NULL, MEM_RELEASE);
???? VirtualFreeEx(hProcess, pItem, NULL, MEM_RELEASE);
???? CloseHandle(hProcess);
???? return TRUE;
}
??? 頭文件源代碼:
#ifdef TREE_EXPORTS
#define TREE_API __declspec(dllexport)
#else
#define TREE_API __declspec(dllimport)
#endif
TREE_API BOOL APIENTRY ExpandTreeNode(HWND hTreeWnd, LPCSTR lpszPath);
??? DEF文件如下:
LIBRARY? Tree
EXPORTS
ExpandTreeNode???? @1
調用例程就不再這里給出了,DLL和VC的調用例程都是用.net環境寫的。
源代碼及調用例程的下載地址:
http://csdngoodname008.51.net/Tree.zip
總結
以上是生活随笔為你收集整理的跨进程实现在Tree中快速定位节点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python读取redis存储数据的存储
- 下一篇: 返回值类型与函数类型不匹配_C++返回值