Основы офисного программирования и документы Word

         

Добавление и удаление панелей и других элементов


Начнем с процедуры, позволяющей в любом из приложений Office 2000 добавить в коллекцию CommandBarsсобственную инструментальную панель с заданным именем. Напомним, что хотя эта задача и решается одним оператором, поскольку у коллекции есть специальный метод Add, но корректная реализация требует предварительной проверки существования в коллекции панелей элемента с таким именем. Вот процедура, решающая эту задачу и использующая ранее написанную функцию Exist:

Public Sub AddPanel(PanelName As String) 'Добавляет и делает видимой панель с именем Panelname 'в коллекцию Commandbars 'Панель расположена вверху документа, 'не заменяет главное меню и не является временной If Not ExistCommandBar(PanelName) Then Call CommandBars.Add(name:=PanelName, Position:=msoBarTop, _ MenuBar:=False, Temporary:=False) End If CommandBars(PanelName).Enabled = True CommandBars(PanelName).Visible = True

End Sub

Листинг 3.4.

(html, txt)

Говоря о коллекции CommandBars и добавлении пользовательских панелей в эту коллекцию, следует иметь в виду одно обстоятельство. В разных приложениях Office 2000 есть свои нюансы использования этих коллекций. В приложении Word можно рассматривать коллекцию панелей, связанную с конкретным документом, и общую коллекцию, связанную с проектом Normal. Поэтому при работе в приложении Word, при рассмотрении коллекции панелей, связанной с документом, следует пользоваться уточненным именем ActiveDocument.CommandBars. В противном случае речь будет идти об общей коллекции, связанной с проектом Normal. При работе в Excel все пользовательские панели будут автоматически добавляться в коллекцию, связанную с документом и не будут появляться при открытии других документов Excel. В приложении Outlook программный проект, частью которого является коллекция, существует в единственном экземпляре, аналогично проекту Normal. Поэтому добавляемые панели будут распространяться на все документы Outlook.

Говоря о приложении Word и добавлении пользовательских панелей, хочу рассказать еще об одном небольшом "жучке" и как с ним бороться.

В приложении Word невозможно программно добавить панель, связанную с документом. Добавляемая программно панель будет всегда связана с проектом Normal и, следовательно, будет доступна для всех документов Word, что не всегда является желательным. Как уже отмечалось, свойство Context, которое должно обеспечивать связывание панели с документом, корректно не работает. Поэтому, если добавляемую панель необходимо связать только с конкретным документом, то работу по добавлению панели необходимо проделать вручную.


Начнем с процедуры, позволяющей в любом из приложений Office 2000 добавить в коллекцию CommandBarsсобственную инструментальную панель с заданным именем. Напомним, что хотя эта задача и решается одним оператором, поскольку у коллекции есть специальный метод Add, но корректная реализация требует предварительной проверки существования в коллекции панелей элемента с таким именем. Вот процедура, решающая эту задачу и использующая ранее написанную функцию Exist:

Public Sub AddPanel(PanelName As String) 'Добавляет и делает видимой панель с именем Panelname 'в коллекцию Commandbars 'Панель расположена вверху документа, 'не заменяет главное меню и не является временной If Not ExistCommandBar(PanelName) Then Call CommandBars.Add(name:=PanelName, Position:=msoBarTop, _ MenuBar:=False, Temporary:=False) End If CommandBars(PanelName).Enabled = True CommandBars(PanelName).Visible = True

End Sub

Листинг 3.4.

Говоря о коллекции CommandBars и добавлении пользовательских панелей в эту коллекцию, следует иметь в виду одно обстоятельство. В разных приложениях Office 2000 есть свои нюансы использования этих коллекций. В приложении Word можно рассматривать коллекцию панелей, связанную с конкретным документом, и общую коллекцию, связанную с проектом Normal. Поэтому при работе в приложении Word, при рассмотрении коллекции панелей, связанной с документом, следует пользоваться уточненным именем ActiveDocument.CommandBars. В противном случае речь будет идти об общей коллекции, связанной с проектом Normal. При работе в Excel все пользовательские панели будут автоматически добавляться в коллекцию, связанную с документом и не будут появляться при открытии других документов Excel. В приложении Outlook программный проект, частью которого является коллекция, существует в единственном экземпляре, аналогично проекту Normal. Поэтому добавляемые панели будут распространяться на все документы Outlook.

Говоря о приложении Word и добавлении пользовательских панелей, хочу рассказать еще об одном небольшом "жучке" и как с ним бороться.

В приложении Word невозможно программно добавить панель, связанную с документом. Добавляемая программно панель будет всегда связана с проектом Normal и, следовательно, будет доступна для всех документов Word, что не всегда является желательным. Как уже отмечалось, свойство Context, которое должно обеспечивать связывание панели с документом, корректно не работает. Поэтому, если добавляемую панель необходимо связать только с конкретным документом, то работу по добавлению панели необходимо проделать вручную.




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

Public Sub AddMainPanel(MainPanel As String) 'Выключаем все панели документа Dim bar As CommandBar For Each bar In CommandBars bar.Enabled = False Next bar 'Добавляем и включаем новую панель главного меню If Not ExistCommandBar(MainPanel) Then Call CommandBars.Add(name:=MainPanel, Position:=msoBarTop, _ MenuBar:=True, Temporary:=False) End If CommandBars(MainPanel).Enabled = True CommandBars(MainPanel).Visible = True

End Sub

Листинг 3.5.

(html, txt)

Поскольку панели добавляются, то их нужно уметь и удалять, - операция Add должна иметь и обратную операцию Remove (Delete). Удаление возможно только для пользовательских панелей и невозможно, естественно, для встроенных панелей. Выполняется удаление достаточно просто, но и здесь желательны предварительные проверки:



Листинг 3.6.

(html, txt)

Приведем еще одну обратную операцию. Поскольку в процедуре AddMainPanel все панели документа были отключены (это очень опасная операция), то необходимо иметь процедуру, восстанавливающую отключенные панели:

Public Sub ResetMainMenu() Dim CstmBar As CommandBar 'Включаем все панели For Each CstmBar In CommandBars CstmBar.Enabled = True Next CstmBar

Set CstmBar = CommandBars.Item("Menu Bar") CstmBar.Visible = True End Sub

Листинг 3.7.

(html, txt)

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

Public Sub AddBuiltinMenu(Panel As String, MenuName As String, _ Num As Variant, item As CommandBarPopup) 'Добавляет встроенный пункт меню с именем MenuName 'на панель Panel Dim bar As CommandBar, ider As Variant Dim Ctrl As CommandBarControl Set bar = CommandBars(Panel) If Not ExistControl(bar, MenuName) Then Set Ctrl = MyFindControl(MenuName) 'Если найден If Not (Ctrl Is Nothing) Then ider = Ctrl.ID bar.Controls.Add Type:=msoControlPopup, _ ID:=ider, Before:=Num Else: Exit Sub End If End If Set item = bar.Controls(MenuName) End Sub



Листинг 3.8.

(html, txt)

В процедуре AddBuiltinMenu встроенный пункт меню с именем MenuName вначале разыскивается в коллекции панелей, а затем добавляется на указанную панель Panel. Параметр Num указывает местоположение добавляемого элемента, а параметр item является результатом, возвращая добавленный пункт меню, как объект класса CommandBarPopup. В следующей процедуре в меню добавляется встроенная команда:

Public Sub AddItem(item As CommandBarPopup, name As String) Dim Ctrl As CommandBarControl If Not ExistItem(item, name) Then 'Найти встроенный элемент в коллекции встроенных панелей Set Ctrl = MyFindControl(name) 'Если найден If Not (Ctrl Is Nothing) Then item.Controls.Add Type:=msoControlButton, ID:=Ctrl.ID End If End If End Sub

