Подписка

добавить на Яндекс

Наши проекты

Delphi+Google

Google API

Google API в Delphi - проект с открытым исходным кодом.

Chrono

Chrono

Хронометр - программа для ведения списка задач.

ODFProc

ODFProc

ODFProc - работа с документами OpenOffice в Lazarus и FreePascal.

Поддержка блога

А тут я коплю на лицензию Delphi XE на iPad =).
Сумма пожертвования не фиксирована.

Публикации

Год назад

Случайный пост

Последние

Сообщения форума

Комментарии

Социальные сети

Google

Facebook

Twitter

Опрос

Вы сейчас или в ближайшем обозримом будущем планируете разрабатывать кроссплатформенное приложение с использованием Firemonkey?



Loading ... Loading ...

Блоги и сообщества

Статьи по Delphi DelphiFeeds.ru - Все Delphi-блоги Рунета Сообщество умных людей VR-Online.RU Бесплатный журнал для программистов и всех, кто интересуется IT Статьи и уроки по Delphi Новостной блог о высоких технологиях
Система Orphus
Опубликовал Vlad 31 января 2010 в 20:58.
Категории: Компоненты Delphi, Основы Delphi.


Как Вы, наверное, знаете из комментариев в блоге сейчас я работаю над объединением всех статей про Ribbon Controls в Delphi в один большой документ. Что получится в итоге - пока не известно даже мне. Может это будет простой пост на 7000+ слов с картинками, а может и целый справочник для начинающих программистов. Пока кодовое название документа "Ribbon Controls. Мышинное программирование". Может звучит немного странно, но вполне отражает суть того, что пока изложено. Дело в том, что большинство действий, совершаемых при работе с Ribbon - это движения мышкой по экрану. Эдакое программирование для дошкольников - взял кнопочку, перетянул на панельку, выбрал мышкой в свойствах значение, ткнул мышкой 2 раза, написал 1 строчку и всё готово. Только вот, как показывают вопросы по Ribbon от читателей блога, да и собственный хоть и не большой, но опыт - иногда бывает очень не просто ухватить мышкой тот самый элемент :) Понимаю, что может звучит и немного неправдоподобно, но так и есть. Часто приходится выделывать что-то наподобие тануа с бубном, чтобы сделать запланированной. Вот я и решил, что хватит уже мучится с мышкой, пора бы перейти к более серьезной работе. А именно - работать с Ribbon Controls именно как с объектами Delphi, без всяких тасканий и перетаскиваний - только код.

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

Ну, а мы пока перейдем к нашим Ribbon Controls в Delphi. Сегодня рассмотрим небольшой пример создания панелей и групп Ribbon в real-time.


Как Вы уже знаете, в основе Ribbon лежат три вида компонентов: вкладка, группа и элемент, отвечающий за выполнение какого-либо действия (Кнопки, ComboBox  и т.д.). При этом элементы располагаются в группах, а те, в свою очередь на вкладках и умещается всё это хозяйство на родительском компоненте TRibbon.

Собственно, имея в руках только эту информацию, уже можно определиться с созданием вкладок и групп на Ribbon. Поэтому сразу и приступим к программированию.

Открываем Delphi, создаем новое приложение и укладываем на форму стандартный для Ribbon набор компонентов: ActionManager, ImageList и TRibbon. Создавать все элементы интерфейса будем по клику на кнопке TButton. Вид нашего будущего приложения должен быть примерно таким:

Первое, что нам необходимо - это создать новую вкладку. Вся совокупность вкладок (Tabs) является коллекцией TRibbonTabs, которая имеет следующее описание:

TRibbonTabs = class(TOwnedCollection)
private
  FDesignerAdd: Boolean;
  function GetItem(Index: Integer): TRibbonTabItem;
  procedure SetItem(Index: Integer; const Value: TRibbonTabItem);
  function GetRibbon: TCustomRibbon;
  procedure CreatePageForItem(AItem: TRibbonTabItem);
protected
  procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); override;
public
  constructor Create(AOwner: TPersistent; ItemClass: TCollectionItemClass);
  function Add: TRibbonTabItem;
  function FindGroup(const GroupName: string): TControl;
  function GetPageFromPageCaption(const Caption: string): TCustomRibbonPage;
  function IndexOfCaption(const Caption: string): Integer;
  function TabExists(const Caption: string): Boolean;
  function SelectNext: Boolean;
  function SelectPrior: Boolean;
  property DesignerAdd: Boolean read FDesignerAdd write FDesignerAdd;
  property Ribbon: TCustomRibbon read GetRibbon;
  property Items[Index: Integer]: TRibbonTabItem read GetItem write SetItem; default;
