Источник: webdelphi
Продолжаем копошиться в дебрях и хитросплетениях Ribbon Controls. Сегодня на повестке дня настройка Ribbon Controls для русскоязычного населения плюс немного креатива в плане создания своих тем оформления для Ribbon Controls.
Помниться у кого-то из читателей блога возникал вопрос "Как руссифицировать меню Costumize Dialog?" . Давайте разбираться. Ведь ни с потолка же падают строки и вставляются сами в менюшку?
Самый простой способ решения подобных вопросов - это заглянуть в папку
C:\Program Files\Embarcadero\RAD Studio\7.0\lib\
и посмотреть модуль с названием, наподобие RibbonSrt или RibbonConst . Ведь разработчики должны соблюдать все правила написания программного кода, в том числе и избегать использования строковых и, по возможности, других констант в телах процедур и функций. Открываем папку и действительно наблюдаем там замечательный файлик RibbonConsts.dcu . Одноименный файл, но с расширением *.pas находится в папке
C:\Program Files\Embarcadero\RAD Studio\7.0\source\Win32\vcl\
Перетаскиваем RibbonConsts.pas себе в проект, подключаем в uses и открываем в редакторе кода. Теперь все, что от нас требуется - это грамотно и без ошибок перевести на русский язык все, содержащиеся в модуле строки. Там их немного - всего двадцать четыре штучки.
После руссификации модуля меню будет выглядеть примерно следующим образом:
Как видите, всё просто и не требует особых программистских способностей. Только уменя пользоваться переводчиком.
А теперь переходим к вопросу, которым я, ради собственного нездорового интереса, сейчас сижу и занимаюсь на работе (только бы не пришло начальство), а именно - изменение внешнего вида Ribbon. Или, говоря более понятным языком - создание собственных тем оформления для Ribbon Controls . Неуверен, что смогу так вот сходу за несколько часов во всём разобраться, да ещё и расписать в блоге, но постараюсь выложить как можно больше информации, если что - надеюсь на Вашу помощь в освоении темы. Итак поехали.
Ribbon Skins в Delphi 2010
Начнем изучение темы с того, что наиболее просто - цветовые схемы. В Delphi уже изначально есть три готовых компонента для цветовых схем:
- XPColorMap
- StanderdColorMap
- TwilightColorMap
Попробуем применить их на практике. По логике вещей и, судя по названию свойств у компонентов, в зависимости от цветовой схемы должны меняться цвета шрифтов и тени компонентов как минимум. Проверим на практике. Размещаем на форме, как обычно: ActionManager и Ribbon . Создаем парочку Action в менеджере, у риббона создаем один Tab и две группы (а можно и одну - как Вам угодно) и размещаем в группах наши Action"ы.
Теперь кидаем на форму простой ComboBox , все три доступные цветовые схемы и кнопку. У меня получилась вот такая неказистая формочка:
Теперь добавляем в ComboBox три строки, каждая из которых будет описывать одну из цветовых схем и в обработчике клика по кнопке пишем следующий код
1
2
3
4
5
6
7
8
|
[…]
case ComboBox1.ItemIndex of
0:Ribbon1.ColorMap:=XPColorMap1;
1:Ribbon1.ColorMap:=StandardColorMap1;
2:Ribbon1.ColorMap:=TwilightColorMap1;
end;
Ribbon1.Repaint:
[…] |
Запускаем приложение и проверяем, что получилось. Порадовало, что цвета шрифтов сменились:
Не порадовал глюк с панелью быстрого запуска - обратите на него внимание. Причём как оказалось глюк этот не пропадает даже если перезагрузить Delphi…хотя это может только на рабочей машинке глюк - дома проверю наверняка. А пока продолжим.
Сейчас мы рассмотрели один из вариантов смены цветовой схемы - с использованием стандартных, уже долгое время существующих компонентов цветовых схем.
Но у Ribbon также есть и свой тип TcustomRibbonColorMap в модуле Ribbon . Можно, да и видимо, нужно использовать этот тип данных при работе с цветовыми схемами Ribbon . Попробуем применить его.
После недолгих манипуляций с мышкой форма приложения приняла следующий вид:
Каждый из новых ColorBox будет описывать значение цвета для одного из свойств TcustomRibbonColorMap .
Дописывем обработчик события кнопки:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
[…]
var Ribbon: TCustomRibbonColorMap;
begin
case case ComboBox1.ItemIndex of
[…]
3: begin
Ribbon:=TCustomRibbonColorMap.Create(self);
With Ribbon do
begin
BevelMinimizedInner:=ColorBox1.Selected;
BevelMinimizedOuter:=ColorBox2.Selected;
BtnSelectedFont:=ColorBox3.Selected;
CaptionFontColor:=ColorBox4.Selected;
ControlColor:=ColorBox5.Selected;
ControlInactiveColor:=ColorBox6.Selected;
ControlFrameColor:=ColorBox7.Selected;
DisabledFontColor:=ColorBox8.Selected;
DocumentFontColor:=ColorBox16.Selected;
FontColor:=ColorBox15.Selected;
HighlightColor:=ColorBox14.Selected;
ActiveTabFontColor:=ColorBox13.Selected;
GroupFontColor:=ColorBox12.Selected;
InactiveTabFontColor:=ColorBox11.Selected;
QuickAccessToolbarMoreColor:=ColorBox10.Selected;
QuickAccessToolbarMoreBorderColor:=ColorBox9.Selected;
end;
Ribbon1.ColorMap:=Ribbon;
end;
end;
[…]
end; |
И теперь можем экспериментировать с цветовой схемой Ribbon сколько нашей душе угодно, подбирать свои цвета шрифтов и т.д. Например, я собрал вот такую "тошнотную" схемку:
Жуть, неправда ли? Но это проcто пример. А у нас остался ещё один открытый вопрос: как сменить не только цвет шрифта, но и тему оформления целиком? Ведь если просто прикинуть, сколько людей купили RAD Studio 2009-2010, сколько используют или пробуют использовать Ribbon Controls? И на всех всего 3 темы. Несерьёзно. Надо как-нибудь выделиться, создать что-то свое (на крайняк - купить за N зелёных енотов).
Благо разработчики из Embarcadero оставили нам возможность немного покреативить в свое удовольствие.
Судя по рисунку выше, креативщик из меня хреновенький, но я все-таки попробую. Первое, что следует сделать - понять каким образом и, самое главное, откуда беретя это красивое оформление панелей, менюшек и табов. Я решил оттолкнуться в своих поисках от модуля RibbonLunaStyleActnCtrls и поиски в итоге привели к следующему классу:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
TCustomRibbonSkin = class
public
type TRibbonSkinLoadType = (ltResource, ltFile);
private
FBitmap: TAlphaBitmap;
protected
procedure DoLoadByResource; virtual;
procedure DoLoadByFile; virtual;
public
constructor Create; virtual;
destructor Destroy; override;
function GetLoadType: TRibbonSkinLoadType; virtual;
function GetResourceHandle: THandle; virtual;
function GetLoadTypeValue: string; virtual;
procedure LoadSkin; virtual;
property Bitmap: TAlphaBitmap read FBitmap;
end; |
Получается с какого стиля оформления мы бы не начинали свои поиски - всё упрётся именно в этот класс. Как видите у этого класса не так уж и много свойств и методов.
С типом TribbonSkinLoadType всё вполне понятно - определяет откуда будет загружаться скрин: из ресурсного файла или же из файла на диске.
Далее одно единственное поле: FBitmap: TalphaBitmap - собственно это и есть файл с необходимыми изображениями для скина.
Следом идут два метода, которые срабатывают соответственно в зависимости от того откуда будет загружаться скин.
Но самое замечательное - это открытое для чтения свойство Bitmap . Помниться ещё когда у меня стояла Delphi 2009 я немог найти толком информации о расположении всех графических элементов в битмапе…надо было сразу искать здесь. Но это всё лирика. Давайте посмотрим как выглядит файл с элементами скина для Ribbon .
Возвращаемся к нашему приложению, бросаем на форму ещё одну кнопку, SaveDialog и пишем в свойстве Caption у кнопки "Сохранить скин" , а в обработчике такой код:
1
2
3
4
|
[…]
if SaveDialog1.Execute then
Ribbon1.Style.RibbonSkin.Bitmap.SaveToFile(SaveDialog1.FileName);
[…] |
Теперь мы можем воочую взглянуть на битмап скрина Ribbon и состряпать свой по образу и подобию. Файл весит не много ни мало 1056kb поэтому ради иллюстрации я приведу сжатый в gif и уменьшенный немного по размеру рисунок. Вот он:
Так как я не дизайнер и в PhotoShop практически ничего не соображаю, то ради эксперимнта я раскрасил немного некоторые области, дабы видеть что у меня получилось загрузить свой скин в программу. Теперь приступаем к фазе №2 - пишем свой модуль для загрузки скина .
Вы обращали внимание, что после первой же компиляции проекта с Ribbon в uses появляется как минимум один дополнительный модуль RibbonLunaStyleActnCtrls ? Вот такой же самый модуль мы и будем писать.
Создаем пустой модуль и даем ему какое0нибудь громогласное название, например: RibbonMegaStyleActnCtrls . Сразу в uses подключаем три модуля: ActnMan, RibbonStyleActnCtrls и Ribbon . А также объявляем одну константу:
1
|
const LoadType: TCustomRibbonSkin.TRibbonSkinLoadType = ltFile; |
То есть договариваемся, что самодельный скин будем грузить из bmp-файла. Теперь обявляем такой класс:
1
2
3
4
5
6
7
|
type
TRibbonMegaStyleActionBars = class(TRibbonStyleActionBars)
public
function GetColorMapClass(ActionBar: TCustomActionBar): TCustomColorMapClass; override;
function GetSkinClass: TCustomRibbonSkinClass; override;
function GetStyleName: string; override;
end; |
и расписываем его методы:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
implementation
uses
ActnMenus, SysUtils;
function TRibbonMegaStyleActionBars.GetColorMapClass(
ActionBar: TCustomActionBar): TCustomColorMapClass;
begin
Result := TRibbonLunaColorMap;
end;
function TRibbonMegaStyleActionBars.GetSkinClass: TCustomRibbonSkinClass;
begin
Result := TRibbonMegaSkin;
end;
function TRibbonMegaStyleActionBars.GetStyleName: string;
begin
Result := 'Ribbon - Mega'; // русскими буквами не писать!
end; |
Обратите внимание на первый метод - я использовал уже готовую цветовую схему от скина Luna , чтобы сильно не забивать пост лишними строками кода, Вы же можете определить в своем модуле собственную цветовую схему для скина, полагаю, что много времени это не займёт.
Теперь создаем класс для нашего скина, который будем использовать в программе:
1
2
3
4
5
|
TRibbonMegaSkin = class(TCustomRibbonSkin)
public
function GetLoadTypeValue: string; override;
function GetLoadType: TCustomRibbonSkin.TRibbonSkinLoadType; override;
end; |
Методы опять же просты и неказисты (дли примера):
1
2
3
4
|
function TRibbonMegaSkin.GetLoadType: TCustomRibbonSkin.TRibbonSkinLoadType;
begin
Result := LoadType; //использовали нашу константу
end; |
1
2
3
4
5
|
function TRibbonMegaSkin.GetLoadTypeValue: string;
begin
Result := ExtractFilePath(ParamStr(0)) + 'mega.bmp'; //указали расположение файла
end;
end; |
Если не устраивает то, что скин будет лежать прямо рядом с исполняемым файлом - нет проблем, укажите свой путь. А нам остается только зарегистрировать наш новый скин и вовремя его выгрузить. Не будем опять же изобретать велосипед (тем более, что на скорую руку он может получиться далеко не с круглыми колесами), а пишем тоже самое, что и для стандартных скинов в секциях initialization и finalization :
1
2
3
4
5
6
7
|
initialization
RibbonMegaStyle := TRibbonMegaStyleActionBars.Create;
RegisterActnBarStyle(RibbonMegaStyle);
finalization
UnregisterActnBarStyle(RibbonMegaStyle);
RibbonMegaStyle.Free; |
Да и незабудьте перед implementation объявить глобальную переменную:
1
2
|
var
RibbonMegaStyle: TRibbonMegaStyleActionBars; |
Теперь подключаем наш модуль в uses и в любом удобном для вас обработчике пишем:
1
2
3
4
|
[…]
Ribbon1.Style:=RibbonMegaStyle;
Ribbon1.Repaint;
[…] |
Я добавил эти строки в обработчик кнопки для применения цветовой схемы. Вот какой вид приняла моя программа после того как я поиздевался над скином:
Жутко некрасиво, но зато ярко и сразу видно, что кто-то нарочно изуродовал Ribbon .
На сегодня всё. В качестве бонуса к посту прилагается та самая программка, которую я писал по ходу дела работы над статьей. В архиве с программой вы найдёте также её исходники, включая модули RibbonConsts (с одной переведенной строкой) и модулем тестового скина, который, в случае чего, избавит Вас от лишней писанины - просто поменяете путь и название файла и скин готов.