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

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

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

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

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

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

Пожалуйста, выскажите свое мнение. Я делаю это с помощью Windows SDk


person Sujay Ghosh    schedule 03.11.2009    source источник
comment
Может быть, вы могли бы отредактировать вопрос, указав больше информации о том, что вы собираетесь делать с ручкой, когда она у вас будет?   -  person Mark Ransom    schedule 03.11.2009
comment
Обратите внимание, что объекты на рабочих столах XP/Vista/7 НЕ являются файлами. Например, общие объекты, найденные там, — это «Мой компьютер» и «Корзина». Они известны своими PIDL. PIDL — это обобщение имени файла. Поэтому вы, вероятно, заинтересованы в выбранных PIDL.   -  person MSalters    schedule 04.11.2009
comment
Итак, если я копирую документ, например, Questions.doc (документ Word), мне нужно получить PIDL для этого или я получаю его в виде файла.   -  person Sujay Ghosh    schedule 05.11.2009
comment
Это сообщение в блоге Microsoft отвечает именно на этот вопрос.   -  person GetFree    schedule 29.05.2019


Ответы (2)


В свете недавнего обсуждения Meta жалуясь на то, что на такие вопросы, как этот, «не было должным образом дан ответ», я попытаюсь дать ответ на этот вопрос. Не означает, что я думаю, что ответ меклариана плохо — на самом деле, далеко не так. Но его явно посчитали неудовлетворительным, так что, возможно, я смогу добавить некоторые дополнительные сведения.

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

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

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

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

<эм>[ <сильный>. . . ]

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

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

Если вы хотите получить доступ к окну рабочего стола Проводника, вам нужно выполнить некоторую дополнительную работу помимо простого вызова функции GetDesktopWindow. В частности, вам нужно просмотреть дочерние окна фактического окна рабочего стола, чтобы найти то, которое Explorer использует для отображения значков. Для этого вызовите функцию FindWindowEx. чтобы получить каждое окно в иерархии, пока вы не доберетесь до того, который вы хотите. Он имеет имя класса 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;

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

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

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

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

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

person Cody Gray    schedule 17.04.2011
comment
Спасибо за комментарий и ссылки. Это не имеет ничего общего с автоматизацией пользовательского интерфейса. Я позволю себе не согласиться с утверждением, что вы не должны делать это в первую очередь - на самом деле итерация через окна, а иногда и COM-сантехника, является единственным способом добраться до окон. - person Sujay Ghosh; 17.04.2011
comment
@Sujay: Этот комментарий полностью упускает суть. Вы не должны открывать эти окна. Я сравнил это с кражей игрушек у других людей, когда они не давали тебе разрешения играть с ними. Это не имеет ничего общего с COM; речь идет о рабочем столе Windows, принадлежащем Shell. - person Cody Gray; 17.04.2011
comment
Вы не должны подходить к этим окнам. Моя работа требует, чтобы я использовал эти окна. Приступить к использованию этих окон элементарно, вы также можете войти в процессы - en.wikipedia.org/wiki/DLL_injection :-), и есть несколько программ, которые это делают. (Я говорю не только о вирусах) ..LOL - person Sujay Ghosh; 17.04.2011
comment
@Sujay: я знаю о плохих методах программирования. Вы так и не поняли, что именно вам нужно сделать. Кроме того, вы можете полностью игнорировать мои предупреждения не делать этого. Это недокументировано, это может быть взломано, и вам специально рекомендуется не делать этого, но это никогда никому не мешало делать это раньше. Теперь у вас есть знания и возможности для поиска обоих окон рабочего стола. - person Cody Gray; 17.04.2011
comment
Я полностью согласен с тем, что это обязательно сломается, и это действительно сломается, так как это полностью зависит от того, как MS разместила окна. Мне тоже это не нравится, но, к сожалению, это единственный способ. Например, код, разработанный для доступа к правой панели проводника Windows в Windows XP, не будет работать в Windows 7, поскольку MS изменила дизайн. Что касается проблемы, я нашел решение давно, я использовал Spy, чтобы получить окна. - person Sujay Ghosh; 17.04.2011

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

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

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

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

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

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

person meklarian    schedule 03.11.2009
comment
Но Spy++ также возвращает дескриптор окна, а дескриптор, возвращаемый Spy++ и GetDesktopWindow, отличается. - person Sujay Ghosh; 04.11.2009