Версия для печати


Создание своего стиля в графическом интерфейсе. Продолжение темы полупрозрачных кнопок.
http://www.delphikingdom.com/asp/viewitem.asp?catalogID=1301

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 {стандартного органа
управления для стиля XP нет}

См. модули 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);

TCepStyleActionBars

Класс TActionBarStyleEx содержит виртуальные абстрактные методы, возвращающие классы всех органов управления. Необходимо перекрыть их и возвратить свои созданные классы, что реализовано в компоненте TCepStyleActionBars. В модуле CepStyleActnCtrls созданы потомки только основных используемых классов, аналогично можно создать дополнительные классы органов управления для разных акций, приведенный выше список является обязательным минимумом, который ограничен только пределами вашей фантазии.

Кроме перекрытых функций добавлена функция ControlKind возвращающая вид органа управления. Что бы несколько упростить процесс замены существующих классов, своими собственными, я ввел список видов органов управления TControlKind, которые могут использоваться, и массив DefControlClasses содержащий классы органов управления определенного вида. В программе при возвращении классов я использую не константы, а значения из массива DefControlClasses.

IImg

Все органы управления рисуются единообразно с помощью нескольких общих процедур, что позволяет снизить дублирование кода. Для отображения картинок в различных состояниях используется графический объект TRichImageList из модуля BitOp. Он создавался для рисования полупрозрачных кнопок. Органы управления изображающие картинку используют интерфейс IImg, который возвращает соответствующий графический объект.

TCepStyleButton

Обычная кнопка расположенная на инструментальной линейке. При отрисовке фона используется градиентная заливка, если инструментальная линейка лежит на контейнере со свойством DrawingStyle = dsGradient. Для определения цветов используется процедура GetColorsInfo.

При отрисовке заголовка недоступной кнопки используются не стандартный цвет серого текста, а цвет фона, что на мой взгляд более красиво.

TCepStyleDropDownBtn

Та же кнопка, но со стрелкой и меню. Кроме прочего перекрывается метод возвращающий класс, всплывающего (при нажатии на стрелку) меню. В данном случае это всегда TCepStylePopupMenu, но можно для разных кнопок использовать разные меню.

TCepStyleCustomizePopup

Меню всплывающее при нажатии на кнопку расположенную справа инструментальной линейки. Это меню содержит кнопки, которые в данный момент не влезают и пункты «Add or Remove Buttons», «Reset Toolbar», «Дополнительные настройки». Последний пункт меню вызывающий диалог настройки инструментальной линейки, создается в перекрытом методе SetActionClient.

Еще перекрывается метод возвращающий класс пунктов подменю Add or Remove Buttons (см. TCepStyleAddRemoveItem). Чтобы русифицировать заголовки (см. модуль Consts).

TCepToolScrollBtn

Кнопка, расположенная справа инструментальной линейки. Чтобы она была видна, должно быть установлено свойство ActionManager.ActionBars[i].AutoSize:=false.

TCepStyleMenuButton

Пункт главного меню. В отличие от стандартной реализации выбранный пункт изображается со скошенными краями, что несомненно, красивее :)

TCepStylePopupMenu

Всплывающее меню. Перекрывается метод возвращающий класс пункта меню со свернутыми редкоиспользуемыми строками (см. TCepStyleExpandBtn).

TCepStyleExpandBtn

При нажатии на этот орган управления раскрываются свернутые пункты меню.

TCepStyleAddRemoveItem

Пункт меню для отображения/сокрытия кнопок

TCepStyleMenuItem

Обычный пункт всплывающего меню.

IStreamCustomActionDockBar

Интерфейс для загрузки/сохранения настроек в поток (TStream). Для чтения/записи в поток всего состояния TActionManager используйте процедуры ActionManagerLoad и ActionManagerSave.

TGradientActionToolBar и TGradientActionMainMenuBar

Эти классы почти идентичны своим предкам, но могут использовать градиентную заливку и поддерживают IStreamCustomActionDockBar.

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

TActionListCep

Это специальная акция для создания списков органов управления, на подобии пункта главного меню 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 будут добавлены подпункты с названием соответствующей формы. При разрушении формы они будут автоматически удалены.

TActionLinkedControlCep

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

Инсталляция

Для того, чтобы увидеть компоненты в IDE последовательно сынсталлируйте пакеты ControlsCepEx.dpk и EditorsCepEx.dpk. Если у вас BDS, то ищите их в папке Packages10, если Delphi 5 то в Packages5, при этом будет доступен только компонент TSpeedButtonCep. Недостающий в более ранних версиях код, расположен в модуле GraphUtilEx.pas. Теоретически (с небольшими переделками) визуальный стиль может работать, начиная с Delphi7, но я не проверял.

Если у Вас уже был ранее установлен компонент TSpeedButtonCep, то предварительно удалите его.



К материалу прилагаются файлы: