如何设置其它进程中listctrl控件CHECKBOX的选中状态

c++编程 专栏收录该内容
92 篇文章 0 订阅
LV_ITEM lvi = {0};
lvi.mask = LVIF_STATE;
lvi.stateMask = LVIS_STATEIMAGEMASK;
lvi.state = INDEXTOSTATEIMAGEMASK(2); //不选中INDEXTOSTATEIMAGEMASK(1)
 
HWND  hWnd = ( HWND )0x001007EA;  //用SPY找到的句柄,自己用FindWindow查找
HANDLE  hProcess;
DWORD  dwPid;
::GetWindowThreadProcessId(hWnd, &dwPid);
hProcess = ::OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE, FALSE, dwPid);
 
LPVOID  plvi = ::VirtualAllocEx(hProcess, NULL, 128, MEM_COMMIT, PAGE_READWRITE);
::WriteProcessMemory(hProcess, plvi, &lvi,  sizeof (lvi), NULL);
::SendMessage(hWnd, LVM_SETITEMSTATE, ( WPARAM )1 /*insertitem返回的索引*/ , ( LPARAM )plvi);






《金山词霸2002》中的附录收集了很多古诗,有时为了寻找一篇古诗,得找很久很久(俺文科很差)。观察其附录的结构,发现是个Tree-View控件,如果能查找里面的项目该有多好,可这个功能软件本身却并没有提供(不知道现在最新的版本是否已经提供了这个功能,如果没有,赶快加上吧,顺便奖励俺一套该产品的最新版,哈哈)……问题出来了:我们要编写一个程序,让她在外部程序中的Tree-View控件里,按用户指定的项目名称顺序查找其中的项目。

要查找首先得遍历,连范围都确定不好何谈查找?所以本篇分两部分进行讲解:第一部分解决遍历的问题;第二部分解决查找指定项目的问题。

第一部分:遍历外部程序Tree-View中的项目

一:程序说明:

如图一所示Tree-View控件的典型结构图,我们将按照图示的顺序来遍历其中的项目。

图一

翻阅SDK手册中关于Tree-View控件的相关章节,发现了几个有用的消息:

TVM_GETNEXTITEM:得到项目的句柄(参数:TVGN_ROOT得到根句柄,TVGN_NEXTVISIBLE得到下一个可见项目的句柄);

TVM_EXPAND:展开或折叠指定项目(参数:TVE_EXPAND展开指定项目);

TVM_SELECTITEM:选中指定项目。

利用这些消息和SendMessage()函数,我们可以很容易写出遍历代码。

二:具体实践

在本文所提供的DEMO中,有一段将十六进制字符串转换成十进制无符号长整型的代码,作用是将用户输入的十六进制TV句柄值转换成十进制并存放在变量dec_sum中。此代码不列入本文讨论的范畴,大家不闲弱智的话就将就着用吧。下面是实现遍历功能的关键代码:

01. /*  Tree-View Control_Demo_SeqShow 1.0 版
02. *   版权所有 (C) 2006 天津 赵春生
03. *   2006.08.28
05. *   http://timw.126.com
06. *   本程序能顺序遍历TV控件中的所有项目。
07. *   代码在Win2000P+SP4 + VC6+SP6测试通过。
08. */
09.  
10. if(error==0)//如果在数据验证转换的过程中未出现错误(error==0时无错误)
11. {
12.  
13. //下面为核心部分:顺序显示(选中)指定Tree-View控件中的所有Item.
14.  
15. hwnd=HWND(dec_sum);//得到转换后的数据
16.  
17. //得到根句柄
18. tvitem.hItem=(HTREEITEM)::SendMessage(hwnd, TVM_GETNEXTITEM,TVGN_ROOT, 0x0);
19. ::SendMessage(hwnd, TVM_SELECTITEM,TVGN_CARET, (long)tvitem.hItem);//选中状态
20.  
21. while((long)tvitem.hItem)
22. {
23. //当此项目能展开时
24. while(::SendMessage(hwnd, TVM_EXPAND,TVE_EXPAND, (long)tvitem.hItem))
25. {
26. //选择下一个可见项目
27. tvitem.hItem=(HTREEITEM)::SendMessage(hwnd,
28. TVM_GETNEXTITEM,TVGN_NEXTVISIBLE,
29. (long)tvitem.hItem);
30.  
31. //选中状态
32. ::SendMessage(hwnd, TVM_SELECTITEM,TVGN_CARET, (long)tvitem.hItem);
33. continue;
34. }
35.  
36.  
37. //当不能再展开的时候,选择下一个可见项目
38. tvitem.hItem=(HTREEITEM)::SendMessage(hwnd,
39. TVM_GETNEXTITEM,TVGN_NEXTVISIBLE,
40. (long)tvitem.hItem);
41.  
42. //选中状态
43. ::SendMessage(hwnd, TVM_SELECTITEM,TVGN_CARET,
44. (long)tvitem.hItem);
45.  
46. }
47. }
48.  
49. //释放内存
50. CloseHandle(hwnd);
51. //顺序显示(选中)完毕

