请教,如何用vb.net从系统SysListView32控件中读取文件名称

文久 2012-05-21 09:41:52
最近需要实现一个功能,即从程序外部获得鼠标左键点击选中的文件名称。大体思路如下。
1、设置鼠标钩子。当发生LeftButtionUp事激活处理程序。(注意:这里必须用LeftButtionDown,因为文件选中发生在LeftButtionDown之后,LeftButtionUp之前)
2、使用api WindowFormPoint获得鼠标位置控件,并用GetClassName获得控件类型,如果为SysListView32(WindowsXp以及Windows7桌面、WinServer2008桌面),则处理选中文件。
3、使用sendmessage向SysListView32发消息,获得选中文件的序号。
4、根据选中序号,获得选中文件的文件名。
其中前三步都应经实现,也就是说,已经知道浏览控件类型、当前浏览窗口句柄hwnd,当前选中文件序号SelectedID。
第四步,目前只找到一个vb的列子,自己改写到vb.net中怎么也运行不了。希望各位大侠指点。
vb的例子代码如下:

Option Explicit

Private Type LVITEM
mask As Long
iItem As Long
iSubitem As Long
state As Long
stateMask As Long
pszText As Long
cchTextMax As Long
iImage As Long
lParam As Long
iIndent As Long
End Type

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, lpAddress As Any, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long

Private Const LVIF_IMAGE = &H2
Private Const LVIF_TEXT = &H1
Private Const LVM_FIRST As Long = &H1000
Private Const LVM_GETITEM As Long = (LVM_FIRST + 5)
Private Const LVM_GETITEMCOUNT = (LVM_FIRST + 4)
Private Const LVM_GETITEMSTATE = (LVM_FIRST + 44)
Private Const LVIS_SELECTED = &H2
Private Const LVM_SETITEMSTATE = (LVM_FIRST + 43)
Private Const LVIF_STATE = &H8&

Private Const PAGE_READWRITE = &H4&
Private Const MEM_RESERVE = &H2000
Private Const MEM_COMMIT = &H1000
Private Const MEM_RELEASE = &H8000
Private Const PROCESS_VM_OPERATION = &H8
Private Const PROCESS_VM_READ = &H10
Private Const PROCESS_VM_WRITE = &H20

