bon818 писал(а):Что это за стандартные системные механизмы, для создания каких-угодно боковых панелей?
Стандартный механизм следующий: панель задач в нижней строке «Пуска», языковая панель (там, где выбор раскладки), панель быстро запуска (у тех, кто её не выключил), и создаваемые пользователями панели с ярлыками — всё это живёт внутри контрола
ReBar, так же известного как
CoolBar. Желающие могут посмотреть с помощью Spy++ или другого вьювера оконной иерархии — всё лежит внутри контейнеров класса
ReBarWindow32.
Для тех, кто не знает: ReBar (он же CoolBar) — этот тот самый контрол, который позволяет положить в него другие контролы (как правило — ToolBar-контролы), а он любезно предоставит вам готовый функционал в виде возможности двигать «полоски», менять их порядок следования, размеры, одним словом — компоновку.
Так вот, по крайней мере, каждый пользователь может создать свою собственную панель на основе произвольной папке (предполагается, что в ней лежат ярлыки на нужные программы или файлы или веб-ресурсы или шелл-команды). Лично я, например, сто лет пользуюсь вот такой панелью, которая у меня прилеплена к верхней границе экрана:
- my_top_panel.png (42.75 Кб) Просмотров: 1519
Но речь вовсе не о том, что пользователь может сам себе создать такую панель на базе папки!
Речь о том, что сама архитектура оболочки Windows позволяет
любому программисту написать свою собственную панель (содержащую
произвольную начинку, будь то какие-то контролы или график загрузки процессора или график стоимости акций на бирже или отображение анекдотов, а может быть отображение температур дисков и т.п.).
Эту custom-панель (написанную кем-то со стороны) можно будет помещать в нижнюю панель Пуска или прикреплять к боковой грани экрана (верхней, левой, правой), либо иметь в виде ни к чему не прилепленного попап-окна. Эта custom-панель будет жить рядом с панелью задач, рядом с языковой панелью — их порядок и взаиморасположение можно будет менять произвольно.
Вот я свою верхнюю панель перетащил и прилепил к левой границе экрана и включил ещё пару панелей, которыми я никогда не пользовался:
- my_top_panel_on_left_edge.png (34.98 Кб) Просмотров: 1519
Обращаю внимание на обведённый красным указатель мыши, который в момент скришота тащит за «корешок» ReBar-а — как раз за возможность произвольной компоновки и отвечает контрол ReBar.
А вот я это сборище вернул обратно наверх, поменял визуальную компоновку (мышкой) и добавил к ним ещё и языковую панель:
- my_top_panel_2.png (52.94 Кб) Просмотров: 1519
Ладно, довольно примеров.
Суть, ещё раз, в том, что Windows позволяет кому угодно взять и написать свою произвольную панель.При этом, программисту не нужно беспокоиться за следующие вещи, потому что Windows берёт ответственность за них на себя:
- За создание контейнера для собственной панели
- За реализацию логики авто-скрытия панели (если надо), за то, чтобы обычные окна не перекрывлаи собой панели, когда развёрнуты на весь экран.
- За механизм перетаскивания панелей, перегруппировки, за возможность менять их взаимное расположение
- За запоминание (для каждого пользователя), где, в каком месте и как пользователь поместил каждую панель, чтобы при следующем входе в систему расположить всё снова так, как было раньше.
То есть, система предоставляет программисту готовый контейнер, внутри которого он может делать что угодно (хоть на голове плясать). Этот контейнер будет помещён в ReBar-контрол, то есть юзер сможет двигать панели, менять расположение, включать режим «Закрепить панели инструментов», а система всё это запомнит.
Так как же, в конце-концов, программисту написать свою собственную произвольную панель с произвольной начинкой?
Для этого, в лучших традициях ООП и COM, программисту нужно написать класс, поддерживающий интерфейс
IDeskBand (или
IDeskBand2, в котором добавлено несколько методов для поддержки «полупрозрачных» панелей).
Далее ActiveX-библиотека (DLL), реализующая этот класс, регистрируется в реестре в специальном месте.
Вот так совпадение, из всех языков программирования, написать ActiveX-библиотеку с классом, реализующим некий системный интерфейс, проще всего на VB6 — он как раз создан для этих задач, он единственный, где классы это априори COM-классы, а объекты — априори COM-объекты. Всего-то написать
Implements IDeskBand в теле класса первой строчкой (вернее второй — после
Option Explicit).
На самом деле, конечно, тут есть своя масса сложностей.Когда проводник (explorer.exe) запускается, он идёт в реестр и проверяет специальный раздел, чтобы найти список зарегистрированных в системе custom-панелей. Если одну из таких панелей нужно отображать (потому что пользователь уже включил её отображение в меню, которое можно было увидеть на скриншотах выше), то проводник порождает экземпляр класса (олицетворяющего панель), создаёт для панели контейнер и взаимодействует через методы этого класса с кодом, который и реализует произвольную панель.
Кстати говоря, абсолютно тем же методом реализуются панели для окна проводника (того окна, в котором отображаются файлы и папки) и для Internet Explorer-а, разница только в разделе реестра, где такие панели регистрируются.
___________
На самом деле, помимо
IDeskBand нужно проимплементировать (реализовать) ещё парочку интерфейсов:
- IObjectWithSite — через метод которого оболочка передаёт нам указатель на объект-контейнер, внутри которого мы (мы = панель) должны осуществлять жизнедеятельность.
- IPersistStreamInit — через который осуществляется сохранение/загрузка специфичных для панели данных, например данных о её состоянии.
Если вкратце, то процесс создания и встраивания панели в оконную иерархию оболочки происходит по следующему сценарию:
- Хост (так я дальше буду называть процесс explorer.exe или процесс Internet Explorer-а) создаёт экземпляр нашего класса.
- Хост вызывает у нашего объекта метод IDeskBand::GetBandInfo с целью получить информацию о нашей панели. Мы внутри этого метода должны заполнить структуру DESKBANDINFO, на которую будет смотреть хост. В этой структуре не так много полей: название панели, максимальные габариты, минимальные габариты, текущие габариты, минимальный шаг изменения размеров по вертикальной оси (например, для панели со значками имеет смысл сделать в качестве шага размер значка, чтобы размер панели изменялся кратно размеру значка), задний цвет фона, флаги.
- Хост, в соответствии с полученной от предыдущего шага информацией, порождает контейнер для будущей панели.
- Хост вызывает метод IObjectWithSite::SetSite нашего объекта и передаёт нам ссылку на другой объект, олицетворяющий контейнер, в которой мы (как панель) должны быть встроены. У этого объекта мы должны запросить интерфейс IOleWindow и вызвать метод GetWindow — тут мы получил хендл (HWND) окна-контейнера.
- Дальше, имея хендл окна контейнера, мы можем в нём порождать другие дочерние контролы (например ToolBar или какие угодно другие), либо рисовать в нём что-то. Можно, с другой стороны, если кому-то в тягость порождать дочерние контролы или рисовать что-то вручную, попробовать строить готовый VB-шный UserControl в область контейнера, используя OLE-шные способы встраивания.
Разумеется, нужно реализовать и другие методы
IDeskBand (который унаследован от
IDockingWindow) — ShowDW, ResizeBorderDW, CloseDW.
Второй момент состоит в том, что в Windows 7 этот прекрасный механизм изничтожили. Это ещё одна из
причин, почему я не перехожу на Windows 7. Но и там на замену (вроде бы как) предложили
другой встроенный системный механизм, которым следует пользоваться.
bon818 писал(а):И причем здесь workarea(рабочая область) , где про это можно прочитать?
Руководствуясь соображениями, что пользователю понадобится прилеплять различные панели и окна к боковым граням экрана, что такие приложения рано или поздно появятся, и что как минимум сам механизм, который я описал выше, тоже даёт возможность прилеплять панели к боковым граням, люди в Microsoft создали понятие «work area» — это область, которую занимают обычные окна при максимизации (разворачивании «на весь экран»), и область, до которой ужимается рабочий стол, а вернее все значки на рабочем столе.
Моя мысль была в том, что если не использовать системный механизм с
IDeskBand, который я описал выше, а делать всё вручную, то чтобы наша импровизированная боковая панель не страдала от того, что её постоянно накрывают какие-то окна, есть смысл переустановить область work area (
SPI_SETWORKAREA) так, чтобы наша боковая панель оказалась вне work area.