有个程序是C++写的,类名:SysListView32,样式带有以下样式
LVS_OWNERDATA
LVS_OWNERDRAWFIXED用以下代码能取到Delphi自带例子"Virtual Listview"中的数据(转自刘麻子在DFW的回贴)function ListView_GetItemText_Mz(hListView: HWnd; iItem, iSubItem: Integer; pszText: PChar; cchTextMax: Integer): Integer;
var
DispInfo: TLVDispInfo;
begin
DispInfo.hdr.hwndFrom := hListView;
DispInfo.hdr.idFrom := GetDlgCtrlID(hListView);
DispInfo.hdr.code := LVN_GETDISPINFO; ZeroMemory(@DispInfo.item, SizeOf(DispInfo.item));
DispInfo.item.mask := LVIF_TEXT;
DispInfo.item.iItem := iItem;
DispInfo.item.iSubItem := iSubItem;
DispInfo.item.pszText := pszText;
DispInfo.item.cchTextMax := cchTextMax; Result := SendMessage(GetParent(hListView), WM_NOTIFY, GetDlgCtrlID(hListView), Integer(@DispInfo));
end;但取不到C++写的这个程序中ListView的内容,想请教下这种内容如何取
LVS_OWNERDATA
LVS_OWNERDRAWFIXED用以下代码能取到Delphi自带例子"Virtual Listview"中的数据(转自刘麻子在DFW的回贴)function ListView_GetItemText_Mz(hListView: HWnd; iItem, iSubItem: Integer; pszText: PChar; cchTextMax: Integer): Integer;
var
DispInfo: TLVDispInfo;
begin
DispInfo.hdr.hwndFrom := hListView;
DispInfo.hdr.idFrom := GetDlgCtrlID(hListView);
DispInfo.hdr.code := LVN_GETDISPINFO; ZeroMemory(@DispInfo.item, SizeOf(DispInfo.item));
DispInfo.item.mask := LVIF_TEXT;
DispInfo.item.iItem := iItem;
DispInfo.item.iSubItem := iSubItem;
DispInfo.item.pszText := pszText;
DispInfo.item.cchTextMax := cchTextMax; Result := SendMessage(GetParent(hListView), WM_NOTIFY, GetDlgCtrlID(hListView), Integer(@DispInfo));
end;但取不到C++写的这个程序中ListView的内容,想请教下这种内容如何取
至于发送LVN_GETDISPINFO消息,我上面贴的代码就是,不过它能取Delphi的虚拟列表数据,但C++的取不到
想知道C++的怎么取,有兴趣的可以试试,我就是试不出
(*//
标题:获取其他进程中TreeView的文本
说明:Window2000+Delphi6调试通过
设计:Zswang
支持:[email protected]
日期:2004-03-26
//*)
function TreeNodeGetNext(mHandle: THandle; mTreeItem: HTreeItem): HTreeItem;
var
vParentID: HTreeItem;
begin
Result := nil;
if (mHandle <> 0) and (mTreeItem <> nil) then begin
Result := TreeView_GetChild(mHandle, mTreeItem);
if Result = nil then
Result := TreeView_GetNextSibling(mHandle, mTreeItem);
vParentID := mTreeItem;
while (Result = nil) and (vParentID <> nil) do begin
vParentID := TreeView_GetParent(mHandle, vParentID);
Result := TreeView_GetNextSibling(mHandle, vParentID);
end;
end;
end; { TreeNodeGetNext }function TreeNodeGetLevel(mHandle: THandle; mTreeItem: HTreeItem): Integer;
var
vParentID: HTreeItem;
begin
Result := -1;
if (mHandle <> 0) and (mTreeItem <> nil) then begin
vParentID := mTreeItem;
repeat
Inc(Result);
vParentID := TreeView_GetParent(mHandle, vParentID);
until vParentID = nil;
end;
end; { TreeNodeGetLevel }function GetTreeViewText(mHandle: THandle; mStrings: TStrings): Boolean;
var
vItemCount: Integer;
vBuffer: array[0..255] of Char;
vProcessId: DWORD;
vProcess: THandle;
vPointer: Pointer;
vNumberOfBytesRead: Cardinal;
I: Integer;
vItem: TTVItem;
vTreeItem: HTreeItem;
begin
Result := False;
if not Assigned(mStrings) then Exit;
GetWindowThreadProcessId(mHandle, @vProcessId);
vProcess := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE, False, vProcessId);
vPointer := VirtualAllocEx(vProcess, nil, 4096, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
mStrings.BeginUpdate;
try
mStrings.Clear;
vItemCount := TreeView_GetCount(mHandle);
vTreeItem := TreeView_GetRoot(mHandle);
for I := 0 to vItemCount - 1 do
begin
with vItem do
begin
mask := TVIF_TEXT;
cchTextMax := SizeOf(vBuffer);
pszText := Pointer(Cardinal(vPointer) + SizeOf(vItem));
hItem := vTreeItem;
end;
WriteProcessMemory(vProcess, vPointer, @vItem, SizeOf(vItem), vNumberOfBytesRead);
SendMessage(mHandle, TVM_GETITEM, 0, lparam(vPointer));
ReadProcessMemory(vProcess, Pointer(Cardinal(vPointer) + SizeOf(TLVItem)),
@vBuffer[0], SizeOf(vBuffer), vNumberOfBytesRead);
mStrings.Add(StringOfChar(#9, TreeNodeGetLevel(mHandle, vTreeItem)) + vBuffer);
vTreeItem := TreeNodeGetNext(mHandle, vTreeItem);
end;
finally
VirtualFreeEx(vProcess, vPointer, 0, MEM_RELEASE);
CloseHandle(vProcess);
mStrings.EndUpdate;
end;
Result := True;
end; { GetTreeViewText }
你这是取TreeView的,实际上,取其它程序中ListView中的数据我已经做到,但是取带LVS_OWNERDATA标志的ListView就不行了TO 10楼:
能共享一下吗?(伴水写的程序)
虚拟列表:
http://blog.vckbase.com/zgf/archive/2005/11/25/15271.aspx
pszText: PChar; cchTextMax: Integer): Integer;
var
LVItem: TLVItem;
ProcessID, ProcessHD, Temp: DWORD;
MemPoint: Pointer;
begin
GetWindowThreadProcessId(hwndLV, ProcessID); ProcessHD := OpenProcess(
PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE,
FALSE, ProcessID); MemPoint := VirtualAllocEx(ProcessHD, nil, SizeOf(TLVItem) + cchTextMax,
MEM_COMMIT, PAGE_READWRITE); LVItem.iSubItem := iSubItem;
LVItem.cchTextMax := cchTextMax;
LVItem.pszText := PChar(Integer(MemPoint) + SizeOf(TLVItem)); WriteProcessMemory(ProcessHD, MemPoint, @LVItem, SizeOf(TLVItem), Temp);
Result := SendMessage(hwndLV, LVM_GETITEMTEXT, i, Integer(MemPoint)); ReadProcessMemory(ProcessHD, Pointer(Integer(MemPoint) + SizeOf(TLVItem)),
pszText, cchTextMax, Temp); VirtualFreeEx(ProcessHD, MemPoint, SizeOf(TLVItem) + cchTextMax, MEM_DECOMMIT);
VirtualFreeEx(ProcessHD, MemPoint, 0, MEM_RELEASE);
end;procedure TForm1.Button1Click(Sender: TObject);
var
TextBuffer: array[0..100] of Char;
iCount: Integer;
aHandle: HWND;
begin
aHandle := $000509D0;
iCount := ListView_GetItemCount(aHandle);
for iCount := 0 to iCount -1 do
begin
ListView_GetItemText_Ex(aHandle, iCount, 0, TextBuffer, 100);
Memo1.Lines.Add(TextBuffer)
end;
end;
已经注入到目标exe了,所以跨进程不是问题,问题是如何取
LVS_OWNERDATA 取出来是空的?
Integer设为1也没数据?
对了,你试试取SysListView32的数目可以取到吗
刘麻子说了可以取Delphi例子中的虚拟列表数据,我试过了也可以,但取C++写的虚拟列表就不行,不知道它们之间有啥区别
我是这么做的:
1.用C++写了个DLL注入到目标进程
2.找到ListView的父窗口
3.子类化父窗口,把旧窗口过程存到old_proc
4.响应code == LVN_GETDISPINFO的WM_NOTIFY
{
NMLVDISPINFO* d = (NMLVDISPINFO*)lParam;
if(d->item.mask & LVIF_TEXT)
CallWndProc(old_proc,...);//让目标进程把文字设进来
OutputDebugString(d->item.pszText);//郁闷的是每次d->item.pszText[0]总被设成了0
} 经过我的分析,推断出LVS_GETDISPINFO获取不了文字信息。因为目标进程的ListView设成了LVS_OWNERDATA和LVS_OWNERDRAWFIXED风格,那么它在WM_DRAWITEM的时候,WM_DRAWITEM的参数里有它需要的全部信息(是否选中、行绘制矩形、行号),又因为是LVS_OWNERDATA,它自然会保存数据。根据行号也就知道要显示什么文字、图片。我还试过不调用目标进程的窗口过程,自己往里写文本,但显示出来的,还是目标里程里的数据。
但为什么它还要响应GetDispInfo呢?我猜测是为了获取行高,不然LVM_GETCOUNTPERPAGE算不出来,自然WM_DRAWITEM里的参数rcItem也算不出来了。可我这个目标进程里没返回文字,怎么算行高呢?它是没返回文字,但返回了图片ID,根据这个应该可以算出行高。
到目前为止,我能想到的获取数据的方法,只有是用WinDebug或者Softice跟到WM_DRAWITEM的响应代码里面去找出数据在哪了,并且还要先分析出来数据结构
而C++版没设上去,这样一点也不影响它实际显示,而且效率还更高
所以楼主得不到数据