уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Вот почему мне нравится вести блог, так это за то, всегда находятся люди, которые не только берут что-то для себя ,  например ту же информацию по Ribbon Controls, но и безвозмездно делятся своими соображениями, идеями,  советуют как сделать лучше и т.д. Получая такие письма от читателей как-то даже интереснее становится про что-то писать. Даже, если не собирался этого делаь, например, как я сейчас буду рассказывать снова про Ribbon. Не хотел начинать новый пост, думал, наконец-то дособираю в кучу всё что знаю и выложу в pdf. Но, один читатель в своем письме привел ряд моментов о которых я в принцпе и не подозревал, а также задал один небольшой, но довольно интересный вопрос:

Как разместить в группу кнопку с рисунком в виде квадрата с заданным цветом и как менять этот цвет? (как в MS Paint в Win7)

Ну, чтож, Павел — этот пост, можно сказать, посвещается Вам :). Заодно и другим может сообща поможем разобраться с этим вопросом.
Итак,начнем.

Прежде всего определимся с задачей. Все видели Paint в Windows 7? Кто не видел — вот скрин той самой части ленты, про которую сегодня пойдет речь:

Суть такова: когда пользователь кликает по маленькому квадратику с цветом, то, в зависимости от того, какая кнопка нажата «Цвет 1» или «Цвет 2» та и принимает цвет нажатого квадрата.
Получается эдакая иллюзия «живости» интерфейса от которой неискушенный пользователь скажет «Вах!». А нам, как разработчиком восхищаться особенно не чем — нам такой механизм взаимодействия надо соорудить из подручных средств в Delphi 2010.
Начнем, как полагается в случае с Ribbon Controls — с мышевозного программирования.

Работаем мышкой.

Для этого запускаем Delphi 2010, создаем новый проект, и на главную форму укладываем следующие компоненты:

  1. TRibbon (1 штука)
  2. TActionManager (1 штука)
  3. TActionList (1 штука)
  4. TImageList (2 штуки)

Теперь  оговорюсь. По натуре я ленив до ужаса, поэтому мне было влом рисовать квадратики с различными цветами и тем более лень было ковыряться в Paint’e в посках изображений его кнопок. По этому я буду работать с иконками, обозначающими типы файлов (чем богаты — тем и рады, что было — то и спёр).

У Вас уже сейчас должно быть подготовлено 2 набора картинок:

  1. Картинки 16х16
  2. Точно такие же картинки, но только размером 32х32.

Теперь у первого ImageList (назовем его il1) выставляем свойства:

  1. ColorDepth = cd32Bit
  2. Height = 32
  3. Width =32

Грузим в него картинки 32х32. У второго ImageList (il2) выставляем свойства:

  1. ColorDepth = cd32Bit
  2. Height = 16
  3. Width =16

Грузим в него картинки в том же порядке, что и в первом ImageList. Если порядок будет нарушен — получим лишнюю головную боль с определением индекса картинки — мелочь, но неприятная.

Теперь открываем свойства ActionList и в свойсве Images указываем il2. Соответственно у ActionManager в Images указываем il1.

Также у ActionManager‘а в свойства LinkedActionLists добавляем наш ActionList.

Следующий шаг — настройка Action’ов. Вначале настраиваем действия в ActionList. Для этого открываем его, добавляем действие и сразу определяем новую группу для Action. У меня — это группа «Файлы». В зависимости от того скалько картинок у вас в il1 и il2 (должно быть в обоих одно и то же количесво) добавляем столько же Action’ов и назначаем каждому свое изображение. В итоге у меня получился следующий набор действий:

Теперь переходим в AсtionManager и добавляем в него два действие, назначив им изображение из il1. Должна получиться примерно такая картинка:

Теперь остается только аккуратно разложить все Action’ы на панельках и первый этап можно считать законченным. У меня получилась лента следующего вида (в запущенном приложении):
Так как мы ещё не назначили ни одного обработчика Action’ам, то, соответственно, в запущенном приложении все элменты неактивны. Также я специально не стал менять свойство Caption у элементов на ленте и Вам менять их пока не советую — проще будет понять, что мы сейчас начнем делать.

Ищем способы смены изображения элемента «на лету»

Прежде всего нам надо определиться с тем как можно сменить изображение на любом элементе управления на ленте Ribbon. Логично предположить, что надо как-то докапаться до конкретного Action’а и поменять у него свойство ImageIndex. Ведь именно так мы и действовали при работе в ActionList? Но на самом деле всё немного проще. Смотрите. У ActionManager’а есть два замечательных метода:

function FindItemByCaption(ACaption: string): TActionClientItem;
function FindItemByAction(Action: TCustomAction): TActionClientItem;