Листинг 3.9.

(html, txt)

Приведем еще парочку процедур добавления:

Листинг 3.10.

(html, txt)

on_load_lecture()

Дальше »

  Если Вы заметили ошибку - сообщите нам.  
Страницы:

« |

1

|

2

|

3

|

4

|

вопросы | »

|

для печати и PDA

Курсы | Учебные программы | Учебники | Новости | Форум | Помощь


Телефон: +7 (495) 253-9312, 253-9313, факс: +7 (495) 253-9310, email: info@intuit.ru

© 2003-2007, INTUIT.ru::Интернет-Университет Информационных Технологий - дистанционное образование



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

Public Sub AddMainPanel(MainPanel As String) 'Выключаем все панели документа Dim bar As CommandBar For Each bar In CommandBars bar.Enabled = False Next bar 'Добавляем и включаем новую панель главного меню If Not ExistCommandBar(MainPanel) Then Call CommandBars.Add(name:=MainPanel, Position:=msoBarTop, _ MenuBar:=True, Temporary:=False) End If CommandBars(MainPanel).Enabled = True CommandBars(MainPanel).Visible = True

End Sub

Листинг 3.5.

Поскольку панели добавляются, то их нужно уметь и удалять, - операция Add должна иметь и обратную операцию Remove (Delete). Удаление возможно только для пользовательских панелей и невозможно, естественно, для встроенных панелей. Выполняется удаление достаточно просто, но и здесь желательны предварительные проверки:

Public Sub DelPanel(PanelName As String) 'Удаляет пользовательскую панель 'из коллекции CommandBars If ExistCommandBar(PanelName) _ And Not CommandBars(PanelName).BuiltIn Then CommandBars(PanelName).Delete End If End Sub

Листинг 3.6.

Приведем еще одну обратную операцию. Поскольку в процедуре AddMainPanel все панели документа были отключены (это очень опасная операция), то необходимо иметь процедуру, восстанавливающую отключенные панели:

Public Sub ResetMainMenu() Dim CstmBar As CommandBar 'Включаем все панели For Each CstmBar In CommandBars CstmBar.Enabled = True Next CstmBar

Set CstmBar = CommandBars.Item("Menu Bar") CstmBar.Visible = True End Sub

Листинг 3.7.

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



Public Sub AddBuiltinMenu( Panel As String, MenuName As String, _ Num As Variant, item As CommandBarPopup) 'Добавляет встроенный пункт меню с именем MenuName 'на панель Panel Dim bar As CommandBar, ider As Variant Dim Ctrl As CommandBarControl Set bar = CommandBars(Panel) If Not ExistControl(bar, MenuName) Then Set Ctrl = MyFindControl(MenuName) 'Если найден If Not (Ctrl Is Nothing) Then ider = Ctrl.ID bar.Controls.Add Type:=msoControlPopup, _ ID:=ider, Before:=Num Else: Exit Sub End If End If Set item = bar.Controls(MenuName) End Sub

Листинг 3.8.

В процедуре AddBuiltinMenu встроенный пункт меню с именем MenuName вначале разыскивается в коллекции панелей, а затем добавляется на указанную панель Panel. Параметр Num указывает местоположение добавляемого элемента, а параметр item является результатом, возвращая добавленный пункт меню, как объект класса CommandBarPopup. В следующей процедуре в меню добавляется встроенная команда:

Public Sub AddItem(item As CommandBarPopup, name As String) Dim Ctrl As CommandBarControl If Not ExistItem(item, name) Then 'Найти встроенный элемент в коллекции встроенных панелей Set Ctrl = MyFindControl(name) 'Если найден If Not (Ctrl Is Nothing) Then item.Controls.Add Type:=msoControlButton, ID:=Ctrl.ID End If End If End Sub

Листинг 3.9.

Приведем еще парочку процедур добавления:

Public Sub AddCustomItem(item As CommandBarPopup, _ name As String, Act As String) 'Добавляет команду меню 'Параметр Act задает имя макроса, реализующего команду Dim Ctrl As CommandBarControl If Not ExistItem(item, name) Then Set Ctrl = item.Controls.Add(Type:=msoControlButton) Ctrl.Caption = name Ctrl.OnAction = Act End If End Sub Public Function AddCustomPopup(item As CommandBarPopup, _ name As String) As CommandBarPopup 'Добавляет подменю в меню, 'возвращая объект подменю в качестве результата Dim Ctrl As CommandBarPopup If Not ExistItem(item, name) Then Set Ctrl = item.Controls.Add(Type:=msoControlPopup) Ctrl.Caption = name End If Set AddCustomPopup = item.Controls(name) End Function

Листинг 3.10.


Exist-функции


К сожалению, у объектов CommandBars, CommandBar, CommandBarPopUp отсутствует весьма полезное свойство, проверяющее существование элемента в коллекции, на панели или меню. Оно необходимо при добавлении элемента, поскольку прежде чем добавить элемент, следует проверить, не существует ли он уже в коллекции. Эта проверка необходима еще и потому, что добавление выполняется вне зависимости от присутствия добавляемого элемента в коллекции (панели, меню) и тем самым порождает копии элементов, что, конечно же, нежелательно. Я написал три функции, реализующие свойство Exist у рассматриваемых объектов:

Листинг 3.1.

(html, txt)

Первая из них проверяет существование панели с заданным именем в коллекции панелей. Обратите внимание, имя можно задавать и по-русски, поскольку проверяются оба свойства Name и NameLocal. Вторая функция проверяет на заданной панели существование элемента с указанным заголовком. Третья функция выполняет аналогичную операцию для меню - объекта CommandBarPopUp.



Коллекция CommandBarControls и ее элементы


В эту коллекцию входят элементы, располагаемые на одной инструментальной панели. Коллекция обладает только традиционными свойствами и методами. Единственное, что следует рассмотреть - это метод Add и его параметры:

Function Add([Type], [Id], [Parameter], [Before], [Temporary]) As CommandBarControl

Метод позволяет добавлять новые элементы в коллекцию. Его параметры:

Type устанавливает тип элемента и класс этого элемента, возвращаемый функцией Add. Если значением Type является константа msoControlButton, то возвращается объект класса CommandBarButton, для значений: msoControlEdit, msoControlDropdown, msoControlComboBox - возвращается объект класса CommandBarComboBox и, наконец, если тип имеет значение msoControlPopup, то возвращаемый класс объекта - CommandBarPopupId задает идентификатор встроенного элемента, добавляемого в коллекцию. Если он опущен, то на панели появится пользовательский, пустой элемент, свойства которого позднее следует определить.Parameter для встроенных элементов используется приложением при запуске команды, для пользовательских элементов может хранить некоторую информацию об элементе. Before задает местоположение элемента на панели, если он опущен, элемент добавляется в конец панели. Temporary является булевым параметром. Его значение True говорит о том, что элемент является временным и будет удален с панели при закрытии приложения. По умолчанию элементы являются постоянными.

Хотя все создаваемые элементы панели относятся к одному из трех различных классов, все они принадлежат также объединяющему классу CommandBarControl. Мы не будем подробно останавливаться на всех свойствах и методах, как отдельных классов, так и объединяющего элементы класса. Рассмотрим только, как решить главную для команд задачу - выполнить некоторую процедуру в ответ на выбор команды меню или щелчок кнопки. Действия, выполняемые командой, должны быть запрограммированы в виде макроса на языке VBA. Напомним, что макрос - это процедура без параметров. Однако есть некоторый способ передачи информации в исполняемый макрос. Для этого можно использовать параметр Parameter, задаваемый при создании элемента или, что удобнее, свойство Parameter. Конечно, для всех встроенных элементов макрос, задающий команду, уже написан. Но для собственных элементов его нужно написать самому, а затем макрос связать с элементом. Свойство OnAction, которым обладают все элементы панели, позволяет связать элемент с исполняемым макросом. Формально свойство является строкой, задающей имя макроса, который и будет вызываться в ответ на выбор пользователя.

Давайте перейдем теперь к рассмотрению задач, возникающих при создании интерфейса. Я начну c рассмотрения процедур, реализующих некоторые дополнительные свойства изучаемых нами объектов.



Поиск элементов


Казалось бы, что с поиском элементов проблем нет, поскольку объекты CommandBars и Commandbar имеют метод FindControl, а в Office 2000 появился и новый метод FindControls. Эти методы, к сожалению, не всегда применимы, поскольку имеют весьма существенный недостаток. Ключом поиска является значение ID или Tag, но в момент поиска значения этих свойств, как правило, не известно. Чаще всего, известен лишь заголовок разыскиваемого элемента, не включенный в число параметров стандартных методов поиска. Поэтому я предпочел написать собственную процедуру поиска. Приведу эту процедуру и заодно расскажу об одной не очень приятной особенности коллекции панелей CommandBars:

Листинг 3.2.

(html, txt)

Эта функция похожа на функцию FindControl коллекции CommandBars, также в случае успеха возвращается первый найденный элемент класса CommandBarControl. Разница состоит в том, что ключом поиска является заголовок искомого элемента. Но я хочу обратить внимание на реализацию данного метода. Заметьте, несмотря на то, что в основной части этой функции организован перебор по всей коллекции CommandBars, этому поиску предшествует поиск на отдельных элементах этой коллекции. Дело в том, что не все панели, реально присутствующие в коллекции, могут быть получены путем перебора в стандартном цикле For Each, индексы этих элементов выходят за диапазон, заданный значением Count этой коллекции. Таким образом, можно получить, например, доступ к панели "File"

Листинг 3.3.

(html, txt)

Но нельзя получить этот элемент в процессе перебора элементов коллекции CommandBars. Вместе с тем, многие команды меню находятся именно на этих панелях. Так, команда меню "Сохранить как " присутствует только на панели "File", в то же время другие команды, как, например, "Открыть", находятся одновременно и на панели "Standard". Справедливости ради, стоит заметить, что, если Вы знаете ID элемента, то для его поиска можно использовать стандартный метод поиска FindControl, который ведет поиск на всех панелях коллекции. Если же перебор панелей организуется самостоятельно, то следует считаться с "жучком", не позволяющим автоматически получить все элементы коллекции CommandBars.



PanelName As String) As Boolean


Public Function ExistCommandBar( PanelName As String) As Boolean 'Возвращает True, если в коллекции CommandBars 'существует панель с именем PanelName Dim bar As CommandBar, Exist As Boolean Exist = False For Each bar In CommandBars If bar.Name = PanelName Or bar.NameLocal = PanelName Then Exist = True Exit For End If Next bar ExistCommandBar = Exist End Function Public Function ExistControl(Panel As CommandBar, _ Capt As String) As Boolean 'Возвращает True, если в коллекции Controls ' панели с именем Panel существует элемент с заголовком capt Dim Ctrl As CommandBarControl, Exist As Boolean Exist = False For Each Ctrl In Panel.Controls If Ctrl.Caption = Capt Then Exist = True Exit For End If Next Ctrl ExistControl = Exist End Function Public Function ExistItem(CtrlPopUp As CommandBarPopup, _ Capt As String) As Boolean 'Возвращает True, если в меню CtrlPopUp ' существует элемент с заголовком capt Dim Ctrl As CommandBarControl, Exist As Boolean Exist = False For Each Ctrl In CtrlPopUp.Controls If Ctrl.Caption = Capt Then Exist = True Exit For End If Next Ctrl ExistItem = Exist End Function
Листинг 3.1.
Закрыть окно

Capt As String) As CommandBarControl


Public Function MyFindControl( Capt As String) As CommandBarControl 'Поиск по заголовку 'Возвращает в качестве результата первый элемент с указанным заголовком Dim bar As CommandBar Dim Ctr As CommandBarControl Dim i As Integer For i = 1 To 9 Select Case i Case 1 Set bar = CommandBars("File") Case 2 Set bar = CommandBars("Edit") Case 3 Set bar = CommandBars("View") Case 4 Set bar = CommandBars("Insert") Case 5 Set bar = CommandBars("Format") Case 6 Set bar = CommandBars("Tools") Case 7 Set bar = CommandBars("Table") Case 8 Set bar = CommandBars("Window") Case 9 Set bar = CommandBars("Help") End Select For Each Ctr In bar.Controls If Ctr.Caption = Capt Then Set MyFindControl = Ctr Exit Function End If Next Ctr Next i For Each bar In CommandBars 'Debug.Print bar.name For Each Ctr In bar.Controls If Ctr.Caption = Capt Then Set MyFindControl = Ctr Exit Function End If Next Ctr Next bar End Function
Листинг 3.2.
Закрыть окно

Set bar


Set bar = CommandBars("File")
Листинг 3.3.
Закрыть окно

и не является временной If


Public Sub AddPanel(PanelName As String) 'Добавляет и делает видимой панель с именем Panelname 'в коллекцию Commandbars 'Панель расположена вверху документа, 'не заменяет главное меню и не является временной If Not ExistCommandBar(PanelName) Then Call CommandBars.Add(name:=PanelName, Position:=msoBarTop, _ MenuBar:=False, Temporary:=False) End If CommandBars(PanelName).Enabled = True CommandBars(PanelName).Visible = True
End Sub
Листинг 3.4.
Закрыть окно

Выключаем все панели документа Dim


Public Sub AddMainPanel(MainPanel As String) ' Выключаем все панели документа Dim bar As CommandBar For Each bar In CommandBars bar.Enabled = False Next bar 'Добавляем и включаем новую панель главного меню If Not ExistCommandBar(MainPanel) Then Call CommandBars.Add(name:=MainPanel, Position:=msoBarTop, _ MenuBar:=True, Temporary:=False) End If CommandBars(MainPanel).Enabled = True CommandBars(MainPanel).Visible = True
End Sub
Листинг 3.5.
Закрыть окно

из коллекции CommandBars If


Public Sub DelPanel(PanelName As String) 'Удаляет пользовательскую панель ' из коллекции CommandBars If ExistCommandBar(PanelName) _ And Not CommandBars(PanelName).BuiltIn Then CommandBars(PanelName).Delete End If End Sub
Листинг 3.6.
Закрыть окно

Включаем все панели For Each


Public Sub ResetMainMenu() Dim CstmBar As CommandBar ' Включаем все панели For Each CstmBar In CommandBars CstmBar.Enabled = True Next CstmBar
Set CstmBar = CommandBars.Item("Menu Bar") CstmBar.Visible = True End Sub
Листинг 3.7.
Закрыть окно

Panel As String, MenuName As


Public Sub AddBuiltinMenu( Panel As String, MenuName As String, _ Num As Variant, item As CommandBarPopup) 'Добавляет встроенный пункт меню с именем MenuName 'на панель Panel Dim bar As CommandBar, ider As Variant Dim Ctrl As CommandBarControl Set bar = CommandBars(Panel) If Not ExistControl(bar, MenuName) Then Set Ctrl = MyFindControl(MenuName) 'Если найден If Not (Ctrl Is Nothing) Then ider = Ctrl.ID bar.Controls.Add Type:=msoControlPopup, _ ID:=ider, Before:=Num Else: Exit Sub End If End If Set item = bar.Controls(MenuName) End Sub
Листинг 3.8.
Закрыть окно

item As CommandBarPopup, name As