三:TV_Demo_SeqShow的使用方法(图2):

图二

1.用SPY++的[Find Window]功能获得目标TV的句柄;

2.将句柄值输入到TV_Demo_SeqShow中的[Tree-View Control''s Handle:];

3.点击[GO!];

如果你把[Windows 资源管理器]中的[文件夹]作为目标,那你可要作好心理准备了……如果实在忍受不了这种刺激,干脆把管理器关掉就可以了。

第二部分:查找外部程序Tree-View中的项目

一:程序说明:

我们已经成功得对外部程序Tree-View中的项目进行了遍历,如果能在遍历的过程中读取每一个项目的名称,结合我们给定的项目名进行比较,那么查找某个项目的问题将变得易如反掌。由此可见:关键的问题是如何读取项目的名称。

读取项目的名称要发送TVM_GETITEM消息,由于该消息需要为LPARAM参数提供一个TV_ITEM结构的地址,在跨进程发送消息的前提下,为了使外部程序正常使用该内存地址,所以我们必须将TV_ITEM结构插入到目标进程的地址空间中去,代码如下:

1. ptvitem=(TVITEM*)VirtualAllocEx(hProcess,NULL,sizeof(TVITEM),MEM_COMMIT,PAGE_READWRITE);//分配内存
2. WriteProcessMemory(hProcess,ptvitem,&tvitem,sizeof(TVITEM),NULL);//写入内存

在写入内存之前,要将TV_ITEM结构配置好:

1. tvitem.mask=TVIF_TEXT;
2. tvitem.cchTextMax=512;
3. tvitem.pszText=pItem;

mask要设置成TVIF_TEXT,因为我们需要的是pszText的值;cchTextMax可以设置得稍微大一些,cchTextMax=512即可;hItem的值用来指定究竟哪个项目来接收TVM_GETITEM消息,该值在遍历的过程中动态获得;重要的是用来存放项目名称的缓冲区地址,即pszText参数的设置:和TV_ITEM结构一样,也要把她插入到目标进程的地址空间中去:

1. pItem=(char*)VirtualAllocEx(hProcess,NULL,16,MEM_COMMIT,PAGE_READWRITE);

二:具体实践:

作为演示,下面的这段程序将在我们指定的Tree-View控件中查找我们需要的项目,在发现第一个部分匹配的项目后,程序将停止运行,不再进行查找操作。作为演示程序,程序并没有做速度上的优化,大家在具体应用的过程中可自行修改。程序找到目标后的效果图(图 三):

 

