(四)C# QQ讨论组广告群发工具——操作QQ的TreeView控件(附源码)

作者: 时间: 2012-04-24 分类: 技术文章 | 7 评论数 |

您的支持,是我前进的动力

C#,QQ讨论组广告群发工具——操作QQ的TreeView控件,通过spy++我们可以发现类ATL:30A57F50为treeview控件。C#/Java技术交流群:96020642,传送门:Rolends

我们需实现如下对treeview的操作:

1),遍历获取信息 2),单选 3),多选

(四)C# QQ讨论组广告群发工具——操作QQ的TreeView控件(附源码)

操作其他进程的步骤这个不区分语言的,一般实现过程如下

1),打开远程进程,这个调用API 函数 OpenProcess来实现
2),分配远程内存,调用API VirtualAllocEx 来实现,当然不是绝对的,当操作是不需要对象,而是通过SendMessage直接返回时就不需要分配
3),内存复制,由本地进程内存复制到远程进程内存,使用WriteProcessMemory来实现,同上不是绝对,只有调用需要读取对象信息时,才有需要
4),发送消息,发送消息就不用说了SendMessage
5),上面发送的消息结果,如果是写入对象的话,那么我们需要读取远程内存到本地和3相反,ReadProcessMemory
6),完了?,没有的.资源没释放,OK,释放资源,一般意义上就完成了

上面所有的步骤在vc里一般都这样实现的,我来讲解一下在C#如何实现操作其他进程的TreeView。

1),获取Treeview控件句柄使用API FindWindowEx来实现

下面这个函数是找出所有控件,可以调用之后判断className来获取到控件指针

 C# Code By wuleba.com
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static List<IntPtr> FindControl (IntPtr hwnd, string className, string title = null)

{

    List<IntPtr> controls = 
new List<IntPtr>();

    IntPtr handle = IntPtr.Zero;

    
while (true)

    {

        IntPtr tmp = handle;

        handle = WinAPIHelper.FindWindowEx (hwnd, tmp, className, title);

        
if (handle != IntPtr.Zero)

        {

            controls.Add (handle);

        }

        
else

            
break;

    }

    
return controls;

}

2),读取item

a),获取根节点:

 C# Code By wuleba.com
1
int retval = WinAPIHelper.SendMessage (hwnd, (int) WinAPIHelper.TV_Messages.TVM_GETNEXTITEM, (int) WinAPIHelper.TVM_GETNEXTITEM.TVGN_ROOT, IntPtr.Zero);

返回值为节点指针。

b),选择获取到的项:

 C# Code By wuleba.com
1
int r1 = WinAPIHelper.SendMessage (hwnd, (int) WinAPIHelper.TV_Messages.TVM_SELECTITEM,   (int) WinAPIHelper.TVM_GETNEXTITEM.TVGN_CARET, new IntPtr (retval) );

返回值为操作结果。

c),展开选中项:

 C# Code By wuleba.com
1
int r2 = WinAPIHelper.SendMessage (hwnd, (int) WinAPIHelper.TV_Messages.TVM_EXPAND,   (int) WinAPIHelper.TVM_EXPAND.TVE_EXPAND, new IntPtr (retval) );

返回操作结果。

d),声明ITEM并写入远程内存:

 C# Code By wuleba.com
1
2
3
4
5
6
7
8
9
WinAPIHelper.TVITEM tvItem = new WinAPIHelper.TVITEM();

int size = Marshal.SizeOf (tvItem);

tvItem.mask = WinAPIHelper.TVIF_TEXT;

tvItem.hItem = (IntPtr) retval;

tvItem.pszText = (IntPtr) (remoteBuffer.ToInt32() + size + 
1);

tvItem.cchTextMax = 
255;

localBuffer = Marshal.AllocHGlobal (Marshal.SizeOf (tvItem) );

Marshal.StructureToPtr (tvItem, localBuffer, 
false);

bSuccess = WinAPIHelper.WriteProcessMemory (hProcess, remoteBuffer, 
ref tvItem, size, IntPtr.Zero);

关于item定义,大家可查询MSDN:

e),发送获取Item消息:

 C# Code By wuleba.com
1
WinAPIHelper.SendMessage (hwnd, (int) WinAPIHelper.TV_Messages.TVM_GETITEM, 0, remoteBuffer);

f),读取远程内存:

 C# Code By wuleba.com
1
bSuccess = WinAPIHelper.ReadProcessMemory (hProcess, remoteBuffer, localBuffer, buff_size, IntPtr.Zero);

g),将指针转为结构:

 C# Code By wuleba.com
1
WinAPIHelper.TVITEM retItem = (WinAPIHelper.TVITEM) Marshal.PtrToStructure (localBuffer, (Type) typeof (WinAPIHelper.TVITEM) )

经过上面的操作我们就获取到了选定的某一项的信息,接下来我们使用:

 C# Code By wuleba.com
1
retval = WinAPIHelper.SendMessage (hwnd, (int) WinAPIHelper.TV_Messages.TVM_GETNEXTITEM, (int) WinAPIHelper.TVM_GETNEXTITEM.TVGN_NEXTVISIBLE, new IntPtr (retval) );

来选择下一个项在进行上面的操作,直到返回值为空位置:

3),多选实现,多选我们需要通过修改ITEM的状态来实现

a),声明ITEM(操作为更改状态)

 C# Code By wuleba.com
1
2
3
4
5
inAPIHelper.TVITEM tvItem = new WinAPIHelper.TVITEM();

tvItem.hItem = items[i].Handle;

tvItem.mask = WinAPIHelper.TVIF_STATE;

tvItem.state = WinAPIHelper.TVIS_SELECTED;

tvItem.stateMask = WinAPIHelper.TVIS_SELECTED;

b),分配远程内存

 C# Code By wuleba.com
1
IntPtr remoteBuffer = WinAPIHelper.VirtualAllocEx (hPro, IntPtr.Zero, buff_size, WinAPIHelper.AllocationType.Commit, WinAPIHelper.MemoryProtection.ExecuteReadWrite);

c),写入远程内存

 C# Code By wuleba.com
1
bool result = WinAPIHelper.WriteProcessMemory (hPro, remoteBuffer, ref tvItem, size, IntPtr.Zero);

d),设置状态

 C# Code By wuleba.com
1
int retval = WinAPIHelper.SendMessage (hTv, (int) WinAPIHelper.TV_Messages.TVM_SETITEM, 0, remoteBuffer);

经过上面就实现了为某一项设置选中状态,实际操作中,我们为提高内存使用效率,是先分配缓冲区,在设置(写入)对象,然后发送指令。

下面是完整代码:

 C# Code By wuleba.com
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
public class WinTreeViewItem

{

    
public int Index { get; set; }

    
public int lpAddress { get; set; }

    
public string Text { get; set; }

    
public bool OwnChild { get; set; }

    
public IntPtr Handle { get; set; }

}

public class TreeViewHelper

{

    
const int buff_size = 1024;

    
const int MAX_TVMSTRING = 255;

    
static public List<WinTreeViewItem> GetAllItem (IntPtr hTv)

    {

        
return GetItems (hTv, nullnullint.MaxValue);

    }

    
static public WinTreeViewItem GetItemByText (IntPtr hTv, params string[] text)

    {

        List<
string> containsList = new List<string>();

        
foreach (var item in text)

        {

            
if (item != null && item != “”)

                containsList.Add (item);

        }

        List<WinTreeViewItem> items = GetItems (hTv, containsList, 
null1false);

        
if (items.Count > 0)

            
return items[0];

        
else

            
return null;

    }

    
static public bool SelectItem (IntPtr hTv, WinTreeViewItem item)

    {

        List<WinTreeViewItem> items = 
new List<WinTreeViewItem>();

        items.Add (item);

        
return SelectItems (hTv, items);

    }

    
static public List<WinTreeViewItem> GetItems (IntPtr hTv, List<string> containsList, List<string> withOutList, int takeCount)