Public Sub AddItem( item As CommandBarPopup, name As String) Dim Ctrl As CommandBarControl If Not ExistItem(item, name) Then 'Найти встроенный элемент в коллекции встроенных панелей Set Ctrl = MyFindControl(name) 'Если найден If Not (Ctrl Is Nothing) Then item.Controls.Add Type:=msoControlButton, ID:=Ctrl.ID End If End If End Sub
Листинг 3.9.
Закрыть окно

_ name As String, Act


Public Sub AddCustomItem(item As CommandBarPopup, _ name As String, Act As String) 'Добавляет команду меню 'Параметр Act задает имя макроса, реализующего команду Dim Ctrl As CommandBarControl If Not ExistItem(item, name) Then Set Ctrl = item.Controls.Add(Type:=msoControlButton) Ctrl.Caption = name Ctrl.OnAction = Act End If End Sub Public Function AddCustomPopup(item As CommandBarPopup, _ name As String) As CommandBarPopup 'Добавляет подменю в меню, 'возвращая объект подменю в качестве результата Dim Ctrl As CommandBarPopup If Not ExistItem(item, name) Then Set Ctrl = item.Controls.Add(Type:=msoControlPopup) Ctrl.Caption = name End If Set AddCustomPopup = item.Controls(name) End Function
Листинг 3.10.
Закрыть окно

Создает главное меню Dim newitem


Public Sub CreateMainMenu() ' Создает главное меню Dim newitem As CommandBarPopup Dim Popupitem As CommandBarPopup 'Создает панель MainPanel главного меню AddMainPanel ("MainPanel") 'Добавляет пункт File Call AddBuiltinMenu("MainPanel", "&Файл", 1, newitem) AddItem newitem, "Созд&ать" AddItem newitem, "&Открыть..." AddItem newitem, "&Закрыть" AddItem newitem, "&Сохранить" AddItem newitem, "&Печать" AddItem newitem, "Сохранить &как..." 'Добавляет пункт Edit Call AddBuiltinMenu("MainPanel", "&Правка", 2, newitem) AddItem newitem, "&Вырезать" AddItem newitem, "&Копировать" AddItem newitem, "Вст&авить" AddItem newitem, "&Найти..." AddItem newitem, "&Заменить..." 'Добавляет собственный пункт "Документы" Call AddMenu("MainPanel", "&Документы", 3, newitem) AddCustomItem newitem, "Все документы", "Sorry" AddCustomItem newitem, "Мои документы", "Sorry" 'Добавляем подменю Set Popupitem = AddCustomPopup(newitem, "Текущие документы") AddCustomItem Popupitem, "Все текущие документы", "Sorry" AddCustomItem Popupitem, "Мои текущие документы", "Sorry" AddCustomItem newitem, "Последний документ", "Sorry"
'Добавляет собственный пункт "Проекты" Call AddMenu("MainPanel", "&Проекты", 4, newitem) AddCustomItem newitem, "Все проекты", "Sorry" AddCustomItem newitem, "Мои проекты", "Sorry" 'Добавляем подменю Set Popupitem = AddCustomPopup(newitem, "Текущие проекты") AddCustomItem Popupitem, "Все текущие проекты", "Sorry" AddCustomItem Popupitem, "Мои текущие проекты", "Sorry" AddCustomItem newitem, "Последний проект", "Sorry"
'Добавляет собственный пункт "Презентации" Call AddMenu("MainPanel", "&Презентации", 5, newitem) AddCustomItem newitem, "Все презентации", "Sorry" AddCustomItem newitem, "Мои презентации", "Sorry" 'Добавляем подменю Set Popupitem = AddCustomPopup(newitem, "Текущие презентации") AddCustomItem Popupitem, "Все текущие презентации", "Sorry" AddCustomItem Popupitem, "Мои текущие презентации", "Sorry" AddCustomItem newitem, "Последняя презентация", "Sorry"
End Sub
Листинг 3.11.
Закрыть окно

Создаем панель Dim panel As


Public Sub CreateComboPanel() 'Создание панели с элементами класса CommandBarCombobox ' Создаем панель Dim panel As CommandBar Dim Ctrl As CommandBarComboBox AddPanel ("ComboPanel") Set panel = CommandBars("ComboPanel") 'Добавляем на панель три Combo кнопки разного типа 'Добавление окна редактирования Edit Set Ctrl = AddCustomCombo(panel, "Edititem", msoControlEdit) 'Добавляем text в окно редактирования Ctrl.Text = "Один" Ctrl.OnAction = "EditReaction" 'Добавление выпадающего списка Set Ctrl = AddCustomCombo(panel, "DropdownItem", msoControlDropdown) 'Задание элементов списка Ctrl.AddItem "One", 1 Ctrl.AddItem "Two", 2 Ctrl.AddItem "Three", 3 'Отчеркивание группы элементов Ctrl.ListHeaderCount = 3 'Добавление элемента в конец списка Ctrl.AddItem "Others" Ctrl.OnAction = "DropdownReaction" 'Добавление элемента Combobox - окно редактирования и список Set Ctrl = AddCustomCombo(panel, "ComboBoxItem", msoControlComboBox) Ctrl.Text = "One" Ctrl.AddItem "One" Ctrl.AddItem "Five" Ctrl.OnAction = "DropdownReaction" End Sub
Листинг 3.12.
Закрыть окно

_ name As String, tip


Public Function AddCustomCombo(panel As CommandBar, _ name As String, tip As Variant) As CommandBarComboBox 'Добавляет на панель элемент, тип которого задан параметром tip 'возвращая объект CommandBarComboBox в качестве результата Dim Ctrl As CommandBarComboBox If Not ExistControl(panel, name) Then Set Ctrl = panel.Controls.Add(Type:=tip) Ctrl.Caption = name End If Set AddCustomCombo = panel.Controls(name) End Function
Листинг 3.13.
Закрыть окно

Edit ComboBox Dim Ctrl As


Public Sub EditReaction() 'Обработчик меню - Edit ComboBox Dim Ctrl As CommandBarComboBox 'Определяем активный элемент коллекции панелей, 'задающий меню, выбранное пользователем Set Ctrl = CommandBars.ActionControl MsgBox ("Привет! В окне редактирования набран (выбран) текст: " & Ctrl.Text)
'Далее можно задать реакцию на введенный текст
End Sub
Public Sub DropdownReaction() 'Обработчик кнопки меню - Dropdown ComboBox Dim Ctrl As CommandBarComboBox Set Ctrl = CommandBars.ActionControl 'MsgBox ("Hi! Here is Dropdown Box") With Ctrl Select Case .Text Case "One", "Two" MsgBox ("Your Choice : one or two") Case "Three" MsgBox ("Your Choice : three") Case Else MsgBox ("Your Choice : unknown") End Select
Select Case .ListIndex Case 1, 2 MsgBox ("Your Choice : one or two") Case 3 MsgBox ("Your Choice : three") Case Else MsgBox ("Your Choice : unknown") End Select
End With End Sub
Листинг 3.14.
Закрыть окно

Создаем панель Dim panel As


Public Sub CreateButtonPanel() 'Создание панели с элементами класса CommandBarButton ' Создаем панель Dim panel As CommandBar Dim ctrl As CommandBarButton Dim Ctrl1 As CommandBarButton AddPanel ("ButtonPanel") Set panel = CommandBars("ButtonPanel") 'Добавляем на панель четыре кнопки 'Добавление кнопки ER Set ctrl = AddCustomButton(panel, "ER") 'Свойства кнопки With ctrl .OnAction = "Translate.FromEtoR" .DescriptionText = _ "Перевод в русскую раскладку клавиатуры" .TooltipText = "English -> Russian" .Style = msoButtonIconAndCaption .Tag = "English -> Russian" .FaceId = 134 End With 'Добавление кнопки RE Set ctrl = AddCustomButton(panel, "RE") 'Свойства кнопки With ctrl .OnAction = "Translate.FromRtoE" .DescriptionText = _ "Перевод в английскую раскладку клавиатуры" .TooltipText = "Russian -> English" .Style = msoButtonIconAndCaption .Tag = "Russian -> English" .FaceId = 135 End With 'Добавление кнопки RL Set ctrl = AddCustomButton(panel, "RL") 'Свойства кнопки With ctrl .OnAction = "Translate.FromRuToLat" .DescriptionText = _ "Перевод в латиницу" .TooltipText = "Кириллица -> Латиница" .Style = msoButtonIconAndCaption .Tag = "Кириллица -> Латиница" .FaceId = 137 End With 'Добавление кнопки RepNew Set ctrl = AddCustomButton(panel, "RepNew") 'Свойства кнопки With ctrl .OnAction = "Translate.RepNew" .DescriptionText = _ "Форматирование программного текста" .TooltipText = "Форматирование" .Style = msoButtonIconAndCaption .Tag = "Форматирование программного текста" .BeginGroup = True 'Поиск кнопки с подходящим рисунком Set Ctrl1 = MyFindControl("&Разметка страницы") Ctrl1.CopyFace .PasteFace End With End Sub
Листинг 3.15.
Закрыть окно

_ name As String) As


Public Function AddCustomButton(panel As CommandBar, _ name As String) As CommandBarButton 'Добавляет на панель кнопку, 'возвращая объект CommandBarButton в качестве результата Dim ctrl As CommandBarButton If Not ExistControl(panel, name) Then Set ctrl = panel.Controls.Add(Type:=msoControlButton) ctrl.Caption = name End If Set AddCustomButton = panel.Controls(name) End Function
Листинг 3.16.
Закрыть окно

Пример создания интерфейса


В качестве примера рассмотрим создание собственного интерфейса у документа Word. Все стандартные панели для него будут отключены, и я создам три собственные инструментальные панели. Одна из них будет содержать главное меню документа, вторая - панель с командными кнопками, третья панель будет содержать специальные элементы класса ComboBox. Тем самым будут охвачены практически все возможные варианты работы с инструментальными панелями в процессе создания интерфейса.



Проектирование панели с элементами Combobox


Макросы, отвечающие за вызов команд меню, встроенных или собственных, могут быть сколь угодно сложными. Зачастую, выбор команды меню является, по существу, приглашением к началу диалога с пользователем. Соответствующий макрос открывает форму (диалоговое окно), содержащее многочисленные кнопки, вкладки и другие элементы интерфейса. Типичным примером являются встроенные команды "Открыть…" и "Сохранить как…", диалоговые окна которых пополнились новыми возможностями в Office 2000. Но не всегда следует применять формы, чтобы организовать диалог с пользователем в процессе выбора команды меню. Нередко можно обойтись специальными элементами класса CommandBarCombobox, позволяющими пользователю при работе с меню задать самостоятельно или выбрать подходящее значение из раскрывающегося списка. Примеры таких элементов хорошо знакомы по встроенному меню. С ними приходится, например, встречаться при выборе стиля, шрифта, подходящего размера шрифта или масштаба.

Давайте создадим панель с собственными элементами подобного типа. Я помещу на панель три элемента разных типов, но принадлежащих одному классу - CommandBarComboBox:

Первый элемент будет представлять окно редактирования Edit. При работе с таким элементом пользователь имеет возможность ввести свой текст в окно редактирования или согласиться с предложенным ему текстом. Макрос, вызываемый в ответ на действия пользователя, может проанализировать текст, введенный пользователем и реагировать на это соответствующим образом.Второй элемент будет представлять выпадающий список (Dropdown List), из которого пользователь может выбрать подходящее значение. На примере я покажу, как можно задать элементы списка и как в макросе, вызываемом в ответ на выбор пользователя, можно проанализировать, какое значение выбрал пользователь из списка.Третий элемент - ComboBox - объединяет достоинства двух предыдущих элементов, обладая как окном редактирования, так и возможностью выбора значения из списка.

Вот текст процедуры, решающей поставленную задачу:


Листинг 3.14.

(html, txt)

Обратите внимание, прежде чем анализировать свойства объекта, нужно получить сам объект, определяющий элемент меню. Для этого используется метод ActionControl коллекции CommandBars, возвращающий активный элемент этой коллекции, то есть тот самый элемент меню, с которым работал пользователь. Получив этот объект на первом шаге, можно далее анализировать его свойства, чтобы определить выбор пользователя.

С окном редактирования все достаточно просто, поскольку уже знакомое свойство Text позволяет понять, какое значение введено пользователем или он согласился с предложенным ему значением. Для списков, как правило, устраивается разбор случаев. Заметьте, я привел два альтернативных способа, позволяющих узнать, какой элемент списка был выбран пользователем. В первом случае используется свойство текст. Альтернативой является использование свойства ListIndex, фиксирующего номер элемента списка, выбранного пользователем. Замечу, что часто приходится пользоваться и свойством List(i), хранящим значение i-го элемента списка.

Public Sub CreateComboPanel() 'Создание панели с элементами класса CommandBarCombobox ' Создаем панель Dim panel As CommandBar Dim Ctrl As CommandBarComboBox AddPanel ("ComboPanel") Set panel = CommandBars("ComboPanel") 'Добавляем на панель три Combo кнопки разного типа 'Добавление окна редактирования Edit Set Ctrl = AddCustomCombo(panel, "Edititem", msoControlEdit) 'Добавляем text в окно редактирования Ctrl.Text = "Один" Ctrl.OnAction = "EditReaction" 'Добавление выпадающего списка Set Ctrl = AddCustomCombo(panel, "DropdownItem", msoControlDropdown) 'Задание элементов списка Ctrl.AddItem "One", 1 Ctrl.AddItem "Two", 2 Ctrl.AddItem "Three", 3 'Отчеркивание группы элементов Ctrl.ListHeaderCount = 3 'Добавление элемента в конец списка Ctrl.AddItem "Others" Ctrl.OnAction = "DropdownReaction" 'Добавление элемента Combobox - окно редактирования и список Set Ctrl = AddCustomCombo(panel, "ComboBoxItem", msoControlComboBox) Ctrl.Text = "One" Ctrl.AddItem "One" Ctrl.AddItem "Five" Ctrl.OnAction = "DropdownReaction" End Sub

Листинг 3.12.

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

Public Function AddCustomCombo(panel As CommandBar, _ name As String, tip As Variant) As CommandBarComboBox 'Добавляет на панель элемент, тип которого задан параметром tip 'возвращая объект CommandBarComboBox в качестве результата Dim Ctrl As CommandBarComboBox If Not ExistControl(panel, name) Then Set Ctrl = panel.Controls.Add(Type:=tip) Ctrl.Caption = name End If Set AddCustomCombo = panel.Controls(name) End Function

Листинг 3.13.

Хотя в процедуре CreateComboPanel есть подробные комментарии, но есть смысл сказать о ней еще несколько слов и остановится на используемых в ней методах и свойствах объектов. Это тем более уместно по той причине, что ранее я не стал описывать свойства и методы объектов класса CommandBarComboBox, ни их общего класса CommandbarControl. Теперь пришла пора в какой-то мере исправить это положение. Прежде всего, напомню, что объекты класса CommandbarComboBox могут быть разного типа. Их тип задается в момент создания элемента и определяется значением соответствующей константы. Так тип наших трех элементов задается соответственно константами: msoControlEdit, msoControlDropdown, msoControlComboBox. Тип определяет, какие свойства и методы класса CommandBarComboBox доступны для использования у данного элемента.

Так, например, я использую свойство Text, чтобы задать текст, появляющийся в окне редактирования у первого и третьего элементов, которые обладают окном редактирования, доступным для ввода значений. Это свойство нельзя задать для второго элемента, задающего выпадающий список. Для него значение свойства Text формируется автоматически при выборе пользователем значения из списка.

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

Некоторые другие свойства и методы объектов этого класса я использовал в макросах, вызываемых в ответ на выбор пользователем соответствующего элемента меню. Мне они понадобились для решения главной задачи - получения в макросе информации, введенной пользователем или выбранной им из списка. Но прежде, приведем тексты соответствующих макросов:



Public Sub EditReaction() 'Обработчик меню - Edit ComboBox Dim Ctrl As CommandBarComboBox 'Определяем активный элемент коллекции панелей, 'задающий меню, выбранное пользователем Set Ctrl = CommandBars.ActionControl MsgBox ("Привет! В окне редактирования набран (выбран) текст: " & Ctrl.Text)

'Далее можно задать реакцию на введенный текст

End Sub

Public Sub DropdownReaction() 'Обработчик кнопки меню - Dropdown ComboBox Dim Ctrl As CommandBarComboBox Set Ctrl = CommandBars.ActionControl 'MsgBox ("Hi! Here is Dropdown Box") With Ctrl Select Case .Text Case "One", "Two" MsgBox ("Your Choice : one or two") Case "Three" MsgBox ("Your Choice : three") Case Else MsgBox ("Your Choice : unknown") End Select

Select Case .ListIndex Case 1, 2 MsgBox ("Your Choice : one or two") Case 3 MsgBox ("Your Choice : three") Case Else MsgBox ("Your Choice : unknown") End Select

End With End Sub

Листинг 3.14.

Обратите внимание, прежде чем анализировать свойства объекта, нужно получить сам объект, определяющий элемент меню. Для этого используется метод ActionControl коллекции CommandBars, возвращающий активный элемент этой коллекции, то есть тот самый элемент меню, с которым работал пользователь. Получив этот объект на первом шаге, можно далее анализировать его свойства, чтобы определить выбор пользователя.

С окном редактирования все достаточно просто, поскольку уже знакомое свойство Text позволяет понять, какое значение введено пользователем или он согласился с предложенным ему значением. Для списков, как правило, устраивается разбор случаев. Заметьте, я привел два альтернативных способа, позволяющих узнать, какой элемент списка был выбран пользователем. В первом случае используется свойство текст. Альтернативой является использование свойства ListIndex, фиксирующего номер элемента списка, выбранного пользователем. Замечу, что часто приходится пользоваться и свойством List(i), хранящим значение i-го элемента списка.



'Добавляет собственный пункт "Проекты" Call AddMenu("MainPanel", "&Проекты", 4, newitem) AddCustomItem newitem, "Все проекты", "Sorry" AddCustomItem newitem, "Мои проекты", "Sorry" 'Добавляем подменю Set Popupitem = AddCustomPopup(newitem, "Текущие проекты") AddCustomItem Popupitem, "Все текущие проекты", "Sorry" AddCustomItem Popupitem, "Мои текущие проекты", "Sorry" AddCustomItem newitem, "Последний проект", "Sorry"

'Добавляет собственный пункт "Презентации" Call AddMenu("MainPanel", "&Презентации", 5, newitem) AddCustomItem newitem, "Все презентации", "Sorry" AddCustomItem newitem, "Мои презентации", "Sorry" 'Добавляем подменю Set Popupitem = AddCustomPopup(newitem, "Текущие презентации") AddCustomItem Popupitem, "Все текущие презентации", "Sorry" AddCustomItem Popupitem, "Мои текущие презентации", "Sorry" AddCustomItem newitem, "Последняя презентация", "Sorry"

End Sub

Листинг 3.11.

Я не стал определять макросы, отвечающие за вызов каждой собственной команды меню, ограничившись стандартной заглушкой "Sorry". В заключение, взгляните на документ, в котором главное меню имеет спроектированный нами вид:


увеличить изображение
Рис. 3.1.  Документ, имеющий собственное главное меню


Создание головного меню


Создадим документ, в котором:

Все встроенные панели отключены,Главное меню содержит пять команд. Каждая команда головного меню является именем вертикально расположенного меню, выпадающего при выборе этой команды. Первые две команды главного меню (Файл, Правка) являются привычными для документов Office 2000 и содержат встроенные команды. Три другие команды главного меню (Документы, Проекты, Презентации) являются пользовательскими и содержат собственные команды, макросы для которых придется написать самостоятельно.

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

Листинг 3.11.

(html, txt)

Я не стал определять макросы, отвечающие за вызов каждой собственной команды меню, ограничившись стандартной заглушкой "Sorry". В заключение, взгляните на документ, в котором главное меню имеет спроектированный нами вид:


увеличить изображение
Рис. 3.1.  Документ, имеющий собственное главное меню


'Добавляет собственный пункт "Проекты" Call AddMenu("MainPanel", "&Проекты", 4, newitem) AddCustomItem newitem, "Все проекты", "Sorry" AddCustomItem newitem, "Мои проекты", "Sorry" 'Добавляем подменю Set Popupitem = AddCustomPopup(newitem, "Текущие проекты") AddCustomItem Popupitem, "Все текущие проекты", "Sorry" AddCustomItem Popupitem, "Мои текущие проекты", "Sorry" AddCustomItem newitem, "Последний проект", "Sorry"

'Добавляет собственный пункт "Презентации" Call AddMenu("MainPanel", "&Презентации", 5, newitem) AddCustomItem newitem, "Все презентации", "Sorry" AddCustomItem newitem, "Мои презентации", "Sorry" 'Добавляем подменю Set Popupitem = AddCustomPopup(newitem, "Текущие презентации") AddCustomItem Popupitem, "Все текущие презентации", "Sorry" AddCustomItem Popupitem, "Мои текущие презентации", "Sorry" AddCustomItem newitem, "Последняя презентация", "Sorry"

End Sub

Листинг 3.11.

Я не стал определять макросы, отвечающие за вызов каждой собственной команды меню, ограничившись стандартной заглушкой "Sorry". В заключение, взгляните на документ, в котором главное меню имеет спроектированный нами вид:


увеличить изображение
Рис. 3.1.  Документ, имеющий собственное главное меню


Создание интерфейса документа. Объект CommandBars


Создание интерфейса документа - одна из важных задач, стоящих при разработке практически любых документов. Создание меню, командных кнопок и других элементов управления, вынесенных на инструментальные панели или встроенных непосредственно в документ, создание диалоговых окон (форм) - все эти задачи успешно решены еще в предыдущих версиях Office, и потому в Office 2000 немногое изменилось в этой области.

В Office команды меню и командные кнопки располагаются на инструментальных панелях, которые составляют коллекцию CommandBars. Эти панели могут быть причалены или пристыкованы (docked) к левому, правому, верхнему или нижнему краю документа, а могут находиться и в плавающем состоянии. Каждая панель (объект CommandBar) содержит набор меню или командных кнопок - коллекцию CommandBarControls. Элементы этой коллекции (объекты CommandBarControl) в зависимости от их типа представляют отдельные меню, команды меню или командные кнопки. В Office 2000 имеется большое число встроенных панелей со встроенными элементами. Но одно из достоинств Office состоит в том, что весь этот интерфейс является настраиваемым - любую из панелей, также как и любой из элементов, расположенных на панели, можно отключить или включить в любую минуту, можно изменять элементы, показываемые на панелях. В Office 2000 это может делаться автоматически, на основе "интеллектуальных" соображений, - отключаются те команды, которые давно не использовались. Самое главное, что наряду со встроенными панелями и командами можно создавать собственные панели и команды. Это позволяет полностью отказаться от стандартного интерфейса, создав свой собственный интерфейс документа. Чаще всего, в документе используется комбинация собственных и встроенных элементов интерфейса.

