跨进程实现在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

  1<string>
  2
  3using namespace  std; 
  4
  5BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 
  6
  7{ 
  8
  9switch  (ul_reason_for_call) 
 10
 11{ 
 12
 13case  DLL_PROCESS_ATTACH: 
 14
 15case  DLL_THREAD_ATTACH: 
 16
 17case  DLL_THREAD_DETACH: 
 18
 19case  DLL_PROCESS_DETACH: 
 20
 21break  ; 
 22
 23} 
 24
 25return  TRUE; 
 26
 27} 
 28
 29/********************************************************************/ 
 30
 31/*  功  能  :  跨进程展开  SysTreeView32  中指定的节点 
 32
 33/* 
 34
 35/*  参  数  : hTreeWnd  SysTreeView32  的句柄 
 36
 37/*  lpszPath  SysTreeView32  中的节点路径  (  忽略大小写  ) 
 38
 39/* 
 40
 41/*  返回值  : TRUE  成功 
 42
 43/*  FALSE  失败  (  节点路径不存在时会返回失败  ,  但仍然展开  ) 
 44
 45/* 
 46
 47/*  说  明  :  在节点路径不存在的情况下  ,  本函数会尽可能展开存在的节点 
 48
 49/********************************************************************/ 
 50
 51TREE_API BOOL APIENTRY ExpandTreeNode(HWND hTreeWnd, LPCSTR lpszPath) 
 52
 53{ 
 54
 55string szPath = lpszPath; 
 56
 57if  (szPath.empty()) 
 58
 59return  FALSE; 
 60
 61DWORD dwProcessID = NULL; 
 62
 63GetWindowThreadProcessId(hTreeWnd, &amp;dwProcessID); 
 64
 65if  (!dwProcessID) 
 66
 67return  FALSE; 
 68
 69HANDLE hProcess = NULL; 
 70
 71hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, FALSE, dwProcessID); 
 72
 73if  (!hProcess) 
 74
 75return  FALSE; 
 76
 77TVITEM tvItem, *pItem = NULL; 
 78
 79ZeroMemory(&amp;tvItem,  sizeof  (TVITEM)); 
 80
 81pItem = (TVITEM *)VirtualAllocEx(hProcess, NULL,  sizeof  (TVITEM), MEM_COMMIT, PAGE_READWRITE); 
 82
 83tvItem.mask = TVIF_TEXT; 
 84
 85tvItem.cchTextMax = 512; 
 86
 87tvItem.pszText = (LPSTR)VirtualAllocEx(hProcess, NULL, 512, MEM_COMMIT, PAGE_READWRITE); 
 88
 89tvItem.hItem = TreeView_GetRoot(hTreeWnd); 
 90
 91if  (!tvItem.hItem) 
 92
 93return  FALSE; 
 94
 95string szPathNode; 
 96
 97string::size_type nBackslashPos = -1; 
 98
 99char  szItemText[512] = {'\0'}; 
100
101do 
102
103{ 
104
105szPathNode = szPath.substr(nBackslashPos + 1, szPath.find('\\\', nBackslashPos + 1) - nBackslashPos - 1); 
106
107do 
108
109{ 
110
111if  (!WriteProcessMemory(hProcess, pItem, &amp;tvItem,  sizeof  (TVITEM), NULL)) 
112
113return  FALSE; 
114
115if  (!TreeView_GetItem(hTreeWnd, pItem)) 
116
117return  FALSE; 
118
119if  (!ReadProcessMemory(hProcess, tvItem.pszText, szItemText, 512, NULL)) 
120
121return  FALSE; 
122
123if  (lstrcmpi(szPathNode.c_str(), szItemText) == 0) 
124
125{ 
126
127TreeView_SelectItem(hTreeWnd, tvItem.hItem); 
128
129if  (TreeView_Expand(hTreeWnd, tvItem.hItem, TVE_EXPAND)) 
130
131{ 
132
133tvItem.hItem = TreeView_GetChild(hTreeWnd, tvItem.hItem); 
134
135if  (!tvItem.hItem) 
136
137return  FALSE; 
138
139} 
140
141} 
142
143else 
144
145{ 
146
147tvItem.hItem = TreeView_GetNextSibling(hTreeWnd, tvItem.hItem); 
148
149if  (!tvItem.hItem) 
150
151return  FALSE; 
152
153} 
154
155}  while  (lstrcmpi(szPathNode.c_str(), szItemText) != 0); 
156
157nBackslashPos = szPath.find('\\\', nBackslashPos + 1); 
158
159}  while  (nBackslashPos != -1); 
160
161VirtualFreeEx(hProcess, tvItem.pszText, NULL, MEM_RELEASE); 
162
163VirtualFreeEx(hProcess, pItem, NULL, MEM_RELEASE); 
164
165CloseHandle(hProcess); 
166
167return  TRUE; 
168
169}   
170  
171---  
172  
173头文件源代码: 
174
175#ifdef  TREE_EXPORTS 
176
177#define  TREE_API  __declspec  (  dllexport  ) 
178
179#else 
180
181#define  TREE_API  __declspec  (  dllimport  ) 
182
183#endif 
184
185TREE_API BOOL APIENTRY ExpandTreeNode(HWND hTreeWnd, LPCSTR lpszPath);   
186  
187---  
188  
189DEF  文件如下: 
190
191LIBRARY  Tree 
192
193EXPORTS 
194
195ExpandTreeNode  @1   
196  
197---  
198  
199调用例程就不再这里给出了,  DLL  和  VC  的调用例程都是用  .net  环境写的。 
200
201源代码及调用例程的下载地址:  http://csdngoodname008.51.net/Tree.zip 
202
203*-------------------------------------------* 
204
205*  转载请通知作者并注明出处,  CSDN  欢迎您!  * 
206
207*  作者:卢培培(  goodname008  )  * 
208
209*  邮箱:  [email protected]  * 
210
211*  专栏:  http://blog.csdn.net/goodname008  * 
212
213*-------------------------------------------*</string>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus