前些日子写软件时,需要实现一个功能,就是在 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, &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(&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, &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>