我通过
LVM_GETITEMRECT
查询桌面图标,只得到图标的位置。但我还需要界限。
Docu在这里:https://learn.microsoft.com/en-us/windows/win32/controls/lvm-getitemrect
这部分我无法实现:
发送消息时,该结构体的左成员用于 指定要从中检索列表视图项的部分 边界矩形。它必须设置为以下值之一....
这里的代码正在运行,但只获取位置 x/y。宽度/高度值始终为 0。备注:完整代码“释放”
finally
中的内存。
genericPtr = VirtualAllocEx(
processHandle,
IntPtr.Zero,
(uint)Marshal.SizeOf(typeof(Rectangle)),
// Rectangle ist the maximum
// sizeof(uint), ??? SIZE HERE ???
AllocationType.Commit,
MemoryProtection.ReadWrite);
CWindow.SendMessage(listViewPtr, (uint)LVM_Message.LVM_GETITEMRECT, itemId, genericPtr.ToInt32());
Rectangle[] vRectangle = new Rectangle[1];
int rectSize = Marshal.SizeOf(typeof(Rectangle));
ReadProcessMemory(processHandle, genericPtr,
Marshal.UnsafeAddrOfPinnedArrayElement(vRectangle, 0),
rectSize, out vNumberOfBytes);
我知道我必须为
LVIR_Message
设置 SendMessage
值,但我该怎么做?
private enum LVIR_Message : uint
{
LVIR_BOUNDS = 0,
LVIR_ICON = 1,
LVIR_LABEL = 2,
LVIR_SELECTBOUNDS = 3
}
参考相关问题:如何在 C# 中禁用桌面视图的“自动排列图标”?
您需要先用
GCHandle
固定矩形,然后才能获取其地址。
并且您需要将
Rectangle
的内容写入目标进程,然后再发送消息。
如果您将应用程序编译为 64 位,则无法使用
IntPtr.ToInt32()
,您将需要 IntPtr.ToInt64()
,因为 LPARAM
会根据您运行的平台而改变大小。
试试这个:
Rectangle vRectangle = new Rectangle;
vRectangle.left = LVIR_Message.LVIR_BOUNDS;
GCHandle gch = GCHandle.Alloc(vRectangle, GCHandleType.Pinned);
try
{
uint rectSize = (uint)Marshal.SizeOf(typeof(Rectangle)); // make sure this is actually 16!
IntPtr rectPtr = gch.AddrOfPinnedObject();
processAllocPtr = VirtualAllocEx(
processHandle,
IntPtr.Zero,
rectSize,
AllocationType.Commit,
MemoryProtection.ReadWrite);
if (processAllocPtr == IntPtr.Zero)
{
throw new Win32Exception();
}
try
{
if (!WriteProcessMemory(
processHandle,
processAllocPtr,
rectPtr,
rectSize,
out vNumberOfBytesWritten))
{
throw new Win32Exception();
}
if (IntPtr.Size() == 8) {
CWindow.SendMessage(listViewPtr, (uint)LVM_Message.LVM_GETITEMRECT, itemId, processAllocPtr.ToInt64());
} else {
CWindow.SendMessage(listViewPtr, (uint)LVM_Message.LVM_GETITEMRECT, itemId, processAllocPtr.ToInt32());
}
if (!ReadProcessMemory(
processHandle,
processAllocPtr,
rectPtr,
rectSize,
out vNumberOfBytes))
{
throw new Win32Exception();
}
}
finally
{
VirtualFreeEx(
processHandle,
processAllocPtr,
0,
MEM_RELEASE
);
}
}
finally
{
gch.Free();
}
// use vRectangle as needed...