请教高手,得到另一个程序的LISTVIEW控件的句柄后,如何读出其中内容? 300酬谢!! (300分)

  • 主题发起人 主题发起人 mylwf
  • 开始时间 开始时间
M

mylwf

Unregistered / Unconfirmed
GUEST, unregistred user!
如果有简单的小例子最好,谢谢! :)
 
用SendMessage向这个句柄发LVM_XXX系列消息来获取所要的信息。<br>以下两个已经可以满足你的要求。<br>LVM_GETITEMCOUNT,获得行数。<br>LVM_GETITEM,获得某行,某列的文字/状态等。<br>具体请参照MSDN,过程比较简单。<br><br>
 
非常感谢!! 我去试试,如果成功,马上给您加分! :)
 
function TreeNodeGetLevel(mHandle: THandle; mTreeItem: HTreeItem): Integer;<br>var<br>&nbsp; vParentID: HTreeItem;<br>begin<br>&nbsp; Result := -1;<br>&nbsp; if (mHandle &lt;&gt; 0) and (mTreeItem &lt;&gt; nil) then begin<br>&nbsp; &nbsp; vParentID := mTreeItem;<br>&nbsp; &nbsp; repeat<br>&nbsp; &nbsp; &nbsp; Inc(Result);<br>&nbsp; &nbsp; &nbsp; vParentID := TreeView_GetParent(mHandle, vParentID);<br>&nbsp; &nbsp; until vParentID = nil;<br>&nbsp; end;<br>end; { TreeNodeGetLevel }<br><br>function TreeNodeGetNext(mHandle: THandle; mTreeItem: HTreeItem): HTreeItem;<br>var<br>&nbsp; vParentID: HTreeItem;<br>begin<br>&nbsp; Result := nil;<br>&nbsp; if (mHandle &lt;&gt; 0) and (mTreeItem &lt;&gt; nil) then begin<br>&nbsp; &nbsp; Result := TreeView_GetChild(mHandle, mTreeItem);<br>&nbsp; &nbsp; if Result = nil then<br>&nbsp; &nbsp; &nbsp; Result := TreeView_GetNextSibling(mHandle, mTreeItem);<br>&nbsp; &nbsp; vParentID := mTreeItem;<br>&nbsp; &nbsp; while (Result = nil) and (vParentID &lt;&gt; nil) do begin<br>&nbsp; &nbsp; &nbsp; vParentID := TreeView_GetParent(mHandle, vParentID);<br>&nbsp; &nbsp; &nbsp; Result := TreeView_GetNextSibling(mHandle, vParentID);<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>end; &nbsp;{ TreeNodeGetNext }<br><br>function GetTreeViewText(mHandle: THandle; mStrings: TStrings): Boolean;<br>var<br>&nbsp; vItemCount: Integer;<br>&nbsp; vBuffer: array[0..1024] of Char;<br>&nbsp; vProcessId: DWORD;<br>&nbsp; vProcess: THandle;<br>&nbsp; vPointer: Pointer;<br>&nbsp; vNumberOfBytesRead: Cardinal;<br>&nbsp; I: Integer;<br>&nbsp; vItem: TTVItem;<br>&nbsp; vTreeItem: HTreeItem;<br>begin<br>&nbsp; Result := False;<br>&nbsp; if not Assigned(mStrings) then Exit;<br>&nbsp; GetWindowThreadProcessId(mHandle, @vProcessId);<br>&nbsp; vProcess := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or<br>&nbsp; &nbsp; PROCESS_VM_WRITE, False, vProcessId);<br>&nbsp; vPointer := VirtualAllocEx(vProcess, nil, 4096, MEM_RESERVE or MEM_COMMIT,<br>&nbsp; &nbsp; PAGE_READWRITE);<br>&nbsp; mStrings.BeginUpdate;<br>&nbsp; try<br>&nbsp; &nbsp; mStrings.Clear;<br>&nbsp; &nbsp; vItemCount := TreeView_GetCount(mHandle);<br>&nbsp; &nbsp; vTreeItem := TreeView_GetRoot(mHandle);<br>&nbsp; &nbsp; for I := 0 to vItemCount - 1 do begin<br>&nbsp; &nbsp; &nbsp; with vItem do begin<br>&nbsp; &nbsp; &nbsp; &nbsp; mask := TVIF_TEXT;<br>&nbsp; &nbsp; &nbsp; &nbsp; cchTextMax := SizeOf(vBuffer);<br>&nbsp; &nbsp; &nbsp; &nbsp; pszText := Pointer(Cardinal(vPointer) + SizeOf(vItem));<br>&nbsp; &nbsp; &nbsp; &nbsp; hItem := vTreeItem;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; WriteProcessMemory(vProcess, vPointer, @vItem, SizeOf(vItem), vNumberOfBytesRead);<br>&nbsp; &nbsp; &nbsp; SendMessage(mHandle, TVM_GETITEM, 0, lparam(vPointer));<br>&nbsp; &nbsp; &nbsp; ReadProcessMemory(vProcess, vPointer, @vItem, SizeOf(TLVItem), vNumberOfBytesRead);<br>&nbsp; &nbsp; &nbsp; ReadProcessMemory(vProcess, vItem.pszText, @vBuffer, vItem.cchTextMax, vNumberOfBytesRead);<br>&nbsp; &nbsp; &nbsp; mStrings.Add(vBuffer);<br>&nbsp; &nbsp; &nbsp; vTreeItem := TreeNodeGetNext(mHandle, vTreeItem);<br>&nbsp; &nbsp; end;<br>&nbsp; finally<br>&nbsp; &nbsp; VirtualFreeEx(vProcess, vPointer, 0, MEM_RELEASE);<br>&nbsp; &nbsp; CloseHandle(vProcess);<br>&nbsp; &nbsp; mStrings.EndUpdate;<br>&nbsp; end;<br>&nbsp; Result := True;<br>end; { GetTreeViewText }
 