Большая часть задач по созданию собственных инструментальных панелей и элементов, располагаемых на них, обычно решается вручную без использования программирования, хотя понятно, что невозможно обойтись без написания макросов, вызываемых в ответ на нажатие командных кнопок или выбор команд меню, созданных собственноручно. Но почти все эти задачи (к сожалению, есть некоторые исключения) можно решать и программно, чем мы сейчас и займемся.



Создание панели с кнопками - объектами класса CommandBarButton


Напомню, класс CommandBarControl объединяет три класса объектов - CommandBarPopup, CommandBarComboBox и CommandBarButton. О двух первых из них мы уже поговорили, осталось рассмотреть самый простой класс, когда элементами панели являются кнопки. Создание панелей с кнопками - это наиболее распространенная задача, которую приходится решать при проектировании интерфейса документа. Чтобы расширить возможности стандартного документа Office 2000, добавить собственные функции, учитывающие специфику документа, достаточно написать соответствующие макросы, реализующие эти функции, связать макросы с кнопками и разместить эти кнопки на инструментальной панели.

Когда я работаю с документом Word, то, как правило, включаю свою панель с кнопками, реализующими дополнительные функции, которые я привык использовать в своей работе. В следующем примере я построю панель, содержащую четыре такие кнопки. Макросы, связанные с первыми двумя кнопками, устраняют ошибки переключения клавиатуры, возникающие в ситуации, когда я забываю изменить раскладку клавиатуры. Я предпочитаю пользоваться собственными макросами, несмотря на то, что подобная стандартная функция включена в состав Word 2000. Мои функции мне представляются более удобными. Третий макрос производит посимвольное преобразование текста из кириллицы в латиницу. Им я часто пользуюсь при пересылке русских текстов за рубеж в случае, когда у получателя отсутствует возможность чтения кириллических текстов. Четвертый макрос служит для форматирования программного текста, копируемого из Редактора VBA, заменяя пробелы символами табуляции, изменяя стиль и выполняя другие полезные преобразования.

Вот процедура, создающая инструментальную панель с кнопками:

Листинг 3.15.

(html, txt)

Как обычно, в этой процедуре вызывается процедура добавления AddCustomButton, добавляющая кнопку на панель. Она подобна другим процедурам добавления, вот ее текст:

Public Function AddCustomButton(panel As CommandBar, _ name As String) As CommandBarButton 'Добавляет на панель кнопку, 'возвращая объект CommandBarButton в качестве результата Dim ctrl As CommandBarButton If Not ExistControl(panel, name) Then Set ctrl = panel.Controls.Add(Type:=msoControlButton) ctrl.Caption = name End If Set AddCustomButton = panel.Controls(name) End Function


Напомню, класс CommandBarControl объединяет три класса объектов - CommandBarPopup, CommandBarComboBox и CommandBarButton. О двух первых из них мы уже поговорили, осталось рассмотреть самый простой класс, когда элементами панели являются кнопки. Создание панелей с кнопками - это наиболее распространенная задача, которую приходится решать при проектировании интерфейса документа. Чтобы расширить возможности стандартного документа Office 2000, добавить собственные функции, учитывающие специфику документа, достаточно написать соответствующие макросы, реализующие эти функции, связать макросы с кнопками и разместить эти кнопки на инструментальной панели.

Когда я работаю с документом Word, то, как правило, включаю свою панель с кнопками, реализующими дополнительные функции, которые я привык использовать в своей работе. В следующем примере я построю панель, содержащую четыре такие кнопки. Макросы, связанные с первыми двумя кнопками, устраняют ошибки переключения клавиатуры, возникающие в ситуации, когда я забываю изменить раскладку клавиатуры. Я предпочитаю пользоваться собственными макросами, несмотря на то, что подобная стандартная функция включена в состав Word 2000. Мои функции мне представляются более удобными. Третий макрос производит посимвольное преобразование текста из кириллицы в латиницу. Им я часто пользуюсь при пересылке русских текстов за рубеж в случае, когда у получателя отсутствует возможность чтения кириллических текстов. Четвертый макрос служит для форматирования программного текста, копируемого из Редактора VBA, заменяя пробелы символами табуляции, изменяя стиль и выполняя другие полезные преобразования.

Вот процедура, создающая инструментальную панель с кнопками:

Public Sub CreateButtonPanel() 'Создание панели с элементами класса CommandBarButton 'Создаем панель Dim panel As CommandBar Dim ctrl As CommandBarButton Dim Ctrl1 As CommandBarButton AddPanel ("ButtonPanel") Set panel = CommandBars("ButtonPanel") 'Добавляем на панель четыре кнопки 'Добавление кнопки ER Set ctrl = AddCustomButton(panel, "ER") 'Свойства кнопки With ctrl .OnAction = "Translate.FromEtoR" .DescriptionText = _ "Перевод в русскую раскладку клавиатуры" .TooltipText = "English -> Russian" .Style = msoButtonIconAndCaption .Tag = "English -> Russian" .FaceId = 134 End With 'Добавление кнопки RE Set ctrl = AddCustomButton(panel, "RE") 'Свойства кнопки With ctrl .OnAction = "Translate.FromRtoE" .DescriptionText = _ "Перевод в английскую раскладку клавиатуры" .TooltipText = "Russian -> English" .Style = msoButtonIconAndCaption .Tag = "Russian -> English" .FaceId = 135 End With 'Добавление кнопки RL Set ctrl = AddCustomButton(panel, "RL") 'Свойства кнопки With ctrl .OnAction = "Translate.FromRuToLat" .DescriptionText = _ "Перевод в латиницу" .TooltipText = "Кириллица -> Латиница" .Style = msoButtonIconAndCaption .Tag = "Кириллица -> Латиница" .FaceId = 137 End With 'Добавление кнопки RepNew Set ctrl = AddCustomButton(panel, "RepNew") 'Свойства кнопки With ctrl .OnAction = "Translate.RepNew" .DescriptionText = _ "Форматирование программного текста" .TooltipText = "Форматирование" .Style = msoButtonIconAndCaption .Tag = "Форматирование программного текста" .BeginGroup = True 'Поиск кнопки с подходящим рисунком Set Ctrl1 = MyFindControl("&Разметка страницы") Ctrl1.CopyFace .PasteFace End With End Sub




Листинг 3.16.

(html, txt)

Вернемся к процедуре CreateButtonPanel и прокомментируем использованные в ней методы и свойства объектов класса CommandBarButton. Помимо общего для кнопок и команд меню метода OnAction, связывающего с кнопкой макрос, я использовал ряд специальных свойств и методов:

Свойство DescriptionText позволяет задать описание функции, выполняемой макросом.Свойство TooltipText задает такое же описание, но в более краткой форме, появляющееся в виде подсказки при подведении курсора к кнопке.Свойство Sryle задает внешний вид кнопки. В данном случае, когда стиль задан константой msoButtonIconAndCaption, на кнопке будет отображаться рисунок, сопровождаемый текстом.Свойство Tag также задает описание элемента. Если элемент обладает свойством Tag, то его можно найти, используя значение этого свойства в качестве ключа в стандартном методе поиска FindControl. Напомню, что в этом методе в качестве ключа нельзя использовать свойство Caption .Свойство FaceId позволяет задать идентификатор картинки, размещаемой на кнопке. Конечно, есть определенная трудность в том, чтобы знать какое число соответствует желаемой картинке. С этой проблемой частично можно справиться, используя методы CopyFace и PasteFace .Метод CopyFace копирует в буфер картинку, размещаемую на кнопке.Метод PasteFace переносит картинку из буфера на кнопку. Заметьте, на кнопку можно поместить любой рисунок в формате, допускающем сжатие. Для этого следует скопировать рисунок в буфер, а затем применить метод PasteFace.

Таким образом, как видите, программные возможности по созданию красивых кнопок на инструментальной панели ничуть не ниже, чем при выполнении этой работы вручную.

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


увеличить изображение
Рис. 3.2.  Документ с тремя панелями, реализующими собственный интерфейс



Листинг 3.15.

Как обычно, в этой процедуре вызывается процедура добавления AddCustomButton, добавляющая кнопку на панель. Она подобна другим процедурам добавления, вот ее текст:

Public Function AddCustomButton(panel As CommandBar, _ name As String) As CommandBarButton 'Добавляет на панель кнопку, 'возвращая объект CommandBarButton в качестве результата Dim ctrl As CommandBarButton If Not ExistControl(panel, name) Then Set ctrl = panel.Controls.Add(Type:=msoControlButton) ctrl.Caption = name End If Set AddCustomButton = panel.Controls(name) End Function

Листинг 3.16.

Вернемся к процедуре CreateButtonPanel и прокомментируем использованные в ней методы и свойства объектов класса CommandBarButton. Помимо общего для кнопок и команд меню метода OnAction, связывающего с кнопкой макрос, я использовал ряд специальных свойств и методов:

Свойство DescriptionText позволяет задать описание функции, выполняемой макросом.Свойство TooltipText задает такое же описание, но в более краткой форме, появляющееся в виде подсказки при подведении курсора к кнопке.Свойство Sryle задает внешний вид кнопки. В данном случае, когда стиль задан константой msoButtonIconAndCaption, на кнопке будет отображаться рисунок, сопровождаемый текстом.Свойство Tag также задает описание элемента. Если элемент обладает свойством Tag, то его можно найти, используя значение этого свойства в качестве ключа в стандартном методе поиска FindControl. Напомню, что в этом методе в качестве ключа нельзя использовать свойство Caption .Свойство FaceId позволяет задать идентификатор картинки, размещаемой на кнопке. Конечно, есть определенная трудность в том, чтобы знать какое число соответствует желаемой картинке. С этой проблемой частично можно справиться, используя методы CopyFace и PasteFace .Метод CopyFace копирует в буфер картинку, размещаемую на кнопке.Метод PasteFace переносит картинку из буфера на кнопку. Заметьте, на кнопку можно поместить любой рисунок в формате, допускающем сжатие. Для этого следует скопировать рисунок в буфер, а затем применить метод PasteFace.



Таким образом, как видите, программные возможности по созданию красивых кнопок на инструментальной панели ничуть не ниже, чем при выполнении этой работы вручную.

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


увеличить изображение
Рис. 3.2.  Документ с тремя панелями, реализующими собственный интерфейс

Свойства и методы коллекции CommandBars


Коллекция CommandBarsобладает не только традиционными свойствами и методами, но и некоторыми специфическими свойствами. Давайте кратко познакомимся с большинством из них:

Property ActionControl As CommandBarControl вызывается обычно в OnAction процедуре и возвращает объект CommandBarControl, чье свойство OnAction связано с этой выполняемой процедурой. Если же такого объекта нет, то возвращается значение Nothing, что бывает при вызове этого свойства из обычной процедуры. Позволяет отключить доступ к объекту на время выполнения процедуры. Property ActiveMenuBar As CommandBar возвращает объект CommandBar, представляющий активную панель меню.Property DisplayKeysInTooltips As Boolean, DisplayTooltips As Boolean - если свойства имеют значения True, то на панели отображаются назначения "горячих" клавиш.Property LargeButtons As Boolean- значение True позволяет включить клавиши "большого" размера.Function Add([Name], [Position], [MenuBar], [Temporary]) As CommandBar. Метод Add - основной метод коллекции позволяет программным путем добавить в коллекцию новую собственную панель, дав ей имя Name. Параметр Position указывает расположение панели на экране. Его возможные значения: msoBarLeft, msoBarTop, msoBarRight, msoBarBottom указывают, куда стыковочная панель будет причалена - справа, слева, вверху или снизу экрана. Значение msoBarFloating этого параметра указывает, что панель появится в плавающем состоянии. Значение msoBarPopup указывает, что новая панель создается для контекстного меню. Булев параметр MenuBar имеет значение True, когда новая панель заменяет главную панель меню. Булев параметр Temporary позволяет сделать добавление панели временным (на момент сеанса) или постоянным.Function FindControl([Type], [Id], [Tag], [Visible], [Recursive]) As CommandBarControl Позволяет найти на панелях, входящих в коллекцию, элемент, удовлетворяющий критериям поиска. Параметры, являющиеся ключами поиска, могут быть опущены, достаточно задания одного из них. Булев параметр Recursive указывает, нужно ли вести поиск на всю глубину, включая все подменю. Если критериям поиска удовлетворяет несколько элементов, то в качестве результата возвращается первый из них. Возвращается значение Nothing, если поиск был безуспешным.Sub ReleaseFocus() Все панели теряют фокус.

В Office 2000 у этой коллекции появились новый метод, новое свойство и новое событие:

Function FindControls([Type], [Id], [Tag], [Visible]) As CommandBarControls. Является обобщением метода FindControl, возвращая в случае успеха коллекцию CommandBarControls, содержащую все элементы, удовлетворяющие критериям поиска.Property AdaptiveMenus As Boolean. Позволяет включить или выключить свойство адаптивности встроенных меню, автоматически настраивающее их видимый состав в зависимости от частоты использования той или иной команды меню.Event OnUpdate(). Событие возникает при любых изменениях командной панели объекта CommandBar.



Свойства и методы объекта CommandBar


Вот основные свойства и методы самого объекта CommandBar, представляющего отдельную панель:

Property BuiltIn As Boolean Это булево свойство определено как для панели, так и для ее элементов, значение True указывает, что панель или элемент являются встроенными, False - определены пользователем.Property Context As String - позволяет установить или проверить контекст, определяющий местоположение хранения панели, то ли непосредственно с самим документом, то ли в другом возможном месте, зависящем от приложения.

К сожалению, это свойство не работает должным образом. Изменить его значение программным путем не удается.

Property Controls As CommandBarControls - можно сказать центральное свойство, возвращающее коллекцию элементов, располагаемых на панели.Property Enabled As Boolean, Visible As Boolean - тоже два центральных и широко используемых свойства. Первое позволяет выключить доступ к панели, обычно временно, второе делает панель вообще невидимой и тем более недоступной.Property Height As Long, Left As Long, Top As Long, Width As Long - типичные свойства графических элементов, в том числе для панели и ее элементов. Задают размеры элемента.Property Index As Long - возвращает порядковый номер элемента в коллекции.Property Name As String, NameLocal As String - имя панели или ее элемента, для встроенных панелей (элементов) имеют смысл два имени "родное" английское имя и локализованное.Property Position As MsoBarPosition- такое же свойство, как у коллекции панелей, но применяемое к отдельно взятой панели.Property Protection As MsoBarProtection - защищает панель от тех или иных действий пользователя. Значением свойства являются константы, определяющие, что конкретно нельзя делать с панелью, например, менять ее размеры или передвигать.Property Type As MsoBarType- возвращает тип панели.Sub Delete() - удаляет панельFunction FindControl([Type], [Id], [Tag], [Visible], [Recursive]) As CommandBarControl - такой же метод поиска элемента, как и описанный выше для коллекции, но поиск ограничен пределами одной панели.Sub Reset() - Восстанавливает установки, принятые по умолчанию, в частности конфигурацию встроенных панелей.Sub ShowPopup([x], [y]) - отображает контекстную панель в позиции, заданной курсором или параметрами X и Y, если они указаны.