VB.NET自動操做其餘程序(4)--讀取、設置其餘軟件listview控件的內容

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 IntegerAs 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 IntegerByVal cols As IntegerAs 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 IntegerByVal cols As IntegerByVal ItmeValue As StringAs 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 html

相關文章
相關標籤/搜索