001. /*  Tree-View Control_Demo_SeqSearch 1.0 版
002. *   版权所有 (C) 2006 天津 赵春生
003. *   2006.08.28
004. *   http://timw.yeah.net
005. *   http://timw.126.com
006. *   本程序能按用户指定的项目名称顺序查找TV控件中的项目。
007. *   代码在Win2000P+SP4 + VC6+SP6测试通过。
008. */
009.  
010. if(error==0)//如果在数据验证转换的过程中未出现错误(error==0时无错误)
011. {
012.  
013. //下面为核心部分:按用户指定的项目名称顺序查找Tree-View控件中的Item.
014.  
015. hwnd=HWND(dec_sum);//得到转换后的数据
016.  
017. GetWindowThreadProcessId(hwnd, &PID);
018.  
019. hProcess=OpenProcess(PROCESS_ALL_ACCESS,false,PID);
020. if (!hProcess)
021. MessageBox("获取进程句柄操作失败!","错误!");
022. else
023. {
024. ptvitem=(TVITEM*)VirtualAllocEx(hProcess,
025. NULL,
026. sizeof(TVITEM),
027. MEM_COMMIT,
028. PAGE_READWRITE);
029. pItem=(char*)VirtualAllocEx(hProcess,
030. NULL,
031. 16,
032. MEM_COMMIT,
033. PAGE_READWRITE);
034.  
035. if (!ptvitem)
036. MessageBox("无法分配内存!","错误!");
037. else
038. {
039. MessageBox("本演示程序将按用户指定的项目名称顺序查找。","提示");
040.  
041. tvitem.mask=TVIF_TEXT;
042. tvitem.cchTextMax=512;
043. tvitem.pszText=pItem;
044.  
045. //得到根句柄
046. tvitem.hItem=(HTREEITEM)::SendMessage(hwnd,
047. TVM_GETNEXTITEM,
048. TVGN_ROOT,
049. 0x0);
050.  
051. //选中状态
052. ::SendMessage(hwnd,
053. TVM_SELECTITEM,
054. TVGN_CARET,
055. (long)tvitem.hItem);
056.  
057. //将设置好的结构插入目标进程
058. WriteProcessMemory(hProcess,
059. ptvitem,
060. &tvitem,   
061. sizeof(TVITEM), NULL);
062.  
063. //发送TVM_GETITEM消息
064. ::SendMessage(hwnd,
065. TVM_GETITEM,
066. 0,
067. (LPARAM)ptvitem);
068.  
069. //获取pszText
070. ReadProcessMemory(hProcess, pItem, ItemBuf, 512, NULL);
071.  
072. //MessageBox(ItemBuf,"ITEM TEXT");
073. if( strnicmp( ItemBuf,
074. str_item_text,
075. strlen(str_item_text) ) == 0)
076. {
077. MessageBox("已经找到!","恭喜");
078. Bingo=1;
079. //如果根就是我们要找的目标,那么程序执行到这里就可以结束了。
080. tvitem.hItem=(HTREEITEM)0x0;
081. }
082.  
083. while((long)tvitem.hItem)
084. {
085. //当此项目能展开时
086. while(::SendMessage(hwnd,
087. TVM_EXPAND,
088. TVE_EXPAND,
089. (long)tvitem.hItem))
090. {
091.  
092. //选择下一个可见项目
093. tvitem.hItem=(HTREEITEM)::SendMessage(hwnd,
094. TVM_GETNEXTITEM,TVGN_NEXTVISIBLE,
095. (long)tvitem.hItem);
096. //选中状态
097. ::SendMessage(hwnd,
098. TVM_SELECTITEM,TVGN_CARET,
099. (long)tvitem.hItem);
100.  
101. //将设置好的结构插入目标进程
102. WriteProcessMemory(hProcess,
103. ptvitem,
104. &tvitem,
105. sizeof(TVITEM),
106. NULL);
107. //发送TVM_GETITEM消息
108. ::SendMessage(hwnd,
109. TVM_GETITEM,
110. 0,
111. (LPARAM)ptvitem);
112.  
113. //获取pszText
114. ReadProcessMemory(hProcess,
115. pItem,
116. ItemBuf,
117. 512,
118. NULL);
119.  
120. //MessageBox(ItemBuf,"ITEM TEXT");
121. if( strnicmp( ItemBuf,
122. str_item_text,
123. strlen(str_item_text) ) == 0)
124. {
125. MessageBox("已经找到!","恭喜");
126. Bingo=1;
127.  
128. //如果发现我们要找的目标,那么程序执行到这里就可以结束了。
129. tvitem.hItem=(HTREEITEM)0x0;
130. break;
131. }
132. continue;
133. }
134.  
135. if(Bingo!=1)
136. {
137. //当不能再展开的时候,选择下一个可见项目
138. tvitem.hItem=(HTREEITEM)::SendMessage(hwnd,
139. TVM_GETNEXTITEM,TVGN_NEXTVISIBLE,
140. (long)tvitem.hItem);
141.  
142. //选中状态
143. ::SendMessage(hwnd,
144. TVM_SELECTITEM,
145. TVGN_CARET,
146. (long)tvitem.hItem);
147.  
148. //将设置好的结构插入目标进程
149. WriteProcessMemory(hProcess,
150. ptvitem,
151. &tvitem,
152. sizeof(TVITEM),
153. NULL);
154.  
155. //发送TVM_GETITEM消息
156. ::SendMessage(hwnd,
157. TVM_GETITEM,
158. 0,
159. (LPARAM)ptvitem);
160.  
161. ReadProcessMemory(hProcess,
162. pItem,
163. ItemBuf,
164. 512,
165. NULL);//获取pszText
166.  
167. //MessageBox(ItemBuf,"ITEM TEXT");
168. if( strnicmp( ItemBuf,
169. str_item_text,
170. strlen(str_item_text) ) == 0)
171. {
172. MessageBox("已经找到!","恭喜");
173. Bingo=1;
174.  
175. //如果发现我们要找的目标,那么程序执行到这里就可以结束了。
176. tvitem.hItem=(HTREEITEM)0x0;
177. break;
178. }
179. }
180.  
181. }
182. }
183. }
184. }
185.  
186. //释放内存
187. CloseHandle(hwnd);
188. CloseHandle(hProcess);
189. VirtualFreeEx(hProcess, ptvitem, 0, MEM_RELEASE);
190. //顺序查找完毕

结束语

代码写得不够幽雅,大家见笑了。在此之前,类似的拙文我已经写了四篇,希望大家看完后能举一反三。谢谢。

向其他程序的ListView控件发送LVM_GETITEMTEXT

如何选中其他程序ListView控件中的某个Item

如何更改其他程序ListView控件中某个Item的内容

如何获取其他程序RichEdit控件中的内容


  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值