由於上篇C#操作QQ的TreeView控件以及詳細講解過如何操作其他進程的控件的流程,所以關於如何操作我就不在啰嗦了
主要實現流程如下
1), 獲取列數
獲取列數需先獲取列的索引指針
columnIndex = WinAPIHelper.SendMessage(lvHwnd, (int)WinAPIHelper.LVM.GETHEADER, 0, 0);
利用列索引指針去獲取列數量
columnCount = WinAPIHelper.SendMessage(new IntPtr(columnIndex), (int)WinAPIHelper.HDM.HDM_GETITEMCOUNT, 0, 0);
2), 獲取行數
rowCount = WinAPIHelper.SendMessage(lvHwnd, (int)WinAPIHelper.LVM.GETITEMCOUNT, 0, 0);
3), 遍歷所有cell,使用LVITEM獲取需要的數據
iRet = WinAPIHelper.SendMessage(lvHwnd, (int)WinAPIHelper.LVM.GETITEMW, j, pItemMemory);
像這些沒有技術難點的東西我會講的少一點,大家可以查MSDN,需要我的APIHelper類,請留言
源代碼
public class WinListViewRow
{
public string[] Cells { get; set; }
}
public class WinListView
{
public WinListView()
{
Rows = new List<WinListViewRow>();
ColumnHeaders = new List<string>();
}
public int RowCount { get; set; }
public int ColumnCount { get; set; }
public List<string> ColumnHeaders { get; set; }
public List<WinListViewRow> Rows { get; set; }
}
public class ListViewHelper
{
const int MAX_LVMSTRING = 512;
public static int GetRowCount(IntPtr lvHwnd)
{
int iRet = WinAPIHelper.SendMessage(lvHwnd, (int)WinAPIHelper.LVM.GETITEMCOUNT, 0, 0);
return iRet;
}
public static string GetItemText(IntPtr lvHwnd, int pRow, int pColumn)
{
byte[] strBuffer = new byte[MAX_LVMSTRING + 1];
IntPtr hPro = WinAPIHelper.OpenProcess(WinAPIHelper.PROCESS_ALL_ACCESS, false, WndHelper.GetProcessId(lvHwnd));
IntPtr pStrBufferMemory = WinAPIHelper.VirtualAllocEx(hPro, IntPtr.Zero, MAX_LVMSTRING, WinAPIHelper.AllocationType.Commit, WinAPIHelper.MemoryProtection.ReadWrite);
WinAPIHelper.LVITEM item = new WinAPIHelper.LVITEM();
item.iSubItem = pColumn;
item.cchTextMax = MAX_LVMSTRING;
item.pszText = pStrBufferMemory;
item.mask = WinAPIHelper.LVIF_TEXT;
IntPtr pItemMemory = WinAPIHelper.VirtualAllocEx(hPro, IntPtr.Zero, Marshal.SizeOf(typeof(WinAPIHelper.LV_ITEM)), WinAPIHelper.AllocationType.Commit, WinAPIHelper.MemoryProtection.ReadWrite);
bool result = WinAPIHelper.WriteProcessMemory(hPro, pItemMemory, ref item, Marshal.SizeOf(item), IntPtr.Zero);
IntPtr pStrLocaAddress = Marshal.AllocHGlobal(MAX_LVMSTRING);
int iRet = WinAPIHelper.SendMessage(lvHwnd, (int)WinAPIHelper.LVM.GETITEMTEXTW, pRow, pItemMemory);
int readLen = 0;
result = WinAPIHelper.ReadProcessMemory(hPro, pStrBufferMemory, pStrLocaAddress, MAX_LVMSTRING, out readLen);
result = WinAPIHelper.ReadProcessMemory(hPro, pItemMemory, ref item, Marshal.SizeOf(item), IntPtr.Zero);
string tmpString2 = Marshal.PtrToStringAuto(pStrLocaAddress);
if (pStrLocaAddress != IntPtr.Zero)
{
try { Marshal.FreeHGlobal(pStrLocaAddress); }
catch { }
}
if (pItemMemory != IntPtr.Zero)
{
try { WinAPIHelper.VirtualFreeEx(hPro, pItemMemory, 0, WinAPIHelper.MEM_RELEASE); }
catch { }
}
if (pStrBufferMemory != IntPtr.Zero)
{
try { WinAPIHelper.VirtualFreeEx(hPro, pStrBufferMemory, 0, WinAPIHelper.MEM_RELEASE); }
catch { }
}
if (hPro != IntPtr.Zero)
{
try { WinAPIHelper.CloseHandle(hPro); }
catch { }
}
return tmpString2;
}
public static WinListView GetListView(IntPtr lvHwnd)
{
WinListView lv = new WinListView();
byte[] strBuffer = new byte[MAX_LVMSTRING + 1];
IntPtr hPro = WinAPIHelper.OpenProcess(WinAPIHelper.PROCESS_ALL_ACCESS, false, WndHelper.GetProcessId(lvHwnd));
IntPtr pStrBufferMemory = WinAPIHelper.VirtualAllocEx(hPro, IntPtr.Zero, MAX_LVMSTRING, WinAPIHelper.AllocationType.Commit, WinAPIHelper.MemoryProtection.ReadWrite);
IntPtr pItemMemory = WinAPIHelper.VirtualAllocEx(hPro, IntPtr.Zero, Marshal.SizeOf(typeof(WinAPIHelper.LV_ITEM)), WinAPIHelper.AllocationType.Commit, WinAPIHelper.MemoryProtection.ReadWrite);
IntPtr pStrLocaAddress = Marshal.AllocHGlobal(MAX_LVMSTRING);
WinAPIHelper.LVITEM item = new WinAPIHelper.LVITEM();
item.cchTextMax = MAX_LVMSTRING;
item.pszText = pStrBufferMemory;
item.mask = WinAPIHelper.LVIF_TEXT;
int columnIndex = 0;
int tryCount = 0;
GETCOLUMNINDEX:
if (columnIndex == 0)
{
tryCount++;
if (tryCount > SysConfig.ListViewItemFindTryCount) { return lv; }
columnIndex = WinAPIHelper.SendMessage(lvHwnd, (int)WinAPIHelper.LVM.GETHEADER, 0, 0);//列的index指針
Console.WriteLine("列指針為" + columnIndex);
Thread.Sleep(1000);
goto GETCOLUMNINDEX;
}
int columnCount = 0;
tryCount = 0;
//獲取總列數
GETCOLUMNCOUNT:
if (columnCount == 0)
{
tryCount++;
if (tryCount > SysConfig.ListViewItemFindTryCount) { return lv; }
columnCount = WinAPIHelper.SendMessage(new IntPtr(columnIndex), (int)WinAPIHelper.HDM.HDM_GETITEMCOUNT, 0, 0);
Console.WriteLine("列數量為" + columnCount);
Thread.Sleep(1000);
goto GETCOLUMNCOUNT;
}
int rowCount = 0;
tryCount = 0;
//獲取總行數
GETROWCOUNT:
if (rowCount == 0)
{
tryCount++;
if (tryCount > SysConfig.ListViewItemFindTryCount) { return lv; }
rowCount = WinAPIHelper.SendMessage(lvHwnd, (int)WinAPIHelper.LVM.GETITEMCOUNT, 0, 0);
Console.WriteLine("行數量為" + rowCount);
Thread.Sleep(1000);
goto GETROWCOUNT;
}
lv.ColumnCount = columnCount;
lv.RowCount = rowCount;
for (int j = 0; j < rowCount; j++)
{
var row = new WinListViewRow();
row.Cells = new string[columnCount];
for (int i = 0; i < columnCount; i++)
{
item.iSubItem = i;
bool result = WinAPIHelper.WriteProcessMemory(hPro, pItemMemory, ref item, Marshal.SizeOf(item), IntPtr.Zero);
int iRet = WinAPIHelper.SendMessage(lvHwnd, (int)WinAPIHelper.LVM.GETITEMTEXTW, j, pItemMemory);
iRet = WinAPIHelper.SendMessage(lvHwnd, (int)WinAPIHelper.LVM.GETITEMW, j, pItemMemory);
int readLen = 0;
result = WinAPIHelper.ReadProcessMemory(hPro, pStrBufferMemory, pStrLocaAddress, MAX_LVMSTRING, out readLen);
result = WinAPIHelper.ReadProcessMemory(hPro, pItemMemory, ref item, Marshal.SizeOf(item), IntPtr.Zero);
string tmpString2 = Marshal.PtrToStringAuto(pStrLocaAddress);
row.Cells[i] = tmpString2;
}
if (row.Cells.Length > 0)
{
lv.Rows.Add(row);
}
}
if (pStrLocaAddress != IntPtr.Zero)
{
try { Marshal.FreeHGlobal(pStrLocaAddress); }
catch { }
}
if (pItemMemory != IntPtr.Zero)
{
try { WinAPIHelper.VirtualFreeEx(hPro, pItemMemory, 0, WinAPIHelper.MEM_RELEASE); }
catch { }
}
if (pStrBufferMemory != IntPtr.Zero)
{
try { WinAPIHelper.VirtualFreeEx(hPro, pStrBufferMemory, 0, WinAPIHelper.MEM_RELEASE); }
catch { }
}
if (hPro != IntPtr.Zero)
{
try { WinAPIHelper.CloseHandle(hPro); }
catch { }
}
return lv;
}
}
這篇代碼實現比較濫,大家可以自己拿去改