Как уже понятно, с помощью них мы можем получить доступ к TActionClientItem у которого, в свою очередь имеется свойство ImageIndex — его-то мы и будем изменять. Остается тольео определиться с тем, какой из методов мы будем использовать. Я буду в качестве примера искать элемент по Caption. И выбор мой не случаен. Посмотрите на рисунок выше и попробуйте, не заглядывая в свои исходники, ответить на вопрос «Какой Caption у первого слева TActionClientItem’a?» :). Будет не верно, если Вы решили, что это actMainAction1. На самом деле для TActionClientItem свойство Caption будет равно &actMainAction1. По умолчанию свойство Caption берется таким же как и у Action, который назначается Вами для элемента, НО обязательно где-то вставляется амперсанд. Говорю «где-то», потому что встречал его и в начале и в середине и в конце строки. Вот такая небольшая особенность поиска по Caption.

Можете теперь немного потренироваться в поисках элементов на ленте по их заголовкам. А я тем временем приведу пример как можно сменить изображение на элементе:

ActionManager1.FindItemByCaption('&actMainAction1').ImageIndex:=2

или так

(ActionManager1.FindItemByCaption('&actMainAction1').Action as TAction).ImageIndex:=2

Вот так запросто мы сменили изображение на первой слева кнопке. Думаю, что на этом способе и остановимся.

Организуем «живой» интерфейс Ribbon

Остается только поработать немного со свойствами элементов на ленте и составить обработчики действий. Вначале настраиваем большие кнопки. Выделяем первую кнопку на ленте, в Object Inspector’е выбираем вкладку свойств Aсtion и вытсавояем свойства:

GroupIndex = 1

AutoCheck = true

Точно такие же свойства выставляем и у второй кнопки. Теперь определим для них действия.  У меня по клику на люой из кнопок в ListBox додавлятся строка, содержащая тип файла. Обработчик получился немного корявнький, но работоспособный:

procedure TForm5.BigButtonAction(Sender: TObject);
begin
  case (Sender as TAction).ImageIndex of
    0:lst1.Items.Add('AI');
    1:lst1.Items.Add('ACC');
    2:lst1.Items.Add('ACE');
    3:lst1.Items.Add('AIFF');
    4:lst1.Items.Add('ASP');
    5:lst1.Items.Add('AVI');
  end;
end;

Второй обработчик будем использовать для всех мелких кнопок. Здесь нам надо будет определить какая из больших кнопок нажата в данный момент и назначить ей «свою» картинку:

procedure TForm5.SmallButtonAction(Sender: TObject);
begin
 if (actmgr1.FindItemByCaption('&actMainAction1').Action as TAction).Checked then
   (actmgr1.FindItemByCaption('&actMainAction1').Action as TAction).ImageIndex:=
   (Sender as TAction).ImageIndex
 else
   (actmgr1.FindItemByCaption('a&ctMainAction2').Action as TAction).ImageIndex:=
   (Sender as TAction).ImageIndex
end;

Теперь назначаем этот обработчик каждой маленькой кнопке (событие OnExcute) и остается только «причесать» наше приложение, а точнее, убрать все подписи для маленьких кнопок. И здесь банальным стиранием свойства Caption не обойтись — надо обязательно выставить у каждого ActionClientItem’a свойство ShowCaption в False:

Теперь можно запустить приложение и убедиться в его работоспособности — в зависимости от того какая большая кнопка нажата у той и меняется иконка при нажатии маленькой кнопки, а также по своему выполнеятся Action. Практически также и работает Paint — какой цвет выбрали — тем и ресуем.

На всякий случай выкладываю здесь исхдник моего приложение. Вот он.

На всякий случай, ещё раз обращаю внимание тех, кто хочет все сделать с Ribbon Controls «по-быстрому», не вникая в суть работы с лентами и всячески избегая чтения MSDN: не используйте без надобности на ленте стандартные компоненты. Я имею в виду кнопки, speedButton’ы, CheckBox’ы, ComboBox’ы и т.д. Все эти компоненты можно получить простым изменением свойств у TActionClientItem. Чрезмерное использование стандартных кнопок может изуродовать ваше приложение до безобразия. Стандартную VCL стоит использовать только тогда, когда Вам не хватает доступных возможностей и делать это надо крайне аккуратно и требуется это очень редко.

0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
5 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
Павел
Павел
19/07/2010 21:38

Спасибо, Влад, за помощь. Очень помогло. Правда, вместо ActionList мне пришлось использовать ActionManager, т.к. у меня их на форме до этого было уже 3 штуки, при запуске он брал иконки из ImagesList того ActionManager, который указан в Ribbon. Добавление в linkedActionLists всех менеджеров и листа, а также танцы с бубном не помогали, поэтому я решил всё же использовать один общий ActionManager для кнопок. Не успел дочитать, как сразу рвался проверять, поэтому свойство ShowCaption нашёл сам :). Вот только кнопочки получились мельче, чем в Paint. Пробовал увеличивать до 20 пикселей, но они «слезают» со своих мест, а также изменять свойство Margins… Подробнее »

Павел
Павел
19/07/2010 21:48

Кстати, помощь в написании PDF не нужна? Мне и самому интересно не только что, там будет, но и как там будет :).

Павел
Павел
20/07/2010 16:00

>По поводу pdf-ки. Могу скинуть на почту начало того, что сделал.
Да не, я потом всё почитаю. Но если в чём нужна будет помощь (проги, вёрстка, мнение со стороны, или даже (чем бог не шут) совет) — обращайся.