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

来源:互联网 发布:mac进入屏保快捷键 编辑:程序博客网 时间:2024/06/07 04:44
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
04.*   http://timw.yeah.net
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控件中的内容


原创粉丝点击