Подтвердить что ты не робот

Как получить дескриптор окна на рабочем столе?

API Windows предоставляет API GetDesktopWindow(), который возвращает дескриптор окна

Но я тестировал с помощью Spy ++, и я обнаружил, что дескриптор окна рабочего стола и дескриптор окна "Рабочий стол Windows" не совпадают.

Поскольку "Рабочий стол Windows" представляет собой представление списка, мне нужно сделать следующее

1) HANDLE hWnd = GetDesktopWindow() ;
2) FindWindow(hWnd, ..... ) with the SyslistView32 as the Window class.

Как только я получу дескриптор Window, я хочу использовать SendMessage() для операций, таких как получение выбранного имени файла, количество выбранных файлов и т.д.

Просьба высказать свое мнение. Я делаю это, используя SDK Windows

4b9b3361

Ответ 1

В свете недавней дискуссии о Meta, жалующейся на то, что такие вопросы, как этот, "не получили должного ответа", я попытаюсь дать отвечая на это вихрем. Не подразумевать, что я думаю, что меклиальный ответ плох - на самом деле, из него. Но это явно считалось неудовлетворительным, поэтому, возможно, я смогу заполнить некоторые дополнительные детали.

Ваша проблема возникает из-за довольно распространенной путаницы в отношении того, что на самом деле представляет собой настольное окно. Функция GetDesktopWindow выполняет именно то, что она задокументировала: возвращает дескриптор окна рабочего стола. Это, однако, не то же окно, которое содержит значки на рабочем столе. Это совершенно другое окно, появившееся впервые в Windows 95. Фактически это элемент управления ListView, установленный в представлении "Большие значки", с фактическим окном рабочего стола в качестве его родителя.

Раймонд Чен, разработчик команды Windows Shell, предоставляет дополнительные сведения в следующей статье Windows Confidential: "Остатки от Windows 3.0"

[.,.] Хотя в Windows 3.0 значки на рабочем столе представляли минимизированные окна, в Windows 95 рабочий стол выступал в качестве контейнера значков.

Рабочий стол Windows 95 фактически был окном, созданным проводником, который закрывал ваш экран (но сидел под всеми другими окнами на рабочем столе). Это окно, в котором отображаются ваши значки. По-прежнему было окно рабочего стола окна менеджера под окном (окно, которое вы получаете, если вы вызываете GetDesktopWindow), но вы его никогда не видели, потому что он был закрыт рабочим столом Windows 95 - так же, как деревянные панели в подвале моего коллеги дома покрыла оригинальную стену и капсулу времени за стеной.

[.,.]

Этот дизайн рабочего стола практически не изменился с момента его появления в Windows 95. На типичной машине исходный рабочий стол по-прежнему существует, но полностью покрыт рабочим столом Explorer.

Итак, окно, возвращаемое функцией GetDesktopWindow, представляет собой фактическое окно рабочего стола, единственное, что у нас было в Windows 3.0. Рабочий стол Explorer (тот, который содержит все ваши значки) - это просто другое окно, сидящее поверх окна рабочего стола (хотя оно полностью покрывает оригинал), которое не было добавлено до Windows 95.

Если вы хотите получить дескриптор окна рабочего стола Explorer, вам нужно выполнить дополнительную работу, кроме простого вызова функции GetDesktopWindow. В частности, вам нужно пройти через дочерние окна реального окна рабочего стола, чтобы найти тот, который использует Explorer для отображения значков. Сделайте это, вызвав FindWindowEx function, чтобы получить каждое окно в иерархии, пока не дойдете до того, что вы хотите. Он имеет имя класса SysListView32. Вероятно, вы также захотите использовать функцию GetShellWindow, которая возвращает дескриптор окна рабочего стола Shell, чтобы помочь вам начать работу.

Код может выглядеть так (предупреждение: этот код не проверен, и я не рекомендую его использовать в любом случае!):

HWND hShellWnd = GetShellWindow();
HWND hDefView = FindWindowEx(hShellWnd, NULL, _T("SHELLDLL_DefView"), NULL);
HWND folderView = FindWindowEx(hDefView, NULL, _T("SysListView32"), NULL);
return folderView;

Я отметил там, что я действительно не рекомендую использовать этот код. Почему нет? Поскольку почти в каждом случае, когда вы хотите получить дескриптор окна рабочего стола (либо фактическое окно рабочего стола, либо рабочий стол Explorer), вы делаете что-то неправильно.

Это не то, как вы должны взаимодействовать с окном рабочего стола. На самом деле, вы на самом деле не должны взаимодействовать с ним вообще! Помните, как вы узнали, когда вы были ребенком, что вы не должны играть с вещами, принадлежащими другим людям без их разрешения? Ну, рабочий стол принадлежит Windows (точнее, Shell), и он не дал вам разрешения играть со своими игрушками! И, как и любой хороший ребенок, "Шелл" подвержен подгонке, когда вы пытаетесь играть со своими игрушками, не спрашивая.

Тот же Raymond Chen опубликовал еще одну статью в своем блоге, в которой подробно описывается очень конкретный случай под названием Что такого особенного в окне рабочего стола?

Помимо примера, который он дает, это принципиально не способ автоматизации пользовательского интерфейса. Он слишком хрупок, слишком проблематичен и слишком подвержен взлому будущих версий Windows. Вместо этого определите, что именно вы на самом деле пытаетесь выполнить, а затем выполните поиск функции, которая позволит вам это сделать.

Если такая функция не существует, урок, который нужно извлечь, заключается не в том, что Microsoft просто хочет сделать жизнь труднее для разработчиков. Но скорее, что вы не должны делать это в первую очередь.

Ответ 2

Если вы хотите, чтобы окно рабочего стола было определено в GetDesktopWindow(), используйте этот дескриптор окна. Это дескриптор окна, который вы должны использовать для поиска окон верхнего уровня и других связанных с ним действий.

То, что вы видите в Spy ++, - это просто контент, нарисованный как рабочий стол на вашем сеансе. Если вы используете автоматическую локализацию в Spy ++, вы увидите, что объявленное SysListView32 окно является дочерним окном оболочки вашего исследователя. Чрезвычайно редко кому-то нужен доступ к этому окну. Кроме того, наличие этого окна может быть изменено между версиями окон.

Изменить (дополнительная информация)

Если вы хотите взаимодействовать или размещать вещи на рабочем столе операционной системы, вам может быть лучше обслуживаться другими API. Вот два таких API, которые могут выполнить это, в зависимости от целевой версии Windows.

Боковая панель Windows @MSDN
Это доступно в Vista и Windows 7

Использование Active Desktop @MSDN
Это доступно в Windows 2000 и XP, хотя часто отключается пользователями и системными администраторами.