Разбираем по кусочкам новый «ленточный» интерфейс Word 2007. Здесь нет и не будет советов о том, как его сделать похожим на Word 2003. Только усовершенствования уже существующего. Также приглашаю посетить мой блог, посвященный работе с макросами в Word.

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

понедельник, 5 января 2009 г.

Динамическое меню (продолжение)

Оказывается, что формировать ленту на лету не только можно, но и чрезвычайно полезно.
Я решил, по примеру Антона Кокина сделать свое меню для работы с закладками, только в версии для Word2007.
Сказано — сделано.
Вот что получилось:

При добавлении закладки в документ меню обновляется и имя закладки появляется внизу списка. Щелчок на имени приводит к переходу на эту закладку. В подменю «Управление закладками» появляются пункты, позволяющие удалить нужную закладку. Например, вот так:

Для того, чтобы все это работало, следует выполнить несколько простых шагов:

  1. Создать динамическое меню в схеме документа при помощи RibbonXMLEditor

  2. В этом меню определить макрос, который отвечает за наполнение меню содержимым

  3. Написать сам макрос в документе, или, что намного лучше, в шаблоне.


Следует заметить, что динамическое меню получает свое содержимое при первом щелчке на нем, что может вызывать определенные задержки при большом количестве закладок или на слабой машине. А я-то думал, почему так долго открываются стандартные меню-галереи? А ведь они обновляются при открытии.
XML-код для динамического меню закладок   Копировать код без номеров строк
1 <dynamicMenu id="DynMenu"
2 label="Закладки"
3 getContent="DynMenuGetBookmarks_GetContent"/>

В шаблоне, где мы делаем все манипуляции с ленточным интерфейсом, пишем код макроса DynMenuGetBookmarks_GetContent. Код этот довольно сложен для восприятия с первого раза, но, разобравшись, он не представляет трудностей.
Макрос формирования меню с закладками документа   Копировать код без номеров строк
1 Sub DynMenuGetBookmarks_GetContent(control As IRibbonControl, ByRef content)
2 '
3 'Формирование меню с закладками документа
4 '
5 Dim sXML As String
6 Dim i As Integer
7 Set bm = ActiveDocument.Bookmarks
8 sXML = "<menu xmlns=""" & "http://schemas.microsoft.com/office/2006/01/customui" & """>" & vbCr
9 '--------------------------
10 'Кнопка «Обновить»
11 '--------------------------
12 sXML = sXML & _
13 "<button id=""RefreshDynMenu"" " & _
14 "label=""Обновить"" " & _
15 "onAction=""RefreshDynMenu_OnAction"" " & _
16 "imageMso=""RecurrenceEdit""/>" & vbCr
17 '--------------------------
18 'Меню «Управление закладками»
19 '--------------------------
20 sXML = sXML & _
21 "<menu id=""ManageBookMarks"" " & _
22 "label=""Управление закладками"" " & _
23 "imageMso=""ControlToolboxOutlook"">" & vbCr & _
24 "<button id=""menu_AddBookmark"" " & _
25 "label=""Добавить закладку"" " & _
26 "onAction=""menu_AddBookmark_onAction""/>" & vbCr & _
27 "<menuSeparator id=""MenuSep2"" title=""Удалить закладки""/>" & vbCr
28 '--------------------------
29 'Кнопки Удаления закладок
30 '------------------------
31 For i = 1 To bm.count
32 sXML = sXML & _
33 "<button id=""delbm" & i & """ " & _
34 "label=""" & bm.Item(i).Name & """ " & _
35 "onAction=""" & "delbm_onAction"" " & _
36 "imageMso=""OutlineCollapse"" " & _
37 "tag=""" & bm.Item(i).Name & """ />" & vbCr
38 Next i
39 sXML = sXML & "</menu>" & vbCr
40 '--------------------------
41 'Разделитель
42 '--------------------------
43 sXML = sXML & _
44 "<menuSeparator id=""MenuSep1"" title=""Существующие в документе закладки""/>" & vbCr
45 '--------------------------
46 'Кнопки с именами закладок
47 '--------------------------
48 If bm.count = 0 Then
49 sXML = sXML & _
50 "<button id=""NoBookmarks"" " & _
51 "label=""В документе нет ни одной закладки""" & " />" & vbCr
52 Else
53 For i = 1 To bm.count
54 sXML = sXML & _
55 "<button id=""bm" & i & """ " & _
56 "label=""" & bm.Item(i).Name & """ " & _
57 "imageMso=""FrontPageToggleBookmark"" " & _
58 "onAction=""" & "GoToBookmark"" " & _
59 "tag=""" & bm.Item(i).Name & """ />" & vbCr
60 Next i
61 End If
62 content = sXML & "</menu>" 'возвращаем значение в компонент
63 End Sub

Как видно первой создается кнопка «Обновить» и для нее назначается макрос RefreshDynMenu_OnAction, который обновляет меню.
1 Sub RefreshDynMenu_OnAction(control As IRibbonControl)
2 '
3 'Обновление динамического меню
4 '
5 CustomRibbon.Invalidate
6 End Sub

При удалении закладки меню обновляется автоматически, но не без нашего участия. Чтобы эта автоматика работала, мы при создании меню «Управление закладками» создаем кнопки, которые отвечают за удаление той или иной закладки. Имя закладки пишем в свойство tag. Удаление закладки происходит при выполнении макроса delbm_onAction
Удаление закладки из меню   Копировать код без номеров строк
1 Public Sub delbm_onAction(control As IRibbonControl)
2 '
3 'Удаление закладки при выборе ее в соответствующем меню
4 '
5 bm.Item(control.Tag).Delete
6 CustomRibbon.Invalidate
7 End Sub

Также при выполнении макроса GoToBookmark осуществляется переход к выбранной закладке.
Переход к закладке   Копировать код без номеров строк
1 Sub GoToBookmark(control As IRibbonControl)
2 '
3 'Переход к закладке
4 '
5 On Error Resume Next
6 Selection.GoTo What:=wdGoToBookmark, Name:=control.Tag
7 If Err.Number <> 0 Then
8 MsgBox "Не удалось перейти к закладке «" & control.Tag & "»", vbOKOnly
9 End If
10 End Sub

Для добавления закладки вызывается стандартный диалог работы с закладками
Добавление закладки   Копировать код без номеров строк
1 Public Sub menu_AddBookmark_onAction(control As IRibbonControl)
2 '
3 'Появление окна для добавления закладки в документ
4 '
5 Dialogs(wdDialogInsertBookmark).Show
6 CustomRibbon.Invalidate
7 End Sub

При любых действиях с закладками вызывается метод CustomRibbon.Invalidate, который обновляет содержимое ленты.
С закладками получилось все довольно просто. Теперь другая задача стоит: как сформировать динамическое меню из доступных для выполнения макросов, которые можно запустить через стандартное диалоговое окно по Alt+F8? Сразу скажу, что в черновом варианте эту задачу я уже решил. Подробности далее в публикациях.

1 коммент.:

Антон Кокин комментирует...

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