Работа с панелями инструментов и меню в VBA, объекты CommandBar, CommandBarControl, CommandBarPopup, контекстные меню
Очень часто в приложении VBA вам потребуются свои наборы меню и панелей инструментов вместо стандартных, предусмотренных приложением. Работу с меню и панелями инструментов обеспечивает коллекция CommandBars, которая находится в объекте Application (об этом важном объекте мы будем говорить в следующих модулях). Коллекция CommandBars содержит, как ясно из названия, набор объектов CommandBar(панели инструментов и меню), каждый из них, в свою очередь — коллекцию CommandBarControls (набор элементов из которых состоит панель/меню), а эта коллекция представляет из себя хранилище элементов, из которых и состоит меню. Таких элементов может быть три:
Пример создания собственной панели инструментов может выглядеть очень просто:
Dim CBar1 As CommandBar
Set CBar1 = CommandBars.Add("Документы", msoBarTop)
CBar1.Enabled = True
CBar1.Visible = True
У нас появилась новая панель инструментов Документы (см. рис. 8.1), которое можно, к примеру, убрать через меню Настройка -> Панели инструментов, однако пока она совершенно бесполезна: в нем нет ни одной кнопки. Для того, чтобы они появились, необходимо добавить новый элемент типа CommandBarControl (одного из трех типов, перечисленных выше) в коллекцию CommandBarControls для этого меню.
Рис. 8.1 В центре рисунка — пустая панель инструментов Документы
Но вначале — про некоторые важные свойства и методы объекта CommandBar:
Set CBar1 = CommandBars.Add("Документы", msoBarTop, True, False)
Первый параметр ( "Документы") — это, конечно, имя объекта (название панели). Второй параметр ( msoBarTop) — либо положение пристыкованной панели ( msoBarTop, msoBarBottom, msoBarLeft, msoBarRight), либо знак того, что панель непристыкована ( msoBarFloating), либо вообще указание на то, что это — контекстное меню, которое до щелчка правой кнопкой мыши не видна ( msoBarPopup). Свойство Visible для контекстного меню неприменимо.
Как будет выглядеть в итоге панель — как меню или панель инструментов, зависит от того, какие элементы вы туда поместите.
После того, как создание панели завершено, необходимо разместить в нем элементы. Например, создание панели инструментов может выглядеть так:
Dim But1 As CommandBarControl
Set But1 = CBar1.Controls.Add(msoControlButton)
But1.Caption = "Кнопка 1"
Вроде бы ничего не произошло — перед нами та же пустая панель. Однако, если навести указатель мыши на начало панели, в нем можно увидеть пустую кнопку, которая называется "Кнопка 1" (см. рис. 8.2).
Рис. 8.2 На панели инструментов Документы появлилась почти невидимая Кнопка 1
Как видно из кода, мы использовали для создания элемента управления (кнопки в панели инструментов) метод Add() коллекции Controls объекта CommandBar (у нас он называется CBar1). Свойства и методы у этой коллекции стандартные, как у множества других коллекций:
Чуть подробнее о методе Add(). Этот метод принимает пять необязательных параметров из которых два первых параметра — очень важны. Первый параметр — Type, он определяет тип передаваемого в коллекцию элемента управления. Таких типов — пять: msoControlButton (кнопка — то есть в итоге получится панель инструментов), msoControlEdit (будет создано поле для ввода текста), msoControlDropdown (ниспадающий список), msoControlComboBox (комбинированный список), or msoControlPopup (пункт меню), например, чтобы наша кнопка превратилась в начальный пункт ниспадающего меню (см. рис. 8.3), в нашем коде можно изменить один этот параметр:
Dim But1 As CommandBarControl
Set But1 = CBar1.Controls.Add(msoControlPopup)
But1.Caption = "Меню 1"
Рис. 8.3 На созданной нами панели инструментов появился пункт меню
Второй важный параметр метода Add() — параметр ID. Этот параметр позволяет привязать элемент управления к уже имеющемуся в системе встроенному элементу управления. Например, чтобы добавить кнопку печати, этот параметр должен быть равен 4, а чтобы добавить кнопку предпросмотра документа, этот параметр должен быть равен 5. Если оставить этот параметр пустым, или указать для него значение 1, то будет создан пользовательский элемент управления, не привязанный ни к каким встроенным.
Остальные параметры этого метода относятся к созданию идентификатора элемента управления, его положению относительно других элементов управления и должен ли он быть постоянным или временным.
Конечно, работа с панелью управления/меню на этом не завершена. Нам потребуется еще донастроить свойства элементов управления. Например, для кнопки из первого примера нам, как минимум, нужно еще определить изображение, которое будет на кнопке, и процедуру, которая при нажатии на нее будет называться. Для объекта CommandBarButton важнейшие свойства, методы и события приводятся ниже:
У этого объекта есть единственное событие — Click. Оно также позволяет определить реакцию на нажатие кнопки, но работать с ним сложнее, чем со свойством OnAction.
В принципе, для работы с панелями инструментов этого вполне достаточно. Однако меню — ниспадающие и контекстные — устроены несколько сложнее. В ниспадающем меню вам потребуется еще определить вложения элементов, а в контекстном меню — еще и привязать это меню к какому-то объекту.
Для работы с вложенными меню используется точно та же коллекция Controls, которой мы уже пользовались. Единственное отличие — эта коллекция Controls принадлежит не объекту CommandBar, а объекту CommandBarPopup — то есть другому меню! В нашем примере вложение будет выглядеть так:
'Создаем стандартный объект CommandBar
Dim CBar1 As CommandBar
Set CBar1 = CommandBars.Add("Документы", msoBarTop)
CBar1.Enabled = True
CBar1.Visible = True
Dim Menu1 As CommandBarPopup
Dim SubMenu1 As CommandBarPopup
Dim SubMenu1Item As CommandBarButton
Set Menu1 = CBar1.Controls.Add(msoControlPopup) ' Создаем верхнее меню
Menu1.Caption = " Меню 1"
Set SubMenu1 = Menu1.Controls.Add(msoControlPopup) ' Создаем вложенное меню
SubMenu1.Caption = "Подменю 1"
'Создаем элемент во вложенном подменю и назначаем ему процедуру Proc1
Set SubMenu1Item = SubMenu1.Controls.Add(msoControlButton)
SubMenu1Item.FaceId = 5
SubMenu1Item.Caption = "Элемент подменю"
SubMenu1Item.OnAction = "Proc1"
То, что получилось, можно посмотреть на рис. 8.4.
Рис. 8.4 Наше меню приобретает законченные очертания
Конечно, можно добавлять элементы не только в свои меню, но и во встроенные. Добавление происходит точно так же, а найти нужное встроенное меню можно при помощи цикла For Each и проверки значения свойства Name.
Контекстные меню (в справке VBA — shortcut menus) — это меню, которые открываются по щелчку правой кнопкой мыши. С ними работа выглядит так:
Set CBar1 = CommandBars.Add ("Мое контекстное меню", msoBarPopup , , True )
Set MenuItem1 = CBar1.Controls.Add
MenuItem1.FaceId = 3
MenuItem1.Caption = "Элемент меню 1"
Set MenuItem2 = CBar1.Controls.Add
MenuItem2.FaceId = 5
MenuItem2.Caption = "Элемент меню 2"
Как мы видим, все очень просто и стандартно. Однако если просто выполним этот код, то никакого контекстного меню не появится: необходимо еще добавить вызов метода ShowPopup():
CBar1.ShowPopup
Тогда контекстное меню возникнет в том месте, где сейчас находится указатель мыши (можно передать этому методу координаты места появления).
Конечно, этот метод нужно положить в обработчик события, связанного с правой кнопкой мыши, а его как раз и нет для многих объектов. Например, в Excel для листа есть событие BeforeRightClick, а для документа Word такого события нет. Но и в этом случае у нас останется возможность добавить свои пункты в стандартное контекстное меню.