VB 5/6-Tipp 0771: Text von fremder ListView und ListViewHeader auslesen
von Frank Schüler
Beschreibung
Mit SendMessage lassen sich einige Informationen von einer fremden ListView auslesen. Nur der Text eines ListViewItems bzw. einen ListViewHeaderItems nicht. Dieses Beispiel zeigt wie es doch geht.
Schwierigkeitsgrad: | Verwendete API-Aufrufe: CloseHandle, FindWindowA (FindWindow), FindWindowExA (FindWindowEx), GetWindowThreadProcessId, OpenProcess, ReadProcessMemory, SendMessageA (SendMessage), VirtualAllocEx, VirtualFreeEx, WriteProcessMemory | Download: |
'Dieser Quellcode stammt von http://www.activevb.de 'und kann frei verwendet werden. Für eventuelle Schäden 'wird nicht gehaftet. 'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. 'Ansonsten viel Spaß und Erfolg mit diesem Source! '----------- Anfang Projektdatei ReadListView.vbp ----------- ' Die Komponente 'Microsoft Windows Common Controls 6.0 (mscomctl.ocx)' wird benötigt. '------- Anfang Formular "frmMain" alias frmMain.frm ------- ' Steuerelement: Schaltfläche "Command1" ' Steuerelement: Listenanzeigesteuerungselement "ListView1" Option Explicit ' Starten Sie zuerst den Taskmanager von Windows und wechseln ' Sie dann auf die Registerkarte "Prozesse". Klicken Sie dann ' auf den Button "Read Taskmanager ListView". Private Sub Form_Load() Me.ScaleMode = vbPixels End Sub Private Sub Command1_Click() Dim hListView As Long ' Handle des SysListView32 im Taskmanager ermitteln hListView = FindTaskmanagerListView ' ist ein Handle vorhanden If hListView <> 0 Then ' ListView auslesen Call ReadFromListView(hListView) End If End Sub ' SysListView32 des Taskmanager finden Private Function FindTaskmanagerListView() As Long Dim lngWnd0 As Long Dim lngWnd1 As Long Dim lngWnd2 As Long Dim lngWnd3 As Long Dim lngWnd4 As Long lngWnd0 = FindWindow("#32770", "Windows Task-Manager") If lngWnd0 <> 0 Then lngWnd1 = FindWindowEx(lngWnd0, 0&, "#32770", vbNullString) If lngWnd1 <> 0 Then lngWnd2 = FindWindowEx(lngWnd1, 0&, "SysListView32", _ "Prozesse") If lngWnd2 <> 0 Then FindTaskmanagerListView = lngWnd2 End If End If End If End Function ' ListView auslesen Private Sub ReadFromListView(ByVal hListViewWnd As Long) Dim xItem As ListItem Dim xColumn As ColumnHeader Dim lngCol As Long Dim lngRow As Long Dim lngColCount As Long Dim lngRowCount As Long Dim lngItem As Long Dim lngHeader As Long ' alle Items löschen ListView1.ListItems.Clear ListView1.ColumnHeaders.Clear ' Reportansicht ListView1.View = lvwReport ' Handle des ListView-Headers ermitteln lngHeader = SendMessage(hListViewWnd, LVM_GETHEADER, 0, 0) ' ist ein Handle vorhanden If lngHeader <> 0 Then ' Anzahl der Headerelemente (Spalten) auslesen lngColCount = SendMessage(lngHeader, HDM_GETITEMCOUNT, 0&, 0&) ' alle Headerelemente durchlaufen For lngItem = 0 To lngColCount - 1 ' Header anlegen Set xColumn = ListView1.ColumnHeaders.Add(, , _ GetHeaderItemString(lngHeader, lngItem)) ' Columnbreite auslesen und für unsere ListView setzen xColumn.Width = SendMessage(hListViewWnd, LVM_GETCOLUMNWIDTH, _ lngItem, 0) Next lngItem End If ' Anzahl der ListView-Elemente (Zeilen) auslesen lngRowCount = SendMessage(hListViewWnd, LVM_GETITEMCOUNT, 0&, 0&) ' alle Zeilen durchlaufen For lngRow = 0 To lngRowCount - 1 ' alle Spalten durchlaufen For lngCol = 0 To lngColCount - 1 ' Spalte 0 If lngCol = 0 Then ' Item in der ListView anlegen Set xItem = ListView1.ListItems.Add(, , _ GetListViewItemString(hListViewWnd, lngRow, lngCol)) Else ' SubItems ausfüllen xItem.SubItems(lngCol) = GetListViewItemString( _ hListViewWnd, lngRow, lngCol) End If Next lngCol Next lngRow End Sub '-------- Ende Formular "frmMain" alias frmMain.frm -------- '--- Anfang Modul "modReadListView" alias modReadListView.bas --- Option Explicit ' ---=== Root Const ===--- Private Const HDM_FIRST As Long = &H1200 Private Const LVM_FIRST As Long = &H1000 ' ---=== Public Const ===--- Public Const HDM_GETITEMCOUNT As Long = (HDM_FIRST + 0) Public Const LVM_GETITEMCOUNT As Long = (LVM_FIRST + 4) Public Const LVM_GETCOLUMNWIDTH As Long = (LVM_FIRST + 29) Public Const LVM_GETHEADER As Long = (LVM_FIRST + 31) ' ---=== Private Const ===--- Private Const HDI_TEXT As Long = &H2 Private Const HDM_GETITEM As Long = (HDM_FIRST + 3) Private Const LVIF_TEXT As Long = &H1 Private Const LVM_GETITEM As Long = (LVM_FIRST + 5) Private Const MAX_LVMSTRING As Long = 255 Private Const MEM_COMMIT As Long = &H1000 Private Const MEM_RELEASE As Long = &H8000 Private Const MEM_RESERVE As Long = &H2000 Private Const PAGE_READWRITE As Long = &H4 Private Const PROCESS_VM_OPERATION As Long = &H8 Private Const PROCESS_VM_READ As Long = &H10 Private Const PROCESS_VM_WRITE As Long = &H20 ' ---=== Type ===--- 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 Type HDITEM mask As Long cxy As Long pszText As Long hbm As Long cchTextMax As Long fmt As Long lParam As Long iImage As Long iOrder As Long Type As Long pvFilter As Long state As Long End Type ' ---=== KERNEL32 ===--- Private Declare Function CloseHandle Lib "kernel32.dll" ( _ ByVal hObject As Long) As Long Private Declare Function OpenProcess Lib "kernel32.dll" ( _ ByVal dwDesiredAccess As Long, _ ByVal bInheritHandle As Long, _ ByVal dwProcessId As Long) As Long Private Declare Function ReadProcessMemory Lib "kernel32.dll" ( _ ByVal hProcess As Long, _ ByVal lpBaseAddress As Long, _ ByRef lpBuffer As Any, _ ByVal nSize As Long, _ ByRef lpNumberOfBytesWritten As Long) As Long Private Declare Function VirtualAllocEx Lib "kernel32.dll" ( _ ByVal hProcess As Long, _ ByVal lpAddress As Long, _ ByVal wSize As Long, _ ByVal flAllocationType As Long, _ ByVal flProtect As Long) As Long Private Declare Function VirtualFreeEx Lib "kernel32.dll" ( _ ByVal hProcess As Long, _ ByVal lpAddress As Long, _ ByVal dwSize As Long, _ ByVal dwFreeType As Long) As Long Private Declare Function WriteProcessMemory Lib "kernel32.dll" ( _ ByVal hProcess As Long, _ ByVal lpBaseAddress As Long, _ ByRef lpBuffer As Any, _ ByVal nSize As Long, _ ByRef lpNumberOfBytesWritten As Long) As Long ' ---=== USER32 ===--- Public Declare Function FindWindow Lib "user32.dll" _ Alias "FindWindowA" ( _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Public Declare Function FindWindowEx Lib "user32.dll" _ Alias "FindWindowExA" ( _ ByVal hWnd1 As Long, _ ByVal hWnd2 As Long, _ ByVal lpsz1 As String, _ ByVal lpsz2 As String) As Long Private Declare Function GetWindowThreadProcessId Lib "user32.dll" ( _ ByVal hwnd As Long, _ ByRef lpdwProcessId As Long) As Long Public Declare Function SendMessage Lib "user32.dll" _ Alias "SendMessageA" ( _ ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ ByRef lParam As Any) As Long Public Function GetListViewItemString(ByVal hListView As Long, Optional _ ByVal Row As Long = 0, Optional ByVal Col As Long = 0) As String Dim hProcess As Long Dim lngLvItemPtr As Long Dim lngProcessID As Long Dim retStr As String Dim bytBuff() As Byte Dim tLVITEM As LVITEM ' ProzessID vom ListView ermitteln If GetWindowThreadProcessId(hListView, lngProcessID) Then ' Handle auf den Prozess öffnen hProcess = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or _ PROCESS_VM_WRITE, False, lngProcessID) ' ist ein Handle vorhanden If hProcess <> 0 Then ' Einen ausreichend großen Speicherbereich im Prozess ' reservieren. Größe der Struktur LVITEM + maximale ' Größe des Strings. Der String soll dann im Speicher ' hinter der Stuktur abgelegt werden. lngLvItemPtr = VirtualAllocEx(hProcess, 0&, Len(tLVITEM) + _ MAX_LVMSTRING, MEM_COMMIT Or MEM_RESERVE, PAGE_READWRITE) ' ist ein Zeiger auf den Speicherbereich vorhanden If lngLvItemPtr <> 0 Then ' LVITEM initialisieren With tLVITEM ' nur den String auslesen .mask = LVIF_TEXT ' Zeile .iItem = Row ' Spalte .iSubItem = Col ' Zeiger auf den Speicherbereich + Größe der ' Struktur LVITEM. Dort soll dann der String ' abgelegt werden. .pszText = lngLvItemPtr + Len(tLVITEM) ' maximale Größe des Strings .cchTextMax = MAX_LVMSTRING End With ' LVITEM in den Speicher an angegebener Speicheradresse ' schreiben If WriteProcessMemory(hProcess, lngLvItemPtr, tLVITEM, _ Len(tLVITEM), ByVal 0&) Then ' ListViewItem-Daten auslesen so wie die Daten an ' angegebener Speicheradresse vorliegen If SendMessage(hListView, LVM_GETITEM, 0&, ByVal _ lngLvItemPtr) Then ' ByteArray zur Aufnahme des Strings dimensionieren ReDim bytBuff(0 To MAX_LVMSTRING) ' String (ByteArray) vom Speicher auslesen. Die ' Speicheradresse ist die wie in LVITEM.pszText ' angegebene Adresse. If ReadProcessMemory(hProcess, lngLvItemPtr + _ Len(tLVITEM), bytBuff(0), MAX_LVMSTRING, _ ByVal 0&) Then ' ByteArray konvertieren retStr = StrConv(bytBuff, vbUnicode) ' String bei vbNullChar abschneiden retStr = Left$(retStr, InStr(1, retStr, _ vbNullChar) - 1) ' String zurück geben GetListViewItemString = retStr End If End If End If ' reservierten Speicher wieder freigeben Call VirtualFreeEx(hProcess, lngLvItemPtr, 0&, MEM_RELEASE) End If ' Handle auf den Prozess schließen Call CloseHandle(hProcess) End If End If End Function Public Function GetHeaderItemString(ByVal hHeader As Long, Optional ByVal _ Item As Long = 0) As String Dim hProcess As Long Dim lngHdrItemPtr As Long Dim lngProcessID As Long Dim retStr As String Dim bytBuff() As Byte Dim tHDITEM As HDITEM ' ProzessID vom Header ermitteln If GetWindowThreadProcessId(hHeader, lngProcessID) Then ' Handle auf den Prozess öffnen hProcess = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or _ PROCESS_VM_WRITE, False, lngProcessID) ' ist ein Handle vorhanden If hProcess <> 0 Then ' Einen ausreichend großen Speicherbereich im Prozess ' reservieren. Größe der Struktur HDITEM + maximale ' Größe des Strings. Der String soll dann im Speicher ' hinter der Stuktur abgelegt werden. lngHdrItemPtr = VirtualAllocEx(hProcess, 0&, Len(tHDITEM) + _ MAX_LVMSTRING, MEM_COMMIT Or MEM_RESERVE, PAGE_READWRITE) ' ist ein Zeiger auf den Speicherbereich vorhanden If lngHdrItemPtr <> 0 Then ' HDITEM initialisieren With tHDITEM ' nur den String auslesen .mask = HDI_TEXT ' Zeiger auf den Speicherbereich + Größe der ' Struktur LVITEM. Dort soll dann der String ' abgelegt werden. .pszText = lngHdrItemPtr + Len(tHDITEM) ' maximale Größe des Strings .cchTextMax = MAX_LVMSTRING End With ' HDITEM in den Speicher an angegebener Speicheradresse ' schreiben If WriteProcessMemory(hProcess, lngHdrItemPtr, tHDITEM, _ Len(tHDITEM), ByVal 0&) Then ' HeaderItem-Daten auslesen so wie die Daten an ' angegebener Speicheradresse vorliegen If SendMessage(hHeader, HDM_GETITEM, Item, ByVal _ lngHdrItemPtr) Then ' ByteArray zur Aufnahme des Strings dimensionieren ReDim bytBuff(0 To MAX_LVMSTRING) ' String (ByteArray) vom Speicher auslesen. Die ' Speicheradresse ist die wie in HDITEM.pszText ' angegebene Adresse. If ReadProcessMemory(hProcess, lngHdrItemPtr + _ Len(tHDITEM), bytBuff(0), MAX_LVMSTRING, _ ByVal 0&) Then ' ByteArray konvertieren retStr = StrConv(bytBuff, vbUnicode) ' String bei vbNullChar abschneiden retStr = Left$(retStr, InStr(1, retStr, _ vbNullChar) - 1) ' String zurück geben GetHeaderItemString = retStr End If End If End If ' reservierten Speicher wieder freigeben Call VirtualFreeEx(hProcess, lngHdrItemPtr, 0&, _ MEM_RELEASE) End If ' Handle auf den Prozess schließen Call CloseHandle(hProcess) End If End If End Function '--- Ende Modul "modReadListView" alias modReadListView.bas --- '------------ Ende Projektdatei ReadListView.vbp ------------
Tipp-Kompatibilität:
Windows/VB-Version | Win32s | Win95 | Win98 | WinME | WinNT4 | Win2000 | WinXP |
VB4 | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
VB5 | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
VB6 | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
Ihre Meinung
Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.