Большое спасибо Гансу за то, что он попробовал это на своем компьютере, и за Sertac за подсказку, что SysListView32 меняет родителей с «Progman» на имя класса «WorkerW».Мое решение состояло в том, чтобы сначала попытаться найти SysListView32 в дочерних элементах Progman:
hwndIcon = NativeMethods.FindWindow("Progman", null);
hwndIcon = NativeMethods.FindWindowEx(hwndIcon, IntPtr.Zero, "SHELLDLL_DefView", null);
hwndIcon = NativeMethods.FindWindowEx(hwndIcon, IntPtr.Zero, "SysListView32", "FolderView");
, если hwndIcon возвращает IntPtr.Zero, я пытаюсь перечислить все окна под рабочим столом, а затем найти те, чье имя класса «WorkerW» (ясделать это в делегате GetSysListViewContainer (...)) Среди последних я нахожу «Один и только один», т.е.тот, у которого есть ребенок.Это тот, который содержит SHELLDLL_DefView, который сам содержит SysListView32, который сам содержит дескриптор каждого значка на рабочем столе:
hwndIcon = NativeMethods.FindWindow("Progman", null);
hwndIcon = NativeMethods.FindWindowEx(hwndIcon, IntPtr.Zero, "SHELLDLL_DefView", null);
hwndIcon = NativeMethods.FindWindowEx(hwndIcon, IntPtr.Zero, "SysListView32", "FolderView");
if (hwndIcon == IntPtr.Zero)
{
IntPtr hDesktop = NativeMethods.GetDesktopWindow();
IntPtr hwnd = IntPtr.Zero;
EnumWindowsProc ewp = new EnumWindowsProc(GetSysListViewContainer);
EnumWindows(ewp, 0);
hwndIcon = NativeMethods.FindWindowEx(hwndIcon, IntPtr.Zero, "SHELLDLL_DefView", null);
hwndIcon = NativeMethods.FindWindowEx(hwndIcon, IntPtr.Zero, "SysListView32", "FolderView");
}
При следующем я получаю количество значков на рабочем столе:
int vItemCount = NativeMethods.SendMessage(hwndIcon, LVM_GETITEMCOUNT, 0, 0);
string vText;
int vProcessId = 0;
И с этим я перебираю все значки:
NativeMethods.GetWindowThreadProcessId(hwndIcon, ref vProcessId);
IntPtr vProcess = NativeMethods.OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, vProcessId);
IntPtr foo = IntPtr.Zero;
IntPtr vPointer = NativeMethods.VirtualAllocEx(vProcess, IntPtr.Zero, sizeof(uint), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
for (int j = 0; j < vItemCount; j++)
{
byte[] vBuffer = new byte[256];
LVITEM[] vItem = new LVITEM[1];
vItem[0].mask = LVIF_TEXT;
vItem[0].iItem = j;
vItem[0].iSubItem = 0;
vItem[0].cchTextMax = vBuffer.Length;
vItem[0].pszText = (IntPtr)((int)vPointer + Marshal.SizeOf(typeof(LVITEM)));
uint vNumberOfBytesRead = 0;
WriteProcessMemory(vProcess, vPointer, Marshal.UnsafeAddrOfPinnedArrayElement(vItem, 0), Marshal.SizeOf(typeof(LVITEM)), ref vNumberOfBytesRead);
SendMessage(hwndIcon, LVM_GETITEMW, j, vPointer.ToInt32());
ReadProcessMemory(vProcess, (IntPtr)((int)vPointer + Marshal.SizeOf(typeof(LVITEM))), Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0), vBuffer.Length, out vNumberOfBytesRead);
// Get the name of the Icon
vText = Encoding.Unicode.GetString(vBuffer, 0, (int)vNumberOfBytesRead);
// Get Icon location
SendMessage(hwndIcon, LVM_GETITEMPOSITION, j, vPointer.ToInt32());
Point[] vPoint = new Point[1];
foo = Marshal.UnsafeAddrOfPinnedArrayElement(vPoint, 0);
ReadProcessMemory(vProcess, vPointer, Marshal.UnsafeAddrOfPinnedArrayElement(vPoint, 0), Marshal.SizeOf(typeof(Point)), out vNumberOfBytesRead);
//and ultimaely move icon.
SendMessage(hwndIcon, LVM_SETITEMPOSITION, j, lParam[0]);
Итак, подведем итог, мне нужно было выяснить, почему я не могу получить дескриптор для контейнера списка, где все значки рабочего стола хранятся в Windows,Исходный код, который я работал хорошо, когда не было фонового вращения, но не смог получить дескриптор ListSysView32, когда был.
Есть ли лучший способ сделать это из .Net?кдж