    {

        
return GetItems (hTv, containsList, withOutList, takeCount, false);

    }

    
static public List<WinTreeViewItem> GetItems (IntPtr hTv, List<string> containsList, List<string> withOutList, int takeCount, bool isAddParent, int containsPreferenceCount = 0int withOutPreferenceCount = 0)

    {

        
if (withOutPreferenceCount < 1 && containsPreferenceCount < 1)

        {

            
throw new Exception (“两个数量级不能同时为空”);

        }

        
int tryCount = 0;

        IntPtr hPro = WinAPIHelper.OpenProcess (WinAPIHelper.PROCESS_ALL_ACCESS, 
false, WndHelper.GetProcessId (hTv) );

        List<WinTreeViewItem> withOutResultItems = 
new List<WinTreeViewItem>();

        List<WinTreeViewItem> containsResultItems = 
new List<WinTreeViewItem>();

        
int index = 0;

        
int retval = 0;

GETROOT:

        
if (retval == 0)

        {

            tryCount++;

            
if (tryCount > SysConfig.TreeViewItemFindTryCount)

            {

                
return null;

            }

            retval = WinAPIHelper.SendMessage (hTv, (
int) WinAPIHelper.TV_Messages.TVM_GETNEXTITEM, (int) WinAPIHelper.TVM_GETNEXTITEM.TVGN_ROOT, IntPtr.Zero);

            Console.WriteLine (
“根节点” + retval);

            Thread.Sleep (
500);

            
goto GETROOT;

        }

        tryCount = 
0;

        
int itemCount = 0;

FINDCOUNT:

        
if (itemCount == 0)

        {

            tryCount++;

            
if (tryCount > SysConfig.TreeViewItemFindTryCount)

            {

                
return null;

            }

            itemCount = WinAPIHelper.SendMessage (hTv, (
int) WinAPIHelper.TV_Messages.TVM_GETCOUNT, 0, IntPtr.Zero);

            Console.WriteLine (
“可用创建数量” + itemCount);

            Thread.Sleep (
500);

            
goto FINDCOUNT;

        }

        IntPtr pStrBufferMemory = WinAPIHelper.VirtualAllocEx (hPro, IntPtr.Zero, MAX_TVMSTRING, WinAPIHelper.AllocationType.Commit, WinAPIHelper.MemoryProtection.ReadWrite);

        IntPtr remoteBuffer = WinAPIHelper.VirtualAllocEx (hPro, IntPtr.Zero, Marshal.SizeOf (
typeof (WinAPIHelper.TVITEM) ), WinAPIHelper.AllocationType.Commit, WinAPIHelper.MemoryProtection.ExecuteReadWrite);

        
if (remoteBuffer == IntPtr.Zero)

        {

            Console.WriteLine (
“远程地址分配失败”);

            
return null;

        }

        
if (pStrBufferMemory == IntPtr.Zero)

        {

            Console.WriteLine (
“远程地址分配失败”);

            
return null;

        }

        WinAPIHelper.TVITEM tvItem = 
new WinAPIHelper.TVITEM();

        
// int size = Marshal.SizeOf(tvItem);

        tvItem.mask = WinAPIHelper.TVIF_TEXT;

        tvItem.pszText = pStrBufferMemory;

        tvItem.cchTextMax = MAX_TVMSTRING;

        IntPtr localBuffer = Marshal.AllocHGlobal (Marshal.SizeOf (tvItem) );

        Marshal.StructureToPtr (tvItem, localBuffer, 
false);

        
int addCount = 0;

        
string tmpcontxt = “”;

        
while (retval != 0)

        {

            
if (index + 1 > itemCount) break;

            tvItem.hItem = (IntPtr) retval;

            var item = 
new WinTreeViewItem()

            {

                Index = index,

                lpAddress = retval

            };

            
int r1 = WinAPIHelper.SendMessage (hTv, (int) WinAPIHelper.TV_Messages.TVM_SELECTITEM, (int) WinAPIHelper.TVM_GETNEXTITEM.TVGN_CARET, new IntPtr (retval) );

            
if (r1 == 0)

            {

                Console.WriteLine (
“选择项失败”);

                
continue;

            }

            
//Thread.Sleep(100);

            int r2 = WinAPIHelper.SendMessage (hTv, (int) WinAPIHelper.TV_Messages.TVM_EXPAND, (int) WinAPIHelper.TVM_EXPAND.TVE_EXPAND, new IntPtr (retval) );

            
if (r2 == 1)

            {

                
//Console.WriteLine(“可以展开”);

                itemCount = WinAPIHelper.SendMessage (hTv, (int) WinAPIHelper.TV_Messages.TVM_GETCOUNT, 0, IntPtr.Zero);

                item.OwnChild = 
true;

            }

            
else

            {

                
//Console.WriteLine(“不可以展开”);

            }

            
bool bSuccess = WinAPIHelper.WriteProcessMemory (hPro, remoteBuffer, ref tvItem, Marshal.SizeOf (tvItem), IntPtr.Zero);

            
if (bSuccess == false)

            {

                Console.WriteLine (
“写入远程地址失败”);

                
continue;

            }

            
int r3 = WinAPIHelper.SendMessage (hTv, (int) WinAPIHelper.TV_Messages.TVM_GETITEM, 0, remoteBuffer);

            
if (r3 == 0)

            {

                Console.WriteLine (
“选择项操作失败”);

                
continue;

            }

            bSuccess = WinAPIHelper.ReadProcessMemory (hPro, remoteBuffer, localBuffer, Marshal.SizeOf (tvItem), IntPtr.Zero);

            
if (bSuccess == false)

            {

                Console.WriteLine (
“读取远程地址失败”);

                
continue;

            }

            WinAPIHelper.TVITEM retItem = (WinAPIHelper.TVITEM) Marshal.PtrToStructure (localBuffer, (Type) 
typeof (WinAPIHelper.TVITEM) );

            
int readLen = 0;

            IntPtr pStrLocaAddress = Marshal.AllocHGlobal (MAX_TVMSTRING);

            bSuccess = WinAPIHelper.ReadProcessMemory (hPro, pStrBufferMemory, pStrLocaAddress, MAX_TVMSTRING, 
out readLen);

            
string pszItemText = Marshal.PtrToStringUni (pStrLocaAddress);

            
// Console.WriteLine(pszItemText);

            item.Handle = tvItem.hItem;

            item.Text = pszItemText;

            
bool withOutAdd = false;

            
bool containsAdd = false;

            
if (item.OwnChild)

            {

                
goto NEXTITEM;

            }

            
if (containsList != null)

            {

                
foreach (var conItem in containsList)

                {

                    
if (pszItemText.Trim().Contains (conItem.Trim() ) )

                    {

                        containsAdd = 
truegoto ADDITEM;

                    }

                }

            }

            
if (withOutList != null)

            {

                
bool isContains = false;

                
foreach (var outItem in withOutList)

                {

                    
if (pszItemText.Trim().Contains (outItem.Trim() ) )

                    {

                        isContains = 
true;

                        
goto NEXTITEM;

                    }

                }

                
if (!isContains)

                {

                    withOutAdd = 
true;

                    
goto ADDITEM;

                }

            }

ADDITEM:

            
if ( (withOutList == null && containsList == null) || (withOutAdd || containsAdd) )

            {

                
if (withOutAdd)

                {

                    
if (withOutResultItems.Count < withOutPreferenceCount && takeCount – containsPreferenceCount > withOutResultItems.Count)

                    {

                        withOutResultItems.Add (item);

                        addCount++;

                    }

                }

                
if (containsAdd)

                {

                    
if (containsResultItems.Count < containsPreferenceCount && takeCount – withOutPreferenceCount > containsResultItems.Count)

                    {

                        containsResultItems.Add (item);

                        addCount++;

                    }

                }

                containsAdd = 
false;

                withOutAdd = 
false;

                
if (addCount == takeCount)

                    
break;

            }

NEXTITEM:

            retval = WinAPIHelper.SendMessage (hTv, (
int) WinAPIHelper.TV_Messages.TVM_GETNEXTITEM, (int) WinAPIHelper.TVM_GETNEXTITEM.TVGN_NEXTVISIBLE, new IntPtr (retval) );

            index++;

        }

        
if (localBuffer != IntPtr.Zero)

        {

            
try

            {

                Marshal.FreeHGlobal (localBuffer);

            }

            
catch { }

        }

        
if (remoteBuffer != IntPtr.Zero)

        {

            
try

            {

                WinAPIHelper.VirtualFreeEx (hPro, remoteBuffer, 
0, WinAPIHelper.MEM_RELEASE);

            }

            
catch { }

        }

        
if (pStrBufferMemory != IntPtr.Zero)

        {

            
try

            {

                WinAPIHelper.VirtualFreeEx (hPro, pStrBufferMemory, 
0, WinAPIHelper.MEM_RELEASE);

            }

            
catch { }

        }

        
if (hPro != IntPtr.Zero)

        {

            
try

            {

                WinAPIHelper.CloseHandle (hPro);

            }

            
catch { }

        }

        withOutResultItems.AddRange (containsResultItems);

        
return withOutResultItems;

    }

    
static public bool SelectItems (IntPtr hTv, List<WinTreeViewItem> items)

