前些日子写软件时,需要实现一个功能,就是在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
*——————————————-*
* 转载请通知作者并注明出处,csdn欢迎您! *
* 作者:卢培培(goodname008) *
* 邮箱:goodname008@163.com *
* 专栏:http://blog.csdn.net/goodname008 *
*——————————————-*