Function ListViewGetText(ByVal hwnd As Long, ByVal iSubitem As Integer, ByVal iItem As Integer) As String
Dim lngProcID As Long, lngProcHandle As Long
Dim typLvItem As LVITEM, strLvItem As String
Dim lngVarPtr1 As Long, lngVarPtr2 As Long
Dim lngMemVar1 As Long, lngMemVar2 As Long
Dim lngMemLen1 As Long, lngMemLen2 As Long
Call GetWindowThreadProcessId(hwnd, lngProcID)
If lngProcID <> 0 Then
lngProcHandle = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, lngProcID)
If lngProcHandle <> 0 Then
strLvItem = String(255, vbNullChar)
lngVarPtr1 = StrPtr(strLvItem)
lngVarPtr2 = VarPtr(typLvItem)
lngMemLen1 = LenB(strLvItem)
lngMemLen2 = LenB(typLvItem)
lngMemVar1 = VirtualAllocEx(lngProcHandle, 0, lngMemLen1, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
lngMemVar2 = VirtualAllocEx(lngProcHandle, 0, lngMemLen2, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
With typLvItem
.cchTextMax = 255
.iItem = iItem
.iSubitem = iSubitem
.mask = LVIF_TEXT
.pszText = lngMemVar1
End With
Call WriteProcessMemory(lngProcHandle, ByVal lngMemVar1, ByVal lngVarPtr1, lngMemLen1, 0)
Call WriteProcessMemory(lngProcHandle, ByVal lngMemVar2, ByVal lngVarPtr2, lngMemLen2, 0)
Call SendMessage(hwnd, LVM_GETITEM, ByVal 0, ByVal lngMemVar2)
Call ReadProcessMemory(lngProcHandle, ByVal lngMemVar1, ByVal lngVarPtr1, lngMemLen1, 0)
strLvItem = StrConv(strLvItem, vbUnicode)
strLvItem = Left(strLvItem, InStr(1, strLvItem, vbNullChar) - 1)
ListViewGetText = strLvItem
Call VirtualFreeEx(lngProcHandle, ByVal lngMemVar1, lngMemLen1, MEM_RELEASE)
Call VirtualFreeEx(lngProcHandle, ByVal lngMemVar2, lngMemLen2, MEM_RELEASE)
Call CloseHandle(lngProcHandle)
End If
End If
End Function

主要问题就是ListViewGetText中开辟内存和向内存读。strptr和varptr在vb.net中没有,可能自己转到vb.net时有些问题。
...全文
460 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
a1875566250 2012-05-21
  • 打赏
  • 举报
回复
vb.net原生支持UNICODE。
varptr、strptr声明起来用byref。
反正byref就是传址,varptr把传值当成传址,很多时候方便,直接通用声明byval就行。
文久 2012-05-21
  • 打赏
  • 举报
回复
我将找到的代码贴在这里供大家参考,代码已经转为vb.net
1 Option Explicit On
2 Module Module1
3 Public Structure LV_ITEMA
4 Dim mask As Integer
5 Dim iItem As Integer
6 Dim iSubItem As Integer
7 Dim state As Integer
8 Dim stateMask As Integer
9 Dim pszText As Integer
10 Dim cchTextMax As Integer
11 Dim iImage As Integer
12 Dim lParam As Integer
13 Dim iIndent As Integer
14 End Structure
15 'Constants
16 Private Const LVFI_PARAM = 1
17 Private Const LVM_FIRST = &H1000
18 Private Const LVM_FINDITEM = LVM_FIRST + 13
19 Private Const LVM_GETITEMTEXT = LVM_FIRST + 45
20 Private Const LVM_SORTITEMS = LVM_FIRST + 48
21 Private Const LVM_GETHEADER = LVM_FIRST + 31
22 Private Const LVM_GETITEMCOUNT = (LVM_FIRST + 4)
23 Private Const HDM_FIRST = &H1200 '// Header messages
24 Private Const HDM_GETITEMCOUNT = (HDM_FIRST + 0)
25 Private Const HDM_ORDERTOINDEX = (HDM_FIRST + 15)
26 Private Const PROCESS_QUERY_INFORMATION = 1024
27 Private Const PROCESS_VM_OPERATION = &H8
28 Private Const PROCESS_VM_READ = &H10
29 Private Const PROCESS_VM_WRITE = &H20
30 Private Const PROCESS_ALL_ACCESS As Long = &H1F0FFF
31 Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
32 Private Const MAX_LVMSTRING As Integer = 255 '可根椐读取数据长度设置适当的数值
33 Private Const MEM_COMMIT = &H1000
34 Private Const MEM_RELEASE = &H8000
35 Private Const PAGE_READWRITE = &H4
36 Private Const LVIF_TEXT As Integer = &H1
'API declarations
38 Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer
39 Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Byte, ByVal nSize As Integer, ByVal lpNumberOfBytesWritten As Integer) As Integer
40 Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Integer, ByVal lpAddress As Integer, ByVal dwSize As Integer, ByVal dwFreeType As Integer) As Integer
41 Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As LV_ITEMA, ByVal nSize As Integer, ByVal lpNumberOfBytesWritten As Integer) As Integer
42 Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Integer, ByVal lpAddress As Integer, ByVal dwSize As Integer, ByVal flAllocationType As Integer, ByVal flProtect As Integer) As Integer
43 Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcId As Integer) As Integer
44 Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Integer, ByRef lpdwProcessId As Integer) As Integer
45 Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
46 Public Function GetListviewItem(ByVal hWindow As Integer, ByVal ProcessID As Integer, ByVal pColumn As Integer, ByVal pRow As Integer) As String
47 Dim Result As Integer
48 Dim myItem As LV_ITEMA
49 Dim pHandle As Integer
50 Dim pStrBufferMemory As Integer
51 Dim pMyItemMemory As Integer
52 Dim strBuffer() As Byte
53 Dim Index As Integer
54 Dim tmpString As String
55 Dim strLength As Integer
56 '******************************
57 '为动态数组变量重新分配存储空间
58 '******************************
59 ReDim strBuffer(MAX_LVMSTRING)
60 '*****************************************************************************************************
61 '打开一个现有进程的句柄,返回值Long,如执行成功,返回进程句柄;零表示失败。会设置GetLastError
62 'Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
63 '参数 类型及说明
64 'dwDesiredAccess Long,指定这个句柄要求的访问方法。指定API32.TXT文件中以PROCESS_???开头的一个或多个常数
65 'bInheritHandle Long,如句柄能够由子进程继承,则为TRUE
66 'dwProcessId Long,要打开那个进程的进程标识符
67 '*****************************************************************************************************
68 pHandle = OpenProcess(PROCESS_ALL_ACCESS, False, ProcessID)
69 '*****************************************************************************************************
70 'VirtualAllocEx(目标进程的句柄,0,内存区域的大小,分配类型,新分配内存的存取保护类型) 返回所分配页面的基址
71 '*****************************************************************************************************
72 pStrBufferMemory = VirtualAllocEx(pHandle, 0, MAX_LVMSTRING, MEM_COMMIT, PAGE_READWRITE)
73 '*************************************************
74 '初始化LV_ITEM 结构
75 'MyItem.iSubItem 列的索引号
76 'myItem.pszText 数据内容(此处是一个分配的内存地址)
77 '*************************************************
78 myItem.mask = LVIF_TEXT
79 myItem.iSubItem = pColumn
80 myItem.pszText = pStrBufferMemory
81 myItem.cchTextMax = MAX_LVMSTRING
82 '***********************************************************
83 '把这个结构写入远程进程process's 存储量
84 'WriteProcessMemory(目标进程的句柄,地址,写入的数据,字节数,0)
85 '***********************************************************
86 pMyItemMemory = VirtualAllocEx(pHandle, 0, Len(myItem), MEM_COMMIT, PAGE_READWRITE)
87 Result = WriteProcessMemory(pHandle, pMyItemMemory, (myItem), Len(myItem), 0&)
88 '********************************
89 '发送消息,得到项目信息和写入内存
90 '********************************
91 strLength = SendMessage(hWindow, LVM_GETITEMTEXT, pRow, pMyItemMemory)
92 Result = ReadProcessMemory(pHandle, pStrBufferMemory, strBuffer(0), MAX_LVMSTRING, 0)
93 tmpString = System.Text.Encoding.Default.GetString(strBuffer).Trim
94 Result = ReadProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), 0)
95 '****************************
96 '释放分配的内存和关闭进程句柄
97 '****************************
98 Result = VirtualFreeEx(pHandle, pStrBufferMemory, 0, MEM_RELEASE)
99 Result = VirtualFreeEx(pHandle, pMyItemMemory, 0, MEM_RELEASE)
100 Result = CloseHandle(pHandle)
101 If Len(tmpString) > 0 Then GetListviewItem = tmpString
102 End Function
103 End Module
文久 2012-05-21
  • 打赏
  • 举报
回复
a1875566250回答的非常正确,我找到了再vb.net下对应的程序,改动很大,不需要varptr、strptr。而是直接使用byval引用即可。非常感谢a1875566250

1,486

社区成员

发帖
与我相关
我的任务
社区描述
VB API
社区管理员
  • API
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