?
Solved

Finding a record in an EXTERNAL ListView

Posted on 2006-05-15
4
Medium Priority
?
956 Views
Last Modified: 2008-01-09
I have the handle to a ListView in another process; i.e. the ListView in the "Add Printer Wizard"

This list contains the list of all available drivers for printers, and I want to be able to write a VB procedure to select a desired Printer from that list...

At the moment, I have the handle to the ListView, and have been trying to use SendMessage with LVM_FINDITEM, but it always returns -1.

I have even tried allocating memory space in the process's memory space for my objects, as I noticed it was required in order to receive the Text property of an item in an external ListView.

Perhaps someone can provide some sample code to do this? This is what I have so far...


Private Const LVFI_PARTIAL = &H8
Private Const LVFI_STRING = &H2
Private Const LVFI_WRAP = &H20
Private Const LVIF_STATE = &H8
Private Const LVIF_TEXT = &H1
Private Const LVIS_FOCUSED = &H1
Private Const LVIS_SELECTED = &H2
Private Const LVM_FIRST = &H1000
Private Const LVM_GETITEMCOUNT = LVM_FIRST + 4
Private Const LVM_GETITEM = LVM_FIRST + 5
Private Const LVM_FINDITEM = LVM_FIRST + 13
Private Const LVM_ENSUREVISIBLE = LVM_FIRST + 19
Private Const LVM_SETITEMSTATE = LVM_FIRST + 43
Private Const LVM_GETITEMTEXT = LVM_FIRST + 45
Private Const LVM_GETSELECTEDCOUNT = LVM_FIRST + 50
Private Const MAX_LVMSTRING = 255&
Private Const MEM_COMMIT = &H1000
Private Const MEM_RELEASE = &H8000
Private Const PAGE_READWRITE = &H4
Private Const PROCESS_QUERY_INFORMATION = 1024
Private Const PROCESS_VM_OPERATION = &H8
Private Const PROCESS_VM_READ = &H10
Private Const PROCESS_VM_WRITE = &H20
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000

' SendMessage types for finding a ListView item
Private Type m_typPoint
    x As Long
    y As Long
End Type
Private Type m_typListViewFindInfo
    flags As Long
    psz As String
    lParam As Long
    pt As m_typPoint
    vkDirection As Long
End Type
Private Type m_typListViewItem
   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 Enum m_typListViewTypes
    lvtFind = 1
    lvtItem = 2
End Enum

Private m_btBuffer() As Byte
Private m_hBufferMem As Long
Private m_hProcess As Long
Private m_hTypeMem As Long
Private m_lvwFind As m_typListViewFindInfo
Private m_lvwItem As m_typListViewItem

Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32.dll" (ByVal m_hProcess As Long, ByVal lpBaseAddress As Any, ByRef lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private 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
Private Declare Function VirtualAllocEx Lib "kernel32.dll" (ByVal m_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.dll" (ByVal m_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 m_hProcess As Long, ByVal lpBaseAddress As Any, ByRef lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long

Private Function ListView_MemoryInit(hListView As Long, ListViewType As m_typListViewTypes) As Boolean

Dim lProcessID As Long

ReDim m_btBuffer(MAX_LVMSTRING) As Byte

' Get the Thread Process ID in which the ListView is contained
Call GetWindowThreadProcessId(hListView, lProcessID)

' Open a handle to the process with the ListView
m_hProcess = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, lProcessID)
' Allocate the memory for the Buffer in the process's memory space
m_hBufferMem = VirtualAllocEx(m_hProcess, 0, MAX_LVMSTRING, MEM_COMMIT, PAGE_READWRITE)

' Initiate the Type being used (whether a ListItem or FindItem)
Select Case ListViewType
Case lvtFind
    ' Allocate the memory for the Type in the process's memory space
    m_hTypeMem = VirtualAllocEx(m_hProcess, 0, Len(m_lvwFind), MEM_COMMIT, PAGE_READWRITE)
    ' Write the Type into the allocated memory space
    Call WriteProcessMemory(m_hProcess, m_hTypeMem, m_lvwFind, Len(m_lvwFind), 0)
Case lvtItem
    m_lvwItem.pszText = m_hBufferMem
    m_lvwItem.cchTextMax = MAX_LVMSTRING

    ' Allocate the memory for the Type in the process's memory space
    m_hTypeMem = VirtualAllocEx(m_hProcess, 0, Len(m_lvwItem), MEM_COMMIT, PAGE_READWRITE)
    ' Write the Type into the allocated memory space
    Call WriteProcessMemory(m_hProcess, m_hTypeMem, m_lvwItem, Len(m_lvwItem), 0)
End Select

ListView_MemoryInit = True

End Function

Private Function ListView_MemoryRead(hListView As Long, ListViewType As m_typListViewTypes) As Boolean

' Read in the Buffer from the process's memory space
Call ReadProcessMemory(m_hProcess, m_hBufferMem, m_btBuffer(0), MAX_LVMSTRING, 0)

Select Case ListViewType
Case lvtFind
    ' Read in the Type from the process's memory space
    Call ReadProcessMemory(m_hProcess, m_hTypeMem, m_lvwFind, Len(m_lvwFind), 0)
Case lvtItem
    ' Read in the Type from the process's memory space
    Call ReadProcessMemory(m_hProcess, m_hTypeMem, m_lvwItem, Len(m_lvwItem), 0)
End Select

ListView_MemoryRead = True

End Function

Private Function ListView_MemoryTerminate(hListView As Long, ListViewType As m_typListViewTypes) As Boolean

' Deallocate the process's memory space
Call VirtualFreeEx(m_hProcess, m_hBufferMem, 0, MEM_RELEASE)
Call VirtualFreeEx(m_hProcess, m_hTypeMem, 0, MEM_RELEASE)

' Close the handle to the Process
Call CloseHandle(m_hProcess)

ListView_MemoryTerminate = True

End Function

Public Function ListView_SelectByText(hListView As Long, ByVal sMatch As String, Optional bPartial As Boolean = True, Optional ByVal lIndex As Long = -1) As Long
'-----------------------------------------------------------------------
' Description : Returns the Index of the ListView item matching sMatch
'-----------------------------------------------------------------------

' Set the default return
ListView_SelectByText = -1

' Build the Search object
With m_lvwFind
    .flags = LVFI_STRING Or LVFI_WRAP
    .psz = sMatch & vbNullChar
    If bPartial Then .flags = .flags Or LVFI_PARTIAL
End With

' Initiate the connection to the ListView
If Not ListView_MemoryInit(hListView, lvtFind) Then GoTo PROCEDURE_EXIT

' Search the ListView for a string
lIndex = SendMessage(hListView, LVM_FINDITEM, lIndex, m_lvwFind)

' Read in the memory from the ListView process
If Not ListView_MemoryRead(hListView, lvtFind) Then GoTo PROCEDURE_EXIT

' If successfully, select it
If lIndex <> -1 And ListView_ItemSelect(hListView, lIndex) Then
    Call SendMessage(hListView, LVM_ENSUREVISIBLE, lIndex, 0&)
End If

' Close the connection to the ListView
If Not ListView_MemoryTerminate(hListView, lvtFind) Then GoTo PROCEDURE_EXIT

' Return the Index of the found ListItem
ListView_SelectByText = lIndex

PROCEDURE_EXIT:
End Function
0
Comment
Question by:PhilAI
  • 2
3 Comments
 
LVL 28

Expert Comment

by:Ark
ID: 16687819
Here is an error
lIndex = SendMessage(hListView, LVM_FINDITEM, lIndex, m_lvwFind)
Yuo need pass memory address in remote process instead of structure:

lIndex = SendMessage(hListView, LVM_FINDITEM, lIndex, m_hTypeMem)

0
 
LVL 28

Accepted Solution

by:
Ark earned 1020 total points
ID: 16687823
PS. You can look on my LVDuplicate (and other duplicates from remote processes) sample at http://vbrussian.com/download.asp?Type=Example&ID=116
0
 
LVL 6

Author Comment

by:PhilAI
ID: 16692935
Many thanks, I will do some testing tomorrow
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I’ve seen a number of people looking for examples of how to access web services from VB6.  I’ve been using a test harness I built in VB6 (using many resources I found online) that I use for small projects to work out how to communicate with web serv…
When designing a form there are several BorderStyles to choose from, all of which can be classified as either 'Fixed' or 'Sizable' and I'd guess that 'Fixed Single' or one of the other fixed types is the most popular choice. I assume it's the most p…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Suggested Courses
Course of the Month15 days, 21 hours left to enroll

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question