Getting desktop icon size with LVM_GETITEMRECT message
I've been fighting with this all night. I just don't what is wrong. I'm trying to get the desktop icon + caption size. I have some functions that find the desktop handle and put it in a variable called S开发者_如何学JAVAysListView32_hwnd. I have verified it is correct with a windows spy program. Here is the part I am having trouble with.
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);
It crashes explorer every time. C# Visual Studio 2010 Windows 7 x64 and I am compiling as a 64 bit program
Here is my full app if needed
This addresses the additional questions asked in the extensive edit to the question.
It seems to me like we are working with
LVITEMs
butVirtualAllocEx
specifiessizeof(uint)
.
The documentation of the dwSize
parameter of VirtualAllocEx()
, on MSDN, states:
The size of the region of memory to allocate, in bytes.
If lpAddress is NULL, the function rounds dwSize up to the next page boundary.
If lpAddress is not NULL, the function allocates all pages that contain one or more bytes in the range from lpAddress to lpAddress+dwSize. This means, for example, that a 2-byte range that straddles a page boundary causes the function to allocate both pages.
In other words it allocates entire pages. Since a page is 4KB you are getting luck. You should ensure that dwSize
is big enough for the buffer you need.
Why does pszText = (IntPtr)((int)lpBaseAddress + Marshal.SizeOf(typeof(LVITEM)))? Wouldn't that just point to the end of the structure.
Yes it does point to the end of the structure. The point is that the pszText
field of LVITEM
must point to a buffer allocated by the caller. Whoever wrote this code chose to use the spare buffer space at the end of the struct. Since the struct declares that pszText
contains 256 bytes, that will easily fit into the remains of the 4KB page. So it works, but it is a little opaque.
This addresses the original question before the extensive edit.
It fails because, the way you have written it can only work when you call from the process that owns the target window handle. This is because you pass a pointer, but that is only valid in your process. As soon as it lands in the other process it refers to an address that is meaningless. And even if it did mean something, a process can't read another processes memory with help from the system. Naturally explorer bombs.
The solution is to use VirtualAllocEx()
to allocate memory in the explorer process. Then send the message. Then use ReadProcessMemory()
to marshal the contents of the rect back into your process. The most commonly cited code sample for this is this Code Project article. That example is using LVM_GETITEMTEXT
but the principles are identical.
精彩评论