    {

        
if (items.Count < 1return false;

        
int r1 = WinAPIHelper.SendMessage (hTv, (int) WinAPIHelper.TV_Messages.TVM_SELECTITEM, (int) WinAPIHelper.TVM_GETNEXTITEM.TVGN_CARET, items[0].Handle);

        
if (items.Count == 1return r1 == 1 ? true : false;

        IntPtr hPro = WinAPIHelper.OpenProcess (WinAPIHelper.PROCESS_ALL_ACCESS, 
false, WndHelper.GetProcessId (hTv) );

        IntPtr remoteBuffer = WinAPIHelper.VirtualAllocEx (hPro, IntPtr.Zero, buff_size, WinAPIHelper.AllocationType.Commit, WinAPIHelper.MemoryProtection.ExecuteReadWrite);

        
for (int i = 1; i < items.Count; i++)

        {

            WinAPIHelper.TVITEM tvItem = 
new WinAPIHelper.TVITEM();

            tvItem.hItem = items[i].Handle;

            tvItem.mask = WinAPIHelper.TVIF_STATE;

            tvItem.state = WinAPIHelper.TVIS_SELECTED;

            tvItem.stateMask = WinAPIHelper.TVIS_SELECTED;

            
int size = Marshal.SizeOf (tvItem);

            
bool result = WinAPIHelper.WriteProcessMemory (hPro, remoteBuffer, ref tvItem, size, IntPtr.Zero);

            
int retval = WinAPIHelper.SendMessage (hTv, (int) WinAPIHelper.TV_Messages.TVM_SETITEM, 0, remoteBuffer);

            Thread.Sleep (
100);

        }

        
if (remoteBuffer != IntPtr.Zero)

        {

            
try

            {

                WinAPIHelper.VirtualFreeEx (hPro, remoteBuffer, 
0, WinAPIHelper.MEM_RELEASE);

            }

            
catch { }

        }

        
if (hPro != IntPtr.Zero)

        {

            
try

            {

                WinAPIHelper.CloseHandle (hPro);

            }

            
catch { }

        }

        
return true;

    }

}

相关文章:(五)C# QQ讨论组广告群发工具——操作其他进程ListView(附源码)

搜妹子,搜出妹子做壁纸!

本文采用 CC协议 发布,转载请注明:转载自 吾乐吧软件站

本文链接地址:http://www.wuleba.com/?p=2235

7 条评论 给“(四)C# QQ讨论组广告群发工具——操作QQ的TreeView控件(附源码)”

  1. 主要是WinAPIHelper这个类库没有哦[可怜]

  2. 我不想说。。 被这种东西骚扰得够多了 发完就退出关闭 连举报都不行 很恶心人

  3. 很不错,支持

  4. 期待下篇教程,强烈支持

发表评论


微软MSDN资源免费订阅,MSDN 我告诉你