跨进程实现在Tree中快速定位节点

80酷酷网    80kuku.com

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



*  邮箱:goodname008163.com                *



*  专栏:http://blog.csdn.net/goodname008   *



*-------------------------------------------*

分享到
  • 微信分享
  • 新浪微博
  • QQ好友
  • QQ空间
点击: