?
Solved

set selected item in external SysListView

Posted on 2007-08-12
8
Medium Priority
?
325 Views
Last Modified: 2008-01-09
I am using vb 2005 and I have to create an itegration with a 3rd party software.  I need a way to select an item in a syslistview of the external program.  I can find the item in the external listview ang get its index number, but then I have not found a way to set it as the selected item.
0
Comment
Question by:pftsupport
  • 5
  • 3
8 Comments
 
LVL 11

Expert Comment

by:AkisC
ID: 19681080
I do not think it can be done, but just to give it a try,
 what is the code you use to find the item in the external listview ang get its index number?
  -andAlso-
 do you have any kind of control, over the 3rd party software?
0
 

Author Comment

by:pftsupport
ID: 19684029
Below is relevent code.  To use, make sure windows explorer is opened to "My Documents" or uncomment relevent code in button click event.
All that is needed on form is button1 and label1.
If you are asking do i have api's for the 3rd party software, the answer is no.
[vb]
Imports System.Text
Imports System.Threading.Thread
Public Class Form1

    Private Declare Function SendMessage Lib "USER32" Alias "SendMessageA" (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As Int32) As Int32
    Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Integer, ByRef lpdwProcessId As Integer) As Integer
    Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcId As Integer) As Integer
    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
    Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Integer, ByVal lpAddress As Integer, ByVal dwSize As Integer, ByVal dwFreeType As Integer) As Integer
    Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As LV_ITEMA, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
    Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As LV_ITEMA, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
    Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As Byte, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer

    Private Const LVM_FIRST As Integer = &H1000
    Private Const LVM_GETNEXTITEM As Integer = (LVM_FIRST + 12)
    Private Const LVNI_SELECTED As Integer = &H2
    Private Const LVM_GETITEMCOUNT As Integer = (LVM_FIRST + 4)
    Private Const LVIF_TEXT As Long = &H1
    Private Const LVM_GETITEMTEXT As Integer = (LVM_FIRST + 45)
    Private Const MAX_LVMSTRING As Integer = 255
    Private Const PROCESS_VM_OPERATION As Short = &H8S
    Private Const PROCESS_VM_READ As Short = &H10S
    Private Const PROCESS_VM_WRITE As Short = &H20S
    Private Const MEM_COMMIT As Short = &H1000S
    Private Const PAGE_READWRITE As Short = &H4S
    Private Const MEM_RELEASE As Short = &H8000S

    Dim iTimer As Integer
    Dim WinExpHnd As Integer

    Private Structure LV_ITEMA
        Dim mask As Integer
        Dim iItem As Integer
        Dim iSubItem As Integer
        Dim state As Integer
        Dim stateMask As Integer
        Dim pszText As Integer
        Dim cchTextMax As Integer
        Dim iImage As Integer
        Dim lParam As Integer
        Dim iIndent As Integer
    End Structure

    Private Function GetListviewItem(ByVal lstviewhwnd As Integer, ByVal ItemToFind As String, ByRef FoundIndex As Integer) As String
        Dim result As Integer
        Dim myItem As LV_ITEMA
        Dim pHandle As Integer
        Dim pStrBufferMemory As Integer
        Dim pMyItemMemory As Integer
        Dim strBuffer() As Byte
        Dim index As Integer
        Dim tmpString As String = String.Empty
        Dim ProcessID As Integer
        Dim itemIndex, ItemNum As Integer
        Dim i As Short
        itemIndex = SendMessage(lstviewhwnd, LVM_GETNEXTITEM, -1, LVNI_SELECTED)
        ItemNum = SendMessage(lstviewhwnd, LVM_GETITEMCOUNT, 0, 0)
        '**********************
        'init the string buffer
        '**********************
        ReDim strBuffer(MAX_LVMSTRING)
        '***********************************************************
        'open a handle to the process and allocate the string buffer
        '***********************************************************
        Call GetWindowThreadProcessId(lstviewhwnd, ProcessID)
        pHandle = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, ProcessID)
        pStrBufferMemory = VirtualAllocEx(pHandle, 0, MAX_LVMSTRING, MEM_COMMIT, PAGE_READWRITE)
        '************************************************************************************
        'initialize the local LV_ITEM structure
        'The myItem.iSubItem member is set to the index of the column that is being retrieved
        '************************************************************************************
        myItem.mask = LVIF_TEXT
        myItem.iSubItem = 0
        myItem.pszText = pStrBufferMemory
        myItem.cchTextMax = MAX_LVMSTRING
        '**********************************************************
        'write the structure into the remote process's memory space
        '**********************************************************
        pMyItemMemory = VirtualAllocEx(pHandle, 0, Len(myItem), MEM_COMMIT, PAGE_READWRITE)
        result = WriteProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), 0)
        '*************************************************************
        '*************************************************************
        'find a specified item in list
        '*************************************************************
        For i = 0 To ItemNum - 1
            '*************************************************************
            'send the get the item message and write back the memory space
            '*************************************************************
            result = SendMessage(lstviewhwnd, LVM_GETITEMTEXT, i, pMyItemMemory)
            result = ReadProcessMemory(pHandle, pStrBufferMemory, strBuffer(0), MAX_LVMSTRING, 0)
            result = ReadProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), 0)
            '**************************************************
            'turn the byte array into a string and send it back
            '**************************************************
            For index = LBound(strBuffer) To UBound(strBuffer)
                If Chr(strBuffer(index)) = vbNullChar Then Exit For
                tmpString = tmpString & Chr(strBuffer(index))
            Next index
            If tmpString = ItemToFind Then
                FoundIndex = i
                Exit For
            End If
            tmpString = String.Empty
        Next
        tmpString = String.Empty
        '*************************************************************
        '*************************************************************
        'find highlighted item in list
        '*************************************************************
        i = itemIndex
        '*************************************************************
        'send the get the item message and write back the memory space
        '*************************************************************
        result = SendMessage(lstviewhwnd, LVM_GETITEMTEXT, i, pMyItemMemory)
        result = ReadProcessMemory(pHandle, pStrBufferMemory, strBuffer(0), MAX_LVMSTRING, 0)
        result = ReadProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), 0)
        '**************************************************
        'turn the byte array into a string and send it back
        '**************************************************
        For index = LBound(strBuffer) To UBound(strBuffer)
            If Chr(strBuffer(index)) = vbNullChar Then Exit For
            tmpString = tmpString & Chr(strBuffer(index))
        Next index
        tmpString = Trim(tmpString)
        '**************************************************
        'deallocate the memory and close the process handle
        '**************************************************
        result = VirtualFreeEx(pHandle, pStrBufferMemory, 0, MEM_RELEASE)
        result = VirtualFreeEx(pHandle, pMyItemMemory, 0, MEM_RELEASE)
        result = CloseHandle(pHandle)
        If Len(tmpString) > 0 Then GetListviewItem = tmpString
        Return tmpString
    End Function

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim ItemIndex As Integer = 0
        '**************************************************
        'uncomment next 2 lines to autmaticly open windows explorer
        '**************************************************
        'Process.Start("explorer.exe")
        'Sleep(1000)
        '**************************************************
        WinExpHnd = GetSubFormByClassNameWithMWClassWithMWCaption("ExploreWClass", "My Documents", "SysListView32", 1)
        Dim s As String = GetListviewItem(WinExpHnd, "My Pictures", ItemIndex)
        Label1.Text = ItemIndex.ToString
       
    End Sub

End Class

Module GetHndMod

    Public Delegate Function EnumChildWindowsCallback(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
    Public Declare Function EnumChildWindows Lib "user32.dll" (ByVal hWndParent As Integer, ByVal lpEnumFunc As EnumChildWindowsCallback, ByVal lParam As Integer) As Integer
    Public Delegate Function EnumWindowsCallback(ByVal hWnd As Integer, ByVal lParam As Integer) As Boolean
    Public Declare Function EnumWindows Lib "user32.dll" Alias "EnumWindows" (ByVal callback As EnumWindowsCallback, ByVal lParam As Integer) As Integer
    Public Declare Sub GetWindowText Lib "user32.dll" Alias "GetWindowTextA" (ByVal hWnd As Integer, ByVal lpString As StringBuilder, ByVal nMaxCount As Integer)
    Public Declare Function GetClassName Lib "user32.dll" Alias "GetClassNameA" (ByVal hwnd As Integer, ByVal lpClassName As StringBuilder, ByVal cch As Integer) As Integer
    Public Declare Auto Function FindWindow Lib "user32.dll" Alias "FindWindow" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
    Public Declare Auto Function FindWindowNullClassName Lib "user32.dll" Alias "FindWindow" (ByVal lpClassName As Integer, ByVal lpWindowName As String) As Integer
    Public Declare Auto Function FindWindowNullWindowCaption Lib "user32.dll" Alias "FindWindow" (ByVal lpClassName As String, ByVal lpWindowName As Integer) As Integer
    Public Declare Function SendMessage Lib "USER32" Alias "SendMessageA" (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As Int32) As Int32
    Public Declare Function SendMessageString Lib "USER32" Alias "SendMessageA" (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As StringBuilder) As Int32

    Const StringBufferLength As Integer = 255
    Const WM_GETTEXT As Integer = &HD

    Dim MWClassName As String
    Dim MWPartialCaption As String
    Dim wHndPartialCap() As Integer
    Dim wHndClassName() As Integer
    Dim SFClassName As String
    Dim SFCaption As String
    Dim SFClassIndex As Integer
    Dim SFClassHit As Integer
    Dim SFHnd As Integer = 0

    Public Function GetSubFormByClassNameWithMWCaption(ByVal MainWindowCaption As String, ByVal SubFormClass As String, ByVal SubFormClassIndex As Integer) As Integer
        Dim i As Integer
        SFHnd = 0
        SFClassHit = 0
        SFClassIndex = SubFormClassIndex
        SFClassName = SubFormClass
        i = EnumChildWindows(GetwHndByCaption(MainWindowCaption), AddressOf EnumChildWindowByClassName, 0)
        GetSubFormByClassNameWithMWCaption = SFHnd
    End Function

    Public Function GetSubFormByCaptionWithMWCaption(ByVal MainWindowCaption As String, ByVal SubFormCaption As String, ByVal SubFormClassIndex As Integer) As Integer
        Dim i As Integer
        SFHnd = 0
        SFClassHit = 0
        SFClassIndex = SubFormClassIndex
        SFCaption = SubFormCaption
        i = EnumChildWindows(GetwHndByCaption(MainWindowCaption), AddressOf EnumChildWindowByCaption, 0)
        GetSubFormByCaptionWithMWCaption = SFHnd
    End Function

    Public Function GetSubFormByClassNameWithMWClass(ByVal MainWindowClass As String, ByVal SubFormClass As String, ByVal SubFormClassIndex As Integer) As Integer
        Dim i As Integer
        SFHnd = 0
        SFClassHit = 0
        SFClassIndex = SubFormClassIndex
        SFClassName = SubFormClass
        i = EnumChildWindows(GetwHndByClassName(MainWindowClass), AddressOf EnumChildWindowByClassName, 0)
        GetSubFormByClassNameWithMWClass = SFHnd
    End Function

    Public Function GetSubFormByCaptionWithMWClass(ByVal MainWindowClass As String, ByVal SubFormCaption As String, ByVal SubFormClassIndex As Integer) As Integer
        Dim i As Integer
        SFHnd = 0
        SFClassHit = 0
        SFClassIndex = SubFormClassIndex
        SFCaption = SubFormCaption
        i = EnumChildWindows(GetwHndByClassName(MainWindowClass), AddressOf EnumChildWindowByCaption, 0)
        GetSubFormByCaptionWithMWClass = SFHnd
    End Function

    Public Function GetSubFormByClassNameWithMWClassWithMWCaption(ByVal MainWindowClass As String, ByVal MainWindowCaption As String, ByVal SubFormClass As String, ByVal SubFormClassIndex As Integer) As Integer
        Dim i As Integer
        SFHnd = 0
        SFClassHit = 0
        SFClassIndex = SubFormClassIndex
        SFClassName = SubFormClass
        i = EnumChildWindows(GetwHndByClassNameByCaption(MainWindowClass, MainWindowCaption), AddressOf EnumChildWindowByClassName, 0)
        GetSubFormByClassNameWithMWClassWithMWCaption = SFHnd
    End Function

    Public Function GetSubFormByCaptionWithMWClassWithMWCaption(ByVal MainWindowClass As String, ByVal MainWindowCaption As String, ByVal SubFormCaption As String, ByVal SubFormClassIndex As Integer) As Integer
        Dim i As Integer
        SFHnd = 0
        SFClassHit = 0
        SFClassIndex = SubFormClassIndex
        SFCaption = SubFormCaption
        i = EnumChildWindows(GetwHndByClassNameByCaption(MainWindowClass, MainWindowCaption), AddressOf EnumChildWindowByCaption, 0)
        GetSubFormByCaptionWithMWClassWithMWCaption = SFHnd
    End Function

    Public Function GetSubFormByClassNameWithMWHnd(ByVal Hnd As Integer, ByVal SubFormClass As String, ByVal SubFormClassIndex As Integer) As Integer
        Dim i As Integer
        SFHnd = 0
        SFClassHit = 0
        SFClassIndex = SubFormClassIndex
        SFClassName = SubFormClass
        i = EnumChildWindows(Hnd, AddressOf EnumChildWindowByClassName, 0)
        GetSubFormByClassNameWithMWHnd = SFHnd
    End Function

    Public Function GetSubFormByCaptionWithMWHnd(ByVal Hnd As Integer, ByVal SubFormCaption As String, ByVal SubFormClassIndex As Integer) As Integer
        Dim i As Integer
        SFHnd = 0
        SFClassHit = 0
        SFClassIndex = SubFormClassIndex
        SFCaption = SubFormCaption
        i = EnumChildWindows(Hnd, AddressOf EnumChildWindowByCaption, 0)
        GetSubFormByCaptionWithMWHnd = SFHnd
    End Function

    Private Function EnumChildWindowByClassName(ByVal hChild As Integer, ByVal lParam As Integer) As Integer
        Dim wClass As New StringBuilder(StringBufferLength)
        GetClassName(hChild, wClass, StringBufferLength)
        If LCase(wClass.ToString) = LCase(SFClassName) Then
            SFClassHit = SFClassHit + 1
            If SFClassHit = SFClassIndex Then
                SFHnd = hChild
                EnumChildWindowByClassName = 0
                Exit Function
            End If
        End If
        EnumChildWindowByClassName = 1  ' Continue enumeration
    End Function

    Private Function EnumChildWindowByCaption(ByVal hChild As Integer, ByVal lParam As Integer) As Integer
        Dim wText As New StringBuilder(StringBufferLength)
        SendMessageString(hChild, WM_GETTEXT, StringBufferLength, wText)
        If LCase(wText.ToString) = LCase(SFCaption) Then
            SFClassHit = SFClassHit + 1
            If SFClassHit = SFClassIndex Then
                SFHnd = hChild
                EnumChildWindowByCaption = 0
                Exit Function
            End If
        End If
        EnumChildWindowByCaption = 1  ' Continue enumeration
    End Function

    Private Function GetwHndByCaption(ByVal MWCaption As String) As Integer
        GetwHndByCaption = FindWindowNullClassName(0, MWCaption)
    End Function

    Private Function GetwHndByClassName(ByVal MWClassName As String) As Integer
        GetwHndByClassName = FindWindowNullWindowCaption(MWClassName, 0)
    End Function

    Private Function GetwHndByClassNameByCaption(ByVal MWClassName As String, ByVal MWCaption As String) As Integer
        GetwHndByClassNameByCaption = FindWindow(MWClassName, MWCaption)
    End Function

    Public Function MWPartialCap(ByVal KnownCaption As String) As Integer()
        Dim iReturn() As Integer = {0}
        GetwHndByPartialCaption(KnownCaption, iReturn)
        MWPartialCap = iReturn
    End Function

    Public Function GetAllMWByClass(ByVal MWClassName As String) As Integer()
        Dim iReturn() As Integer = {0}
        GetwHndByClassName(MWClassName, iReturn)
        GetAllMWByClass = iReturn
    End Function

    Private Function GetwHndByPartialCaption(ByVal PartialCaption As String, ByRef wHnd() As Integer) As Boolean
        MWPartialCaption = PartialCaption
        FindMWPartialCaption()
        wHnd = wHndPartialCap
    End Function

    Private Function GetwHndByClassName(ByVal ClassName As String, ByRef wHnd() As Integer) As Boolean
        MWClassName = ClassName
        FindMWClassName()
        wHnd = wHndClassName
    End Function

    Private Sub FindMWPartialCaption()
        ReDim wHndPartialCap(0)
        EnumWindows(AddressOf FindMWPartialCaptions, 0)
    End Sub

    Private Sub FindMWClassName()
        ReDim wHndClassName(0)
        EnumWindows(AddressOf FindMWClassNames, 0)
    End Sub

    Private Function FindMWPartialCaptions(ByVal hWnd As Integer, ByVal lParam As Integer) As Boolean
        Dim MWCaption As New StringBuilder(StringBufferLength)
        Dim WC As String = String.Empty
        GetWindowText(hWnd, MWCaption, StringBufferLength)
        WC = MWCaption.ToString
        If InStr(WC, MWPartialCaption) Then
            If wHndPartialCap.Length = 1 And wHndPartialCap(0) = 0 Then
                wHndPartialCap(0) = hWnd
            Else
                ReDim Preserve wHndPartialCap(wHndPartialCap.Length)
                Dim i As Integer = wHndPartialCap.Length - 1
                Try
                    wHndPartialCap(i) = hWnd
                Catch
                End Try
            End If
        End If
        'Return True
        FindMWPartialCaptions = 1
    End Function

    Private Function FindMWClassNames(ByVal hWnd As Integer, ByVal lParam As Integer) As Boolean
        Dim wClass As New StringBuilder(StringBufferLength)
        GetClassName(hWnd, wClass, StringBufferLength)
        Dim s As String = wClass.ToString
        If LCase(wClass.ToString) = LCase(MWClassName) Then
            If wHndClassName.Length = 1 And wHndClassName(0) = 0 Then
                wHndClassName(0) = hWnd
            Else
                ReDim Preserve wHndClassName(wHndClassName.Length)
                Dim i As Integer = wHndClassName.Length - 1
                wHndClassName(i) = hWnd
            End If
        End If
        FindMWClassNames = 1
    End Function

End Module
[/vb]
0
 
LVL 11

Expert Comment

by:AkisC
ID: 19685151
It will take me some time to go throught the lines of code
I'll be back either with an anwer :) -or- I did not get one :(
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 11

Expert Comment

by:AkisC
ID: 19690284
The best I came up... I hope it will give an idea -or- it will confuse you more :(

Private Const LVM_FIRST = &H1000&
Private Const LVM_SETITEMPOSITION = (LVM_FIRST + 15)
Public Sub SetItemPosition(ByVal iIndex As Long, ByVal x As Long, ByVal y As
 Long)
Dim tP As POINTAPI
Dim lR As Long
   tP.x = x
   tP.y = y
   lR = SendMessage(lstviewhwnd, LVM_SETITEMPOSITION, iIndex - 1, tP)
End Sub
0
 
LVL 11

Accepted Solution

by:
AkisC earned 2000 total points
ID: 19690289
0
 

Author Comment

by:pftsupport
ID: 19707982
Well the information you are providing is not only for vb6 instead of .net, but it is for a listview that is within your same memory space (program).  When windows moved to 32bit, applications were given their own memory space.  This means that you cannot directly access the memory space of another application but must instead inject into the memory space so that you have an indirect way to communicate.

Does anyone have a solution for selecting an item in an external syslistview with a 32 bit application?

Thanks
0
 

Author Comment

by:pftsupport
ID: 19718398
I found a vb6 solution at another website so I was able to see what needed to be done and then able to create a solution that works in vb2005.
0
 
LVL 11

Expert Comment

by:AkisC
ID: 19720162
Thank you pftsupport
Have fun coding...
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
This Micro Tutorial will teach you how to add a cinematic look to any film or video out there. There are very few simple steps that you will follow to do so. This will be demonstrated using Adobe Premiere Pro CS6.
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Suggested Courses
Course of the Month16 days, 4 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