end;

Как можно видеть из приведенного листинга, отдельная вкладка - это объект TRibbonTabItem. Попробуем создать новую вкладку. Создаем событие onClick  у Button1 и пишем :

procedure TForm5.Button1Click(Sender: TObject);
var RibbonTabItem:TRibbonTabItem;
begin
  RibbonTabItem:=TRibbonTabItem.Create(ribbon1.Tabs);
end;

Теперь можете запустить приложение и убедиться, что новая вкладка создается и содержит стандартное название типа "RibbonTab1", "RibbonTab2" и т.д. Но нам-то необходимо нормальное название. Поэтому давайте немного разберемся с объектом TRibbonTabItem.

В числе прочих, TRibbonTabItem имеет следующие свойства:

BestTabWidth: Integer - оптимальная ширина вкладки, т.е. ширина вкладки не может быть больше этого значения. Свойство только для чтения.
MinTabwidth: Integer - минимальная ширина вкладки . Свойство только для чтения
Caption: string - заголовок вкладки.
Page: TCustomRibbonPage - объект, содержащий все необходимые свойства и методы для управления дочерними элементами вкладки (группами).

Таким образом, нам пригодятся сегодня два свойства: Caption и Page. Вначале изменим заголовок новой вкладки, например, воспользовавшись свойством Count у колеекции Ribbon1.Tabs :

[...]
  RibbonTabItem.Caption:='Tab #'+IntToStr(Ribbon1.Tabs.Count);
[...]

В итоге при работе с приложением у Вас должно получиться примерно следующее:

Двигаемся дальше. Следующий шаг - добавление ной группы. Здесь в принципе тоже нет никаких сложностей - каждая группа - это дочерний элемент вкладки. Здесь при работе, нам как раз и пригодиться свойство Page: TCustomRibbonPage.

Объект TCustomRibbonPage содержит следующие полезные для нас публичные свойства и методы:

procedure AlignGroups - автоматическое выравнивание групп на вкладке
procedure AddGroup(const Group: TCustomRibbonGroup) - добавление новой группы на вкладку
function FindGroup(const GroupCaption: string): TControl - поиск группы по её заголовку
function FindGroupAt(const Pt: TPoint): TCustomRibbonGroup - поиск группы по координатам точки.
property GroupCount: Integer - количество групп на вкладке
property Groups[Index: Integer]: TCustomRibbonGroup - отдельная группа вкладки
property Index: Integer - порядковый номер вкладки на Ribbon
property Ribbon: TCustomRibbon - родительский элемент вкладки.

Для того, чтобы добавить новую группу нам необходимо воспользоваться методом AddGroup где в качестве входного параметра выступает добавляемая нами группа. Что ж, приступим. Добавляем новую переменную типа TCustomRibbonGroup в обработчик события и пишем:

[...]
  Group:=TRibbonGroup.Create(RibbonTabItem.page);//группа размещается на вкладке
  RibbonTabItem.Page.AddGroup(Group); //добавляем группу в коллекцию
  Group.Parent:=RibbonTabItem.Page; //указываем родительский элемент для группы
  Group.Caption:='Group #'+IntToStr(RibbonTabItem.Page.GroupCount);//указываем заголовок
[...]

Теперь при каждом клике по кнопке в real-time создается новая вкладка и на каждой вкладке одна группа.  Следует отметить, что каждая новая группа по умолчанию имеет следующие свойства:

Width := 200;
  Height := TCustomRibbon.cRibbonGroupHeight;//86 px
  Align := alNone;
  GroupAlign := gaVertical;
  Rows := 3; //количество строк

В принципе, вы всегда можете изменить некоторые из этих свойств как Вам угодно.

Теперь остался один открытый вопрос: зачем нам на форме два лишних компонента - ActionManager и ImageList?

Ответ на этот вопрос, Вы узнаете в следующем посте. Будем работать непосредственно с отдельными группами, элементами и  действиями. А пока можете сохранить приложение, т.к. оно нам ещё пригодиться, подписаться на RSS и ждать новых публикаций в блоге webdelphi.ru :)

----------------------
Не мыслите себя вне Глобальной Паутины? Тогда Вас должны заинтересовать стихи про интернет. Новое слово в поэзии :)

Если Вы часто заказываете выполнение каких-либо работ через интернет, то фриланс для заказчиков - это то, что вам нужно. Много полезной информации именно для Вас.
----------------------
Понравилась статья? Тогда:
Делись! Загружай! Плюсуй!
   Отправить PDF на   
Читай ещё статьи на WebDelphi.ru

Комментарии (12)

WP_Cloudy
  • Жека пишет:

    Не подскажите как сделать так что б по нажатию на кнопку открывалась нужная вкладка (например на Вкладке1 существует кнопку(Action1), после её нажатия должна открыться Вкладка2… как это сделать?)

  • Vlad пишет:

    Так это вам в ActionManager надо сделать новое событие по которому и будете перебирать вкладки

  • Жека пишет:

    так вот в этом и вопрос… как правильно написать что б работало.. а то всё никак не получается (((

  • Vlad пишет:

    Пртведи кусок кода где пробуешь переключить вкладку

  • Жека пишет:

    Ribbon1.ActivePage.Index:=2
    или
    Ribbon1.ActivePage := — этот вариант Делфи не принимает
    или
    RibbonPage2.Show; и все без результата

  • Vlad пишет:

    Переключение по вкладкам Ribbon’а осуществляется, например так:
    Ribbon1.Tabs.SelectNext; — переход на следующую вкладку
    Ribbon1.Tabs.SelectPrior; — переход на предыдущую вкладку

  • Жека пишет:

    Спасибо за информацию… но я так понял на конкретную страницу перейти нельзя…. либо прописывать одну и туже команду несколько раз…

  • Vlad пишет:

    Жека, я привел только пример перехода по закладкам. Думаю, что всё-таки есть способ перехода, хотя бы в том же TRibbon.Tag[x].

  • bambarmia пишет:

    Спасибо, Vlad, статья, как всегда, на высоте. Отлично дополняет пример http://www.webdelphi.ru/2009/10/ribbon-controls-shag-za-shagom-shag-1-vizualnaya-razrabotka-interfejsa/#comment-1780 ! // Только не сочтите за занудство, но, коли планируете издать «справочник», перефразируйте «Часто приходится выделывать что-то наподобие тануа с бубном, чтобы сделать запланированной.»
    С уважением, благодарный читатель)))

  • Vlad пишет:

    Естественно, если будет справочник таких фраз там не будет :)

  • ppush пишет:

    Спасибо, Vlad, статья отличная.
    Но у меня возникла тпкая проблема ,
    При создании вкладок в цикле например что-то такое


    Ribbon1.BeginUpdate;
    for j := 0 to 20 do
    begin
    I_Loop := Length(RibonPages);
    SetLength(RibonPages, I_Loop + 1);
    RibonPages[I_Loop] := TRibbonPage.Create(Self);
    RibonPages[I_Loop].Name := 'RP_SYSDBA'+IntToStr(j);
    RibonPages[I_Loop].Parent := Ribbon1;

    RibonPages[I_Loop].Caption :=GetString('SYSDBA');
    Ribbon1.AddTab(RibonPages[I_Loop]);
    end;

    Ribbon1.EndUpdate;

    перерисовка  Ribbon-а при каждой интерации создает довольнотаки неприятное впечатление
    и кажется Ribbon1.BeginUpdate не работает.

    Если сталкивались с подобным пожалусто напишите как с этом справиться.

  • Drump пишет:

    Недавно столкнулся с такой проблемой: при разработке необходимо создавать вкладку(и группы в ней) динамически. Но при создании RibbonGroup цвет Caption не черный, а какой-то розоватый. На другом компьютере — голубой. Но самое интересное то, что вторая вкладка создается с нормальным цветом! Не подскажите в чем дело? И как сделать чтобы цвет был «нормальным». 

Ваш ответ

Внимание: Все комментарии модерируются, и это может вызвать задержку их публикации. Отправлять комментарий заново не требуется.

Пожалуйста, заключайте исходный код в тэги [code][/code].
Если код большой, то воспользуйтесь Вставкой кода на отдельной странице и оставьте в комментарии ссылку на исходник