外部sysListView32內容獲取及設置選中狀態


public void SetLisSelected(IntPtr listView,List<string> fcusers)
        {
            //該listview總行數
            int rowcnt = API.SendMessage(listView, API.LVM_GETITEMCOUNT, 0, 0);

            //listview的列頭句柄
            int lvHeader = API.SendMessage(listView, API.LVM_GETHEADER, 0, 0);

            uint hProcessId = 0; //列頭的processid
            API.GetWindowThreadProcessId((IntPtr)lvHeader, out hProcessId);    //lvHeader是SysListView的子窗SysHeader32的句柄,lvParent是SysListView的句柄
            IntPtr hProcess = API.OpenProcess(API.PROCESS_VM_OPERATION | API.PROCESS_VM_READ | API.PROCESS_VM_WRITE, false, hProcessId);
            IntPtr hPointer = API.VirtualAllocEx(hProcess, IntPtr.Zero, 4096, API.MEM_RESERVE | API.MEM_COMMIT, API.PAGE_READWRITE);
           
            uint processId; //進程pid 
            API.GetWindowThreadProcessId(listView, out processId);

            //獲取Listview的process句柄
            IntPtr process = API.OpenProcess(API.PROCESS_VM_OPERATION | API.PROCESS_VM_READ | API.PROCESS_VM_WRITE, false, processId);
            //申請代碼的內存區,返回申請到的虛擬內存首地址
            IntPtr pointer = API.VirtualAllocEx(process, IntPtr.Zero, 4096, API.MEM_RESERVE | API.MEM_COMMIT, API.PAGE_READWRITE);

            //取出每行第一列,判斷是否滿足條件
            for (int i = 0; i < rowcnt; i++)
            {
                //如果要返回ListView所有內容,這里加上加上 for (int j = 0; j < cols; j++) 並將下面的 vItem[0].iSubItem = 0 改為=j;
                byte[] vBuffer = new byte[256];//定義一個臨時緩沖區
                API.LVITEM[] vItem = new API.LVITEM[1];
                vItem[0].mask = API.LVIF_TEXT;//說明pszText是有效的
                vItem[0].iItem = i;     //行號
                vItem[0].iSubItem = 0;  //列號
                vItem[0].cchTextMax = vBuffer.Length;//所能存儲的最大的文本為256字節
                vItem[0].pszText = (IntPtr)((int)pointer + Marshal.SizeOf(typeof(API.LVITEM)));
                uint vNumberOfBytesRead = 0;

                //把數據寫到vItem中
                //pointer為申請到的內存的首地址
                //UnsafeAddrOfPinnedArrayElement:獲取指定數組中指定索引處的元素的地址
                API.WriteProcessMemory(process, pointer, Marshal.UnsafeAddrOfPinnedArrayElement(vItem, 0), Marshal.SizeOf(typeof(API.LVITEM)), ref vNumberOfBytesRead);

                //發送LVM_GETITEMW消息給hwnd,將返回的結果寫入pointer指向的內存空間
                API.SendMessage(listView, API.LVM_GETITEMW, i, (int)pointer);

                //從pointer指向的內存地址開始讀取數據,寫入緩沖區vBuffer中
                API.ReadProcessMemory(process, (IntPtr)((int)pointer + Marshal.SizeOf(typeof(API.LVITEM))), Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0), vBuffer.Length, ref vNumberOfBytesRead);

                //string vText = Encoding.Unicode.GetString(vBuffer, 0, (int)vNumberOfBytesRead); //此方法獲取的內容是亂碼                   
                string vText = Marshal.PtrToStringUni(Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0)); //不能用Marshal.PtrToStringAnsi等其他方法,否則內容是亂碼

                string userName = vText;

                if (fcusers.Any(c=>c==userName)) //第一列內容在目標列表中,選中該行
                {
                    int iItem = i; //行號
                    vItem[0].state = API.LVIS_SELECTED;
                    vItem[0].stateMask = API.LVIS_SELECTED;      

                    uint vNumberOfBytesRead0 = 0;
                    API.WriteProcessMemory(hProcess, hPointer, Marshal.UnsafeAddrOfPinnedArrayElement(vItem, 0), Marshal.SizeOf(typeof(API.LVITEM)), ref vNumberOfBytesRead0);
                    API.SendMessage(listView, (uint)API.LVM_SETITEMSTATE, iItem, hPointer.ToInt32());//此處發送消息使得該item被選中
                    //System.Threading.Thread.Sleep(100);
                }
            }

            API.VirtualFreeEx(hProcess, hPointer, 0, API.MEM_RELEASE);
            API.CloseHandle(hProcess);

            API.VirtualFreeEx(process, pointer, 0, API.MEM_RELEASE);//在其它進程中釋放申請的虛擬內存空間,MEM_RELEASE方式很徹底,完全回收
            API.CloseHandle(process);//關閉打開的進程對象
        }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM