使用LVM_GETITEMRECT消息获取桌面图标大小

时间:2011-09-16 16:47:30

标签: c# syslistview32

我整晚都在和这个人打架。我只是没有错。我正在尝试获取桌面图标+标题大小。我有一些函数可以找到桌面句柄并将其放在一个名为SysListView32_hwnd的变量中。我已经通过Windows间谍程序验证了它是正确的。这是我遇到麻烦的部分。

Rectangle rct = new Rectangle();
IntPtr pRct = Marshal.AllocHGlobal(Marshal.SizeOf(rct));
Marshal.StructureToPtr(rct, pRct, true);

SendMessage(SysListView32_hwnd, LVM_GETITEMRECT, (IntPtr)0, pRct);

Rectangle Rect = (Rectangle)Marshal.PtrToStructure(pRct, typeof(Rectangle));
Marshal.FreeHGlobal(pRct);
Debug.WriteLine(Rect.Height + "    " + Rect.Width);

每次都会崩溃探险家。 C#Visual Studio 2010 Windows 7 x64和我正在编译为64位程序

如果需要,

Here是我的完整应用

2 个答案:

答案 0 :(得分:2)

这解决了广泛编辑问题时提出的其他问题。

  

在我看来,我们正在使用LVITEMsVirtualAllocEx指定sizeof(uint)

MSDN上dwSize dwSize参数的文档说明:

  

要分配的内存区域的大小,以字节为单位。

     

如果lpAddress为NULL,则该函数将dwSize四舍五入到下一页边界。

     

如果lpAddress不为NULL,则该函数将分配包含lpAddress到lpAddress + dwSize范围内的一个或多个字节的所有页面。这意味着,例如,跨越页面边界的2字节范围会导致函数分配两个页面。

换句话说,它分配整个页面。由于页面是4KB,你运气好。您应确保pszText足够大,以满足您所需的缓冲区。

  

为什么pszText =(IntPtr)((int)lpBaseAddress + Marshal.SizeOf(typeof(LVITEM)))?这不仅仅指向结构的结束。

是的,它确实指向结构的结尾。关键是LVITEM的{​​{1}}字段必须指向调用者分配的缓冲区。编写此代码的人选择使用结构末尾的备用缓冲区空间。由于struct声明pszText包含256个字节,因此很容易适合4KB页面的剩余部分。所以它有效,但它有点不透明。

答案 1 :(得分:1)

这解决了广泛编辑之前的原始问题。

它失败了,因为你编写它的方式只能在你拥有目标窗口句柄的进程调用时才能工作。这是因为您传递了一个指针,但这仅在您的过程中有效。一旦它落入另一个过程,它就会指一个毫无意义的地址。即使它确实意味着什么,过程也无法在系统的帮助下读取另一个进程内存。自然探险家炸弹。

解决方案是使用VirtualAllocEx()在资源管理器进程中分配内存。然后发送消息。然后使用ReadProcessMemory()将rect的内容封送回您的进程。最常见的代码示例是Code Project article。该示例使用LVM_GETITEMTEXT但原则相同。