标签:
4.3、读取其他软件listview控件的内容
4.3.0、根据窗口句柄,获取进程Id,打开并插入进程,申请代码的内存区,返回申请到的虚拟内存首地址
Dim processId As Integer
‘进程pid
hwnd = FindWindow("#32770", "Windows 任务管理器") ‘获取任务管理器窗口句柄,注释By Lyh
hwnd = FindWindowEx(hwnd, 0, "#32770", Nothing) ‘获取选项卡窗口句柄,注释By Lyh
hwnd = FindWindowEx(hwnd, 0, "SysListView32", Nothing) ‘获取进程列表框ListView窗口句柄,注释By Lyh
headerhwnd = SendMessage(hwnd, LVM_GETHEADER, 0, 0)
‘listview的列头句柄
rows =SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0)
‘总行数,即进程的数量
cols = SendMessage(headerhwnd, HDM_GETITEMCOUNT, 0, 0)
‘列表列数
‘根据窗口句柄,获取进程Id
GetWindowThreadProcessId(hwnd, processId)
‘打开并插入进程
process = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, processId)
‘申请代码的内存区,返回申请到的虚拟内存首地址
pointer = VirtualAllocEx(process, IntPtr.Zero, 4096, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
‘获取ListView样式
If (SendMessage(hwnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0) And LVS_EX_CHECKBOXES = LVS_EX_CHECKBOXES) Then
‘返回‘任务管理器--进程返回,应用程序返回
‘ListView 带检查框
End If
.............调用后边相关函数与过程,实现相应功能,以下为示例代码.............
Dim tempHead As String() = New String(cols - 1) {}
tempHead = GetListViewHead(cols)
ListView1.Columns.Clear()
For j As Integer = 0 To cols - 1
ListView1.Columns.Add(tempHead(j))
Next
Dim tempStr As String(,)
‘二维数组
Dim temp As String() = New String(cols - 1) {}
tempStr = GetListViewItmeValue(rows, cols)
‘将要读取的其他程序中的ListView控件中的文本内容保存到二维数组中
ListView1.Items.Clear()
‘清空LV控件信息
‘输出数组中保存的其他程序的LV控件信息
For i As Integer = 0 To rows - 1
For j As Integer = 0 To cols - 1
temp(j) = tempStr(i, j)
Next
Dim lvi As New ListViewItem(temp)
ListView1.Items.Add(lvi)
Next
.............示例代码.............
VirtualFreeEx(process, pointer, 0, MEM_RELEASE)
‘在其它进程中释放申请的虚拟内存空间,MEM_RELEASE方式很彻底,完全回收
CloseHandle(process)
‘关闭打开的进程对象
4.3.1、获取ListView表头
Private Function GetListViewHead(ByVal cols As Integer) As String()
Dim tempStr As String() = New String(cols - 1) {}
‘一维数组:保存LVHead控件的文本信息
Dim vBuffer As Byte() = New Byte(255) {}
‘定义一个临时缓冲区
Dim vItem As HDITEM = New HDITEM
vItem.mask = HDI_TEXT
vItem.cchTextMax = vBuffer.Length
‘所能存储的最大的文本为字节
vItem.pszText = New IntPtr(CInt(pointer) + Marshal.SizeOf(GetType(HDITEM))) ‘tmpptr ‘DirectCast(CInt(pointer) + Marshal.SizeOf(GetType(HDITEM)), IntPtr)
Dim vNumberOfBytesRead As UInteger = 0
‘把数据写到vItem中
‘pointer为申请到的内存的首地址
Dim ptr As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(vItem)) ‘也可以像GetListViewItmeValue定义一个只有个元素的维数组,以方便的通过UnsafeAddrOfPinnedArrayElement获取地址,就不知道哪个效率更高。
Marshal.StructureToPtr(vItem, ptr, True)
WriteProcessMemory(process, pointer, ptr, Marshal.SizeOf(GetType(HDITEM)), vNumberOfBytesRead)
For j As Integer = 0 To cols - 1
‘发送HDM_GETITEM消息给headerhwnd,将返回的结果写入pointer指向的内存空间
SendMessage(headerhwnd, HDM_GETITEM, j, pointer)
‘从pointer指向的内存地址开始读取数据,写入缓冲区vBuffer中
ReadProcessMemory(process, (CInt(pointer) + Marshal.SizeOf(GetType(HDITEM))), Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0), vBuffer.Length, vNumberOfBytesRead)
tempStr(j) = Encoding.Unicode.GetString(vBuffer, 0, CInt(vNumberOfBytesRead))
Next
‘VirtualFreeEx(process, pointer, 0, MEM_RELEASE) ‘最后才调用,因为程序别的部分还需要用到。
‘在其它进程中释放申请的虚拟内存空间,MEM_RELEASE方式很彻底,完全回收
‘CloseHandle(process) ‘最后才调用,因为程序别的部分还需要用到。
‘关闭打开的进程对象
Return tempStr
End Function
4.3.2、 从内存中读取指定的LV控件的文本内容
以下读取listview内容的代码参考自并作了修改:
C#如何获取其他程序ListView控件中的内容http://www.cnblogs.com/hongfei/archive/2012/12/24/2829799.html
也可参考:参考《向其他程序的ListView控件发送LVM_GETITEMTEXT》
‘‘‘ </summary>
‘‘‘ <param name="rows">要读取的LV控件的行数</param>
‘‘‘ <param name="cols">要读取的LV控件的列数</param>
‘‘‘ <returns>取得的LV控件信息</returns>
Private Function GetListViewItmeValue(ByVal rows As Integer, ByVal cols As Integer) As String(,)
Dim tempStr As String(,) = New String(rows - 1, cols - 1) {}
‘二维数组:保存LV控件的文本信息
Dim vBuffer As Byte() = New Byte(255) {}
‘定义一个临时缓冲区
Dim vItem As LVITEM() = New LVITEM(0) {} ‘定义个只有个元素的维数组,是为了方便通过UnsafeAddrOfPinnedArrayElement获得地址。
vItem(0).mask = LVIF_TEXT ‘Or LVIF_STATE ‘Or LVIF_PARAM ‘Or LVIF_IMAGE ‘
‘说明pszText是有效的
vItem(0).cchTextMax = vBuffer.Length
‘所能存储的最大的文本为字节
Dim vNumberOfBytesRead As UInteger = 0
vItem(0).pszText = New IntPtr(CInt(pointer) + Marshal.SizeOf(GetType(LVITEM))) ‘tmpptr ‘DirectCast(CInt(pointer) + Marshal.SizeOf(GetType(LVITEM)), IntPtr)
For i As Integer = 0 To rows - 1
vItem(0).iItem = i
‘行号
For j As Integer = 0 To cols - 1
vItem(0).iSubItem = j
‘把数据写到vItem中
‘pointer为申请到的内存的首地址
‘UnsafeAddrOfPinnedArrayElement:获取指定数组中指定索引处的元素的地址
WriteProcessMemory(process, pointer, Marshal.UnsafeAddrOfPinnedArrayElement(vItem, 0), Marshal.SizeOf(GetType(LVITEM)), vNumberOfBytesRead)
‘发送LVM_GETITEMW消息给hwnd,将返回的结果写入pointer指向的内存空间
SendMessage(hwnd, LVM_GETITEMW, i, pointer)
‘从pointer指向的内存地址开始读取数据,写入缓冲区vBuffer中
ReadProcessMemory(process, (CInt(pointer) + Marshal.SizeOf(GetType(LVITEM))), Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0), vBuffer.Length, vNumberOfBytesRead)
tempStr(i, j) = Encoding.Unicode.GetString(vBuffer, 0, CInt(vNumberOfBytesRead))
Next
Next
‘VirtualFreeEx(process, pointer, 0, MEM_RELEASE)
‘在其它进程中释放申请的虚拟内存空间,MEM_RELEASE方式很彻底,完全回收
‘CloseHandle(process)
‘关闭打开的进程对象
Return tempStr
End Function
4.3.3、获取ListView样式
‘获取ListView样式
If (SendMessage(hwnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0) And LVS_EX_CHECKBOXES = LVS_EX_CHECKBOXES) Then ‘返回‘任务管理器--进程返回,应用程序返回
MsgBox("ListView 带检查框")
Else
MsgBox("不带检查框")
End If
4.3.4、读取ListView中Checkbox是否Checked
‘读取ListView中Checkbox是否Checked,第三个参数为行。通过第四个参数,获取不同的ITEMSTATE值,例如,LVIS_SELECTED获取是否该行被选中。
If (SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_STATEIMAGEMASK) = 2 << 12) Then
MsgBox("Checked")
Else
MsgBox("UnCheck")
End If
4.3.5、设置checkbox值
‘设置checkbox
‘在commctrl.h中的相关定义:
‘#define INDEXTOSTATEIMAGEMASK(i) ((i) << 12) ’表示i往左移位次,VB.NET也有该运算符。
‘#define ListView_SetCheckState(hwndLV, i, fCheck) \
‘ ListView_SetItemState(hwndLV, i, INDEXTOSTATEIMAGEMASK((fCheck)?2:1), LVIS_STATEIMAGEMASK)
‘#endif
‘说明:INDEXTOSTATEIMAGEMASK((fCheck)?2:1) 为或左移位次,结果即为:&H2000(checkbox选中)及&H1000(checkbox不选中)
‘#define ListView_SetItemState(hwndLV, i, data, mask) \
‘{ LV_ITEM _ms_lvi;\
‘ _ms_lvi.stateMask = mask;\
‘ _ms_lvi.state = data;\
‘ SNDMSG((hwndLV), LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)(LV_ITEM FAR *)&_ms_lvi);\ ‘最后一个参数,只需理解为1个指针就好,不必理会那么多
‘}
‘这个宏定义的意思:传递一个LV_ITEM 结构变量指针,只需设置结构中的stateMask、state为需要的值。
Private Sub SetListViewItmeCheck(ByVal rows As Integer)
Dim vBuffer As Byte() = New Byte(255) {}
‘定义一个临时缓冲区
Dim vItem As LVITEM() = New LVITEM(0) {}
vItem(0).state = &H2000 ‘Checked:2<<12 即是&H2000 ’设置值为LVIS_SELECTED 则可以选中该行
vItem(0).stateMask = LVIS_STATEIMAGEMASK ‘ LVIS_STATEIMAGEMASK ’设置值为LVIS_SELECTED 则可以选中该行
Dim vNumberOfBytesRead As UInteger = 0
‘把数据写到vItem中
‘pointer为申请到的内存的首地址
‘UnsafeAddrOfPinnedArrayElement:获取指定数组中指定索引处的元素的地址
WriteProcessMemory(process, pointer, Marshal.UnsafeAddrOfPinnedArrayElement(vItem, 0), Marshal.SizeOf(GetType(LVITEM)), vNumberOfBytesRead)
‘发送LVM_SETITEMSTATE消息给hwnd,进程从pointer指向的内存空间传递参数,如果只需传递简单的参数,则不需要前面那么多复杂的代码,只需发出下面代码即可。
SendMessage(hwnd, LVM_SETITEMSTATE, rows, pointer)
‘VirtualFreeEx(process, pointer, 0, MEM_RELEASE)
‘在其它进程中释放申请的虚拟内存空间,MEM_RELEASE方式很彻底,完全回收
‘CloseHandle(process)
‘关闭打开的进程对象
End Sub
4.3.6、设置ListVIew控件的文本内容
Private Function SetListViewItmeValue(ByVal rows As Integer, ByVal cols As Integer, ByVal ItmeValue As String) As Integer
Dim vBuffer As Byte() = New Byte(255) {}
‘定义一个临时缓冲区
Dim vItem As LVITEM() = New LVITEM(0) {} ‘定义个只有个元素的维数组,是为了方便通过UnsafeAddrOfPinnedArrayElement获得地址。
vItem(0).mask = LVIF_TEXT ‘Or LVIF_STATE ‘Or LVIF_PARAM ‘Or LVIF_IMAGE ‘
‘说明pszText是有效的
vItem(0).cchTextMax = vBuffer.Length
‘所能存储的最大的文本为字节
Dim vNumberOfBytesRead As UInteger = 0
vItem(0).pszText = New IntPtr(CInt(pointer) + Marshal.SizeOf(GetType(LVITEM))) ‘tmpptr ‘DirectCast(CInt(pointer) + Marshal.SizeOf(GetType(LVITEM)), IntPtr)
‘上面这行,可以用如下形式代码代替。
‘ 参考《向其他程序的ListView控件发送LVM_GETITEMTEXT》中的LVM_SETITEMTEXT部分
‘http://wenku.baidu.com/link?url=BD0hEOPJYYDcgvaG9qrXflpA-ViRnfmlKp6Vo8Z5zTiyDBFSGuCzcCNc_gZ_oxtmMk9s3CJZLDmcv8zfd9wKCXjeZBpWWC1D3C_pbbF0FQ3
‘Dim MypszText As IntPtr = VirtualAllocEx(process, IntPtr.Zero, 256, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
‘vItem(0).pszText = MypszText
‘WriteProcessMemory(process, MypszText, Marshal.StringToHGlobalAuto(ItmeValue), ItmeValue.Length * 2, vNumberOfBytesRead)
vItem(0).iItem = rows
‘行号
vItem(0).iSubItem = cols
‘‘将数据ItmeValue写入vItem的pszText中(StringToHGlobalAuto引用不同的字符串到指针,结果不一样)
‘以及把数据写到vItem中,顺序可互换
‘pointer为申请到的内存的首地址
‘UnsafeAddrOfPinnedArrayElement:获取指定数组中指定索引处的元素的地址
WriteProcessMemory(process, (CInt(pointer) + Marshal.SizeOf(GetType(LVITEM))), Marshal.StringToHGlobalAuto(ItmeValue), ItmeValue.Length * 2, vNumberOfBytesRead)
WriteProcessMemory(process, pointer, Marshal.UnsafeAddrOfPinnedArrayElement(vItem, 0), Marshal.SizeOf(GetType(LVITEM)), vNumberOfBytesRead)
‘发送LVM_SETITEMTEXT消息给hwnd,进程从pointer指向的内存空间传递参数,如果只需传递简单的参数,则不需要前面那么多复杂的代码,只需发出下面代码即可。
SendMessage(hwnd, LVM_SETITEMTEXT, rows, pointer)
‘VirtualFreeEx(process, MypszText, 0, MEM_RELEASE)
‘VirtualFreeEx(process, pointer, 0, MEM_RELEASE)
‘在其它进程中释放申请的虚拟内存空间,MEM_RELEASE方式很彻底,完全回收
‘CloseHandle(process)
‘关闭打开的进程对象
End Function
VB.NET自动操作其他程序(4)--读取、设置其他软件listview控件的内容
标签:
原文地址:http://www.cnblogs.com/lefour/p/5464114.html