以前没有接触过类似问题,现在已经可以取到 ITEMCOUNT 了,可里面的文字还是取不出来。<br><br>非常感谢楼上的大侠,可小弟实在功力不够,移植不到LISTVIEW上啊<br><br>哪位大侠能写一个简单的例子,小弟另开帖300分奉上,谢谢!
 
给一个建议吧:参考有关listview的消息看看,MSDN里头很详细,<br><br>此外用SendMessage发送就可以了,而不建议用PostMessage发送,
 
uses<br> ...,CommCtrl;<br>var<br> item :TLVItem;<br> buffer :array[0..300] of char;<br> sText :string;<br>begin<br> with item do begin<br> mask:=LVIF_TEXT;<br> iItem:=0; //第0行<br> iSubItem:=0; //第0列<br> pszText:=pchar(@buffer);<br> cchTextMax:=300;<br> end;<br> if 0&lt;&gt;SendMessage(hWnd,LVM_GETITEM,0,LPARAM(@item)) then<br> sText:=item.pszText;<br>
 
直接用API函数GetWindowsText就可以了<br>GetWindowsText(listhandle:hwnd;listtext:pansichar;cch:dword);<br>listhandle为句柄,listtext为字符缓冲区变量,cch为缓冲区大小,调用后,listtext为LISTVIEW中的内容;<br>
 
谢谢楼上的朋友,可这些我怎么试了很多遍,都不能成功啊? 郁闷
 
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2471980
 
肯定是使用LVM_GETITEM等LISTVIEW的消息来操作,但由于你操作的是不同进程,所以不可能直接取得文本等信息,这就涉及到进程间通信的问题了,可以使用HOOK加内存映射文件,还可以直接读写进程内存等方法实现,HOOK加内存映射文件的代码比较复杂,还要用到DLL,下午帮你写个用直接读写进程内存的API来实现的代码吧.
 
俺有个例子,网上下载的,要不?
 
楼上的,如果有的话就贴出来吧,我也就不去写了。 &nbsp;[:)]
 
http://218.19.172.170/music/GrabListView.zip
 
楼上的好象搞错了吧?<br>花了近50分钟,搞了一下:<br>{***************************************************************<br>&nbsp;*<br>&nbsp;* Project Name: LittleCode -- uListViewInfo<br>&nbsp;* Typist: &nbsp; &nbsp; &nbsp; XJG(xianjun@163.net)<br>&nbsp;* Purpose: &nbsp; &nbsp; &nbsp;使用读取进程内存的方式取得ListView的信息<br>&nbsp;* Comment Time: 2004-05-01 14:44:42<br>&nbsp;* History: &nbsp; &nbsp; &nbsp;Create by xjg. 2004-05-01 14:44:42<br>&nbsp;*<br>&nbsp;****************************************************************}<br><br>unit uListViewInfo;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br>&nbsp; Dialogs, uMDIAncestor, StdCtrls;<br><br>type<br>&nbsp; TForm3 = class(TFormMDIAncestor)<br>&nbsp; &nbsp; Memo1: TMemo;<br>&nbsp; &nbsp; Edit1: TEdit;<br>&nbsp; &nbsp; Button1: TButton;<br>&nbsp; &nbsp; Label1: TLabel;<br>&nbsp; &nbsp; procedure Button1Click(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>implementation<br><br>{$R *.dfm}<br><br>uses<br>&nbsp; CommCtrl;<br><br>const<br>&nbsp; Max_CaptionWidth = 512;<br><br>function GetListViewItemText(const AHwnd, AProcess: THandle; const pMemory: Pointer): string;<br>var<br>&nbsp; AItemCount, I, J, K: Integer;<br>&nbsp; S, ResName: string;<br>&nbsp; lvColumn: TLVColumn;<br>&nbsp; lvItem: TLVItem;<br>&nbsp; ASuccess: Boolean;<br>&nbsp; lpNumberOfBytesWritten: Cardinal;<br>begin<br>&nbsp; J := 0;<br>&nbsp; repeat<br>&nbsp; &nbsp; FillChar(lvColumn, SizeOf(lvColumn), 0);<br>&nbsp; &nbsp; lvColumn.Mask := LVCF_TEXT;<br>&nbsp; &nbsp; lvColumn.pszText := Pointer(Cardinal(pMemory) + SizeOf(lvColumn));<br>&nbsp; &nbsp; lvColumn.cchTextMax := Max_CaptionWidth;<br><br>&nbsp; &nbsp; WriteProcessMemory(AProcess, pMemory, @lvColumn, SizeOf(lvColumn), lpNumberOfBytesWritten);<br>&nbsp; &nbsp; ASuccess := Boolean(SendMessage(AHwnd, LVM_GETCOLUMN, J, LPARAM(pMemory)));<br>&nbsp; &nbsp; ReadProcessMemory(AProcess, pMemory, @lvColumn, SizeOf(TLVColumn), lpNumberOfBytesWritten);<br><br>&nbsp; &nbsp; SetLength(S, Max_CaptionWidth);<br>&nbsp; &nbsp; FillChar(Pointer(S)^, Max_CaptionWidth, 0);<br>&nbsp; &nbsp; ReadProcessMemory(AProcess, lvColumn.pszText, Pointer(S), lvColumn.cchTextMax, lpNumberOfBytesWritten);<br><br>&nbsp; &nbsp; if ASuccess and (StrLen(PChar(S)) &gt; 0) then<br>&nbsp; &nbsp; &nbsp; if J = 0 then<br>&nbsp; &nbsp; &nbsp; &nbsp; ResName := PChar(S)<br>&nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; ResName := ResName + #09 + PChar(S);<br>&nbsp; &nbsp; Inc(J);<br>&nbsp; until not ASuccess;<br>&nbsp; Dec(J);<br>&nbsp; Result := ResName;<br><br>&nbsp; AItemCount := ListView_GetItemCount(AHwnd);<br>&nbsp; for I := 0 to AItemCount - 1 do<br>&nbsp; begin<br>&nbsp; &nbsp; for K := 0 to J - 1 do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; FillChar(lvItem, SizeOf(lvItem), 0);<br>&nbsp; &nbsp; &nbsp; lvItem.Mask := LVCF_TEXT;<br>&nbsp; &nbsp; &nbsp; lvItem.iSubItem := K;<br>&nbsp; &nbsp; &nbsp; lvItem.cchTextMax := Max_CaptionWidth;<br>&nbsp; &nbsp; &nbsp; lvItem.pszText := Pointer(Cardinal(pMemory) + SizeOf(lvColumn));<br><br>&nbsp; &nbsp; &nbsp; WriteProcessMemory(AProcess, pMemory, @lvItem, SizeOf(lvItem), lpNumberOfBytesWritten);<br>&nbsp; &nbsp; &nbsp; SendMessage(AHwnd, LVM_GETITEMTEXT, I, LPARAM(pMemory));<br>&nbsp; &nbsp; &nbsp; ReadProcessMemory(AProcess, pMemory, @lvItem, SizeOf(lvItem), lpNumberOfBytesWritten);<br>&nbsp; &nbsp; &nbsp; SetLength(S, Max_CaptionWidth);<br>&nbsp; &nbsp; &nbsp; FillChar(Pointer(S)^, Max_CaptionWidth, 0);<br>&nbsp; &nbsp; &nbsp; ReadProcessMemory(AProcess, lvItem.pszText, Pointer(S), lvItem.cchTextMax, lpNumberOfBytesWritten);<br><br>&nbsp; &nbsp; &nbsp; if K = 0 then<br>&nbsp; &nbsp; &nbsp; &nbsp; ResName := PChar(S)<br>&nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; ResName := ResName + #09 + PChar(S);<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; Result := Result + #13#10 + ResName;<br>&nbsp; end;<br>end;<br><br>procedure TForm3.Button1Click(Sender: TObject);<br>var<br>&nbsp; hProcessID: DWORD;<br>&nbsp; hListView, hProcess: THandle;<br>&nbsp; pMemory: Pointer;<br>begin<br>&nbsp; hListView := StrToIntDef(Edit1.Text, 0);<br>&nbsp; GetWindowThreadProcessId(hListView, @hProcessID);<br>&nbsp; hProcess := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or<br>&nbsp; &nbsp; PROCESS_VM_WRITE, False, hProcessID);<br>&nbsp; if hProcess = 0 then<br>&nbsp; &nbsp; RaiseLastOSError;<br>&nbsp; try<br>&nbsp; &nbsp; pMemory := VirtualAllocEx(hProcess, nil, 4096, MEM_RESERVE or MEM_COMMIT,<br>&nbsp; &nbsp; &nbsp; PAGE_READWRITE);<br>&nbsp; &nbsp; if pMemory = nil then<br>&nbsp; &nbsp; &nbsp; RaiseLastOSError;<br>&nbsp; &nbsp; try<br>&nbsp; &nbsp; &nbsp; Memo1.Text := GetListViewItemText(hListView, hProcess, pMemory);<br>&nbsp; &nbsp; finally<br>&nbsp; &nbsp; &nbsp; VirtualFreeEx(hProcess, pMemory, 0, MEM_RELEASE);<br>&nbsp; &nbsp; end;<br>&nbsp; finally<br>&nbsp; &nbsp; CloseHandle(hProcess);<br>&nbsp; end;<br>end;<br><br>end.<br><br>
 
skadon的代码也可以实现这功能,不过比较复杂一些了~ 原理是一样的。<br><br>刚刚只是看了一下压缩包里的文件名,以为skadon贴错代码了,不好意思[:)]
 
谢谢大家!!<br><br>我另开贴答谢 XIANJUN
 
后退
顶部