获取WIN7桌面图标名称,我已要抓狂,求助各位大神!

lclwcf 2013-08-07 09:07:58
以下方法在WIN7下获取桌面句柄无效:
Handle := FindWindow('progman', nil);
改为以下函数后可以:
procedure findDesktopWnd;
Function MyEnumWindowProc(wnd: HWND; LPARAM: LPARAM): Boolean; stdcall;
var
sndWnd, targetWnd: Cardinal;
begin
sndWnd := FindWindowEx(wnd, 0, 'SHELLDLL_DefView', 0);
if sndWnd = 0 then
begin
Result := true;
Exit;
end;
targetWnd := FindWindowEx(sndWnd, 0, 'SysListView32', 'FolderView');
if targetWnd = 0 then
begin
Result := true;
Exit;
end;
deskTopHandel := wnd;
Result := false;
end;

begin
EnumWindows(@MyEnumWindowProc, 0);
end;

在正确获得桌面句柄后,获取图标位置XP,WIN7的代码都好用
// 取得桌面存放图标的listview句柄
function GetDesktopLvHand: THandle;
begin
//Result := FindWindow('progman', nil);
findDesktopWnd;
Result :=deskTopHandel;
Result := GetWindow(Result, GW_Child);
Result := GetWindow(Result, GW_Child);
end;

// 取得图标的坐标位置
function GetIcoPosition(h: THandle; idx: Integer): TPoint;
var
hpro, pid, dm, i: Cardinal;
p: Pointer;
begin
GetWindowThreadProcessId(h, pid);
hpro := OpenProcess(PROCESS_ALL_ACCESS, False, pid);
if hpro <> 0 then
try
p := VirtualAllocEx(hpro, nil, SizeOf(TPoint), MEM_COMMIT,
PAGE_READWRITE);
ListView_GetItemPosition(h, idx, TPoint(p^));
ReadProcessMemory(hpro, p, @Result, SizeOf(Result), dm);
finally
VirtualFreeEx(hpro, p, 0, MEM_RELEASE);
CloseHandle(hpro);
end;
end;

现在问题来了,XP上好用的一段代码在WIN7下程序会崩溃,查了很资料,也没有办法解释是为什么:
function ListView_GetItemText_Ex(hwndLV: HWND; i, iSubItem: Integer; 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;



function GetIcoItemText(i: Integer): string;
var
TextBuffer: array [0 .. 100] of char;
FDeskTopLvHandle: THandle;
begin
FDeskTopLvHandle := GetDesktopLvHand;
ListView_GetItemText_Ex(FDeskTopLvHandle, i, 0, TextBuffer, 100);
Result := TextBuffer;
end;



经过排查
Result := SendMessage(hwndLV, LVM_GETITEMTEXT, i, Integer(MemPoint));
这句会造成WIN7下程序崩溃。
求各位大神帮看下,谢谢!WIN764位+delphi7.


...全文
319 点赞 收藏 6
写回复
6 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
LastAvengers 2013-11-06
以前也试着写过这些小工具,XP下正常使用但是在我的64位的Win7下就挂了……
回复
秦枫_ 2013-11-06
这个跟XP或者Win7没多大关系,32和64位的区别 这儿有个原来写的例子 //---------- 引用 CommCtrl type TLVItem64 = packed record mask: UINT; iItem: Integer; iSubItem: Integer; state: UINT; stateMask: UINT; _align: LongInt; pszText: Int64; cchTextMax: Integer; iImage: Integer; lParam: LPARAM; end; function GetDesktopLvHand: THandle; begin Result := FindWindow('progman', nil); Result := GetWindow(Result, GW_Child); Result := GetWindow(Result, GW_Child); end; //32位系统------ function GetIconRect32(hDeskWnd:HWND ;strIconName:String;var lpRect:TRECT):Boolean; const cchTextMax=512; var ItemBuf: array [0 .. 512] of char; pszText: PChar; LVItem: TLVItem; ProcessID, ProcessHD, drTmp: DWORD; pLVITEM: Pointer; pItemRc:^TRect; nCount,iItem:Integer; begin Result :=False ; GetWindowThreadProcessId(hDeskWnd, ProcessID); ProcessHD := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE, False,ProcessID); if (ProcessHD=0) then Exit else begin pLVITEM := VirtualAllocEx(ProcessHD, nil, SizeOf(TLVItem),MEM_COMMIT, PAGE_READWRITE); pszText:=VirtualAllocEx(ProcessHD,nil,cchTextMax,MEM_COMMIT,PAGE_READWRITE); pItemRc:=VirtualAllocEx(ProcessHD,nil,sizeof(TRECT),MEM_COMMIT,PAGE_READWRITE); if (pLVITEM=nil) then else begin LVItem.iSubItem := 0; LVItem.cchTextMax := cchTextMax; LVItem.pszText := PChar(Integer(pLVITEM) + SizeOf(TLVItem)); WriteProcessMemory(ProcessHD, pLVITEM, @LVItem, SizeOf(TLVItem), drTmp); nCount:=SendMessage(hDeskWnd,LVM_GETITEMCOUNT,0,0); for iItem := 0 to nCount - 1 do begin SendMessage(hDeskWnd, LVM_GETITEMTEXT, iItem, Integer(pLVITEM)); //ReadProcessMemory(ProcessHD,pszText,@ItemBuf,cchTextMax,drTmp); ReadProcessMemory(ProcessHD,Pointer(Integer(pLVITEM) + SizeOf(TLVItem)),@ItemBuf, cchTextMax, drTmp); if (ItemBuf=strIconName) then begin SendMessage(hDeskWnd,LVM_GETITEMRECT,iItem,LPARAM(pItemRc)); ReadProcessMemory(ProcessHD,pItemRc,@lpRect,sizeof(TRECT),drTmp); Result :=True ; Break ; end; end; //VirtualFreeEx(ProcessHD,pLVITEM,0,MEM_RELEASE); VirtualFreeEx(ProcessHD,pLVITEM, SizeOf(TLVItem) + cchTextMax,MEM_DECOMMIT); VirtualFreeEx(ProcessHD,pszText,0,MEM_RELEASE); VirtualFreeEx(ProcessHD,pItemRc,0,MEM_RELEASE);//释放内存 end; CloseHandle(ProcessHD); end; end; //64位系统------ function GetIconRect64(hDeskWnd:HWND ;strIconName:String;var lpRect:TRECT):Boolean; const cchTextMax=512; var ItemBuf: array [0 .. 512] of char; pszText: PChar; LVItem: TLVItem64; ProcessID, ProcessHD, drTmp: DWORD; pLVITEM: Pointer; pItemRc:^TRect; nCount,iItem:Integer; begin Result :=False ; GetWindowThreadProcessId(hDeskWnd, ProcessID); ProcessHD := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE, False,ProcessID); if (ProcessHD=0) then Exit else begin pLVITEM := VirtualAllocEx(ProcessHD, nil, SizeOf(TLVItem64),MEM_COMMIT, PAGE_READWRITE); pszText:=VirtualAllocEx(ProcessHD,nil,cchTextMax,MEM_COMMIT,PAGE_READWRITE); pItemRc:=VirtualAllocEx(ProcessHD,nil,sizeof(TRECT),MEM_COMMIT,PAGE_READWRITE); if (pLVITEM=nil) then else begin LVItem.iSubItem := 0; LVItem.cchTextMax := cchTextMax; LVItem.pszText := Int64(pszText); WriteProcessMemory(ProcessHD, pLVITEM, @LVItem, SizeOf(TLVItem64), drTmp); nCount:=SendMessage(hDeskWnd,LVM_GETITEMCOUNT,0,0); for iItem := 0 to nCount - 1 do begin SendMessage(hDeskWnd, LVM_GETITEMTEXT, iItem, Integer(pLVITEM)); ReadProcessMemory(ProcessHD,pszText,@ItemBuf,cchTextMax,drTmp); if (ItemBuf=strIconName) then begin SendMessage(hDeskWnd,LVM_GETITEMRECT,iItem,LPARAM(pItemRc)); ReadProcessMemory(ProcessHD,pItemRc,@lpRect,sizeof(TRECT),drTmp); Result :=True ; Break; end; end; VirtualFreeEx(ProcessHD,pLVITEM,0,MEM_RELEASE); VirtualFreeEx(ProcessHD,pszText,0,MEM_RELEASE); VirtualFreeEx(ProcessHD,pItemRc,0,MEM_RELEASE);//释放内存 end; CloseHandle(ProcessHD); end; end; 调用示例: var prRect:TRECT; 32位:GetIconRect32(GetDesktopLvHand,'回收站',prRect); 64位:GetIconRect64(GetDesktopLvHand,'回收站',prRect); delphi2010测试通过...
回复
shoufaqi2 2013-10-25
楼主解决了吗?
回复
lclwcf 2013-08-07
VC 的代码也不行,只能取得图标个数。只是程序没有崩溃而已。谁能指点一下,谢谢! void CEnumIconsDlg::OnBtnEnumIcons() { // bytes to allocate for icon text and LVITEM struct #define ALLOC_SIZE 200 HWND hWnd; // handle to desktop window DWORD dwPID; // explorer process ID (associated with desktop) HANDLE hProcess; // handle to explorer process (associated with desktop) LPVOID pData; // pointer to LVITEM struct in explorer address space LPVOID pString; // pointer to icon text in explorer address space char szText[ALLOC_SIZE]; // char array of icon text in application address space char* pszMessageBox; // string to display SIZE_T BytesRead; // for ReadProcessMemory SIZE_T BytesWritten; // for WriteProcessMemory BOOL fResult; // for ReadProcessMemory/WriteProcessMemory LVITEM lvi; // LVITEM struct int i; // counter for enumeration int nItemCount; // icon item count // get desktop window handle if(((hWnd = FindWindowEx(NULL, NULL, "Progman", NULL)) == NULL) || ((hWnd = FindWindowEx(hWnd, NULL, "SHELLDLL_DefView", NULL)) == NULL) || ((hWnd = FindWindowEx(hWnd, NULL, "SysListView32", NULL)) == NULL)) { MessageBox("Could not get desktop window."); goto Exit; } // get item count on desktop nItemCount = ::SendMessage(hWnd, LVM_GETITEMCOUNT, (WPARAM)0, (LPARAM)0); // allocate memory for output string pszMessageBox = (char*) malloc(ALLOC_SIZE * nItemCount); sprintf(pszMessageBox, "%d items:\n\n", nItemCount); // get desktop window process ID (explorer.exe) GetWindowThreadProcessId(hWnd, &dwPID); // open process to get explorer process handle hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); // allocate memory in explorer's address space // allocate space for LVITEM struct pData = VirtualAllocEx(hProcess, NULL, ALLOC_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); // allocate space for string (i.e. "Network Neighborhood") pString = VirtualAllocEx(hProcess, NULL, ALLOC_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); // init LV_ITEM struct ZeroMemory(&lvi, sizeof(LVITEM)); lvi.iItem = 0; lvi.iSubItem = 0; lvi.cchTextMax = 500; lvi.pszText = (char*)pString; // use alloc'd string space // write the contents of lvi into explorer's address space fResult = WriteProcessMemory(hProcess, pData, &lvi, sizeof(LVITEM), &BytesWritten); // enum all icons for(i = 0; i < nItemCount; i++) { // get item's name ::SendMessage(hWnd, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)pData); // read back lvi struct (for debugging purposes only) fResult = ReadProcessMemory(hProcess, pData, szText, ALLOC_SIZE, &BytesRead); // read text of queried item fResult = ReadProcessMemory(hProcess, pString, szText, ALLOC_SIZE, &BytesRead); // append string to output string strcat(pszMessageBox, szText); strcat(pszMessageBox, "\n"); } // output message box with all icon texts MessageBox(pszMessageBox); // free alloc'd memory for message box free(pszMessageBox); // free alloc'd memory for string and LVITEM structs if(!VirtualFreeEx(hProcess, pString, ALLOC_SIZE, MEM_DECOMMIT)) { MessageBox("VirtualFreeEx failed."); goto Exit; } if(!VirtualFreeEx(hProcess, pData, ALLOC_SIZE, MEM_DECOMMIT)) { MessageBox("VirtualFreeEx failed."); goto Exit; } // close process handle CloseHandle(hProcess); Exit: return; }
回复
清风皎月 2013-08-07
回复
lclwcf 2013-08-07
有人解释了为什么出错和解决了这个问题。不过是汇编版的,我正在研究。 碰到类似的问题的朋友可以参考。 http://masm32.com/board/index.php?topic=1464.0 里面有生成的EXE,确实XP,win7平台均可以提取桌面图标文字。
回复
相关推荐
发帖
Delphi
创建于2007-08-02

4925

社区成员

Delphi 开发及应用
申请成为版主
帖子事件
创建了帖子
2013-08-07 09:07
社区公告
暂无公告