Cepгей Poщин дата публикации 12-02-2007 02:06 Создание своего стиля в графическом интерфейсе. Продолжение темы полупрозрачных кнопок.
В Delphi 6 появился компонент TActionManager дающий
возможность изменять состав меню и инструментальных линеек
(TActionToolBar), а так же полностью изменить внешний вид графического
интерфейса. В Delphi 7, появилась возможность создавать графический
интерфейс в стиле XP. В Delphi 2006 компонент TControlBar может
использовать градиентную заливку. Мне захотелось распространить эту
возможность на инструментальные линейки, пункты меню и кнопки, т. е.
создать свой визуальный стиль (см. модуль CepStyleActnCtrls). Что бы не
повторять многократно растиражированные статьи посмотрите ссылки http://docs.luksian.com/programming/delphi/delphi7/?f=Glava6/Index7.html,
http://dn.codegear.com/article/33461.
Процесс создания визуального стиля сводится к созданию
потомка класса TActionBarStyleEx. И потомков следующих органов
управления:
TXPStyleButton = class(TCustomButtonControl);
TXPStyleDropDownBtn = class(TCustomDropDownButton);
TXPStyleCustomizePopup = class(TCustomizeActionToolBar);
TXPStyleToolScrollBtn = class(TCustomToolScrollBtn);
TXPStyleMenuButton = class(TCustomMenuButton);
TXPStylePopupMenu = class(TCustomActionPopupMenu);
TXPStyleExpandBtn = class(TCustomMenuExpandBtn);
TXPStyleAddRemoveItem = class(TCustomAddRemoveItem);
TXPStyleMenuItem = class(TCustomMenuItem);
TXPColorMap = class(TCustomActionBarColorMap);
TCustomComboControl
|
|
См. модули XPActnCtrls и ActnMenus.
Внешний вид программы TestCepStyle
Можно создавать потомков TXPStyleXXX для обеспечения
бoльшей совместимости со стилем XP и меньшей трудоемкости, а можно
создавать потомков TCustomXXX, что на мой взгляд предпочтительнее, т.
к. модуль XPActnCtrls сделан явно на скорую руку и далек от
совершенства (это субъективное мнение). Если хотите разобраться в
деталях реализации, настоятельно рекомендую смотреть исходики, там
довольно много комментариев.
Класс TActionBarStyleEx занимается в основном тем, что
возвращает соответствующий класс для последующего создания нужного
органа управления. Того же самого можно добиться если установить
обработчик onGetControlClass, onGetPopupClass. Например:
procedure
TMainForm.PopupActionBar1GetControlClass(Sender: TCustomActionBar;
AnItem: TActionClient; var
ControlClass: TCustomActionControlClass);
begin
if AnItem is TActionClientItem then
ControlClass := ActionManager1.Style.GetControlClass(Sender,
TActionClientItem(AnItem));
end;
|
|
Не смотря на то, что использование TActionManager,
TActionToolBar, TActionMainMenuBar и механизма «акций»
(actions) является рекомендованным и давно существующим его используют
относительно редко (судя по вопросам с круглого стола). Возможно, это
связано со сложностью динамического формирования меню и
инструментальных линеек. Например, для многодокументного приложения
обязателен пункт главного, содержащий список всех дочерних форм. Чтобы
упростить его формирование, созданы два новых класса TActionListCep и
TActionLinkedControlCep. См. категорию Windows в списке стандартных
акций.
В дополнение созданы два компонента, которые
поддерживают градиентную заливку и запись состояния в поток:
TGradientActionToolBar = class
(TActionToolBar);
TGradientActionMainMenuBar = class
(TActionMainMenuBar);
|
|
Класс TActionBarStyleEx содержит виртуальные
абстрактные методы, возвращающие классы всех органов управления.
Необходимо перекрыть их и возвратить свои созданные классы, что
реализовано в компоненте TCepStyleActionBars. В модуле
CepStyleActnCtrls созданы потомки только основных используемых классов,
аналогично можно создать дополнительные классы органов управления для
разных акций, приведенный выше список является обязательным минимумом,
который ограничен только пределами вашей фантазии.
Кроме перекрытых функций добавлена функция ControlKind
возвращающая вид органа управления. Что бы несколько упростить процесс
замены существующих классов, своими собственными, я ввел список видов
органов управления TControlKind, которые могут использоваться, и массив
DefControlClasses содержащий классы органов управления определенного
вида. В программе при возвращении классов я использую не константы, а
значения из массива DefControlClasses.
Все органы управления рисуются единообразно с помощью
нескольких общих процедур, что позволяет снизить дублирование кода. Для
отображения картинок в различных состояниях используется графический
объект TRichImageList из модуля BitOp. Он создавался для рисования
полупрозрачных кнопок.
Органы управления изображающие картинку используют интерфейс IImg,
который возвращает соответствующий графический объект.
Обычная кнопка расположенная на инструментальной
линейке. При отрисовке фона используется градиентная заливка, если
инструментальная линейка лежит на контейнере со свойством DrawingStyle
= dsGradient. Для определения цветов используется процедура
GetColorsInfo.
При отрисовке заголовка недоступной кнопки
используются не стандартный цвет серого текста, а цвет фона, что на мой
взгляд более красиво.
Та же кнопка, но со стрелкой и меню. Кроме прочего
перекрывается метод возвращающий класс, всплывающего (при нажатии на
стрелку) меню. В данном случае это всегда TCepStylePopupMenu, но можно
для разных кнопок использовать разные меню.
Меню всплывающее при нажатии на кнопку расположенную
справа инструментальной линейки. Это меню содержит кнопки, которые в
данный момент не влезают и пункты «Add or Remove Buttons»,
«Reset Toolbar», «Дополнительные настройки».
Последний пункт меню вызывающий диалог настройки инструментальной
линейки, создается в перекрытом методе SetActionClient.
Еще перекрывается метод возвращающий класс пунктов
подменю Add or Remove Buttons (см. TCepStyleAddRemoveItem). Чтобы
русифицировать заголовки (см. модуль Consts).
Кнопка, расположенная справа инструментальной линейки.
Чтобы она была видна, должно быть установлено свойство
ActionManager.ActionBars[i].AutoSize:=false.
Пункт главного меню. В отличие от стандартной
реализации выбранный пункт изображается со скошенными краями, что
несомненно, красивее :)
Всплывающее меню. Перекрывается метод возвращающий
класс пункта меню со свернутыми редкоиспользуемыми строками (см.
TCepStyleExpandBtn).
При нажатии на этот орган управления раскрываются
свернутые пункты меню.
Пункт меню для отображения/сокрытия кнопок
Обычный пункт всплывающего меню.
Интерфейс для загрузки/сохранения настроек в поток
(TStream). Для чтения/записи в поток всего состояния TActionManager
используйте процедуры ActionManagerLoad и ActionManagerSave.
Эти классы почти идентичны своим предкам, но могут
использовать градиентную заливку и поддерживают
IStreamCustomActionDockBar.
Если компонент перетащить и бросить в свободную
область экрана, то он окажется в форме-носителе с крестиком в правом
верхнем углу. В некоторых случаях не нужно, что бы пользователь мог
закрыть, таким образом, меню, или инструментальную линейку. В
TGradientActionToolBar добавлено свойство EnableClose управляющее
наличием крестика, а в TGradientActionMainMenuBar крестика убирается,
безусловно.
Это специальная акция для создания списков органов
управления, на подобии пункта главного меню Window. Создание и
добавление формы в список может выглядеть примерно так:
procedure
TMainForm.actNewMDIChildExecute(Sender: TObject);
var N: integer;
F: TForm;
begin
F := TForm.CreateNew(self);
F.FormStyle := fsMDIChild;
F.Parent := self;
N := MDIChildCount;
F.Caption := 'Дочерняя форма
'+inttostr(N);
actFormList.AddLinkedControl(F);
end;
|
|
Ко всем пунктам меню и кнопкам использующим акцию
actFormList будут добавлены подпункты с названием соответствующей
формы. При разрушении формы они будут автоматически удалены.
Эта акция используется для управления видимостью
органа управления заданного в свойстве Control. Если это форма, то она
отображается и перемещается на верхний уровень, иначе просто меняется
свойство visible.
Для того, чтобы увидеть компоненты в IDE
последовательно сынсталлируйте пакеты ControlsCepEx.dpk и
EditorsCepEx.dpk. Если у вас BDS, то ищите их в папке Packages10, если
Delphi 5 то в Packages5, при этом будет доступен только компонент
TSpeedButtonCep. Недостающий в более ранних версиях код, расположен в
модуле GraphUtilEx.pas. Теоретически (с небольшими переделками)
визуальный стиль может работать, начиная с Delphi7, но я не проверял.
Если у Вас уже был ранее установлен компонент
TSpeedButtonCep, то предварительно удалите его.
К материалу прилагаются файлы:
[Фоновые рисунки, прозрачность, скины ] [Внешний вид в стиле ...]
Обсуждение материала [ 06-11-2009 01:30 ] 17 сообщений |