Всякий раз, когда разработчик создает очередное решение, одна из серьезных проблем, стоящих перед ним, состоит в организации интерфейса своей системы. Хороший интерфейс, - привлекательный и понятный пользователю, во многом определяет успех предлагаемого решения. Диалог с пользователем - важная часть интерфейса. Во многих случаях для организации диалога достаточно обычных диалоговых окон, открываемых в нужный момент с выдачей подходящего сообщения. Зачастую для организации диалога предпочтительнее более выразительные средства и тут незаменим Помощник (объект Assistant ), хорошо знакомый пользователям Office 2000, поскольку именно он обеспечивает диалог со справочной системой, может организовать подсказки и выдачу советов. Давайте познакомимся с объектом Assistant поближе и научимся использовать его в своих решениях. Объект Assistant, задающий Помощника, появился в предыдущей версии Office 97. В новой версии он сохранил свои основные свойства и поведение.
Вначале несколько слов о Помощнике. Идея Помощников (Мастеров, Агентов) в программировании не нова. Сегодня эта технология приобрела широкую популярность. В любом достаточно сложном приложении, в котором пользователю отводится активная роль, полезно создать некоторую совокупность Помощников пользователя. Пользователь будет выбирать, какую задачу он хочет решить в тот или иной момент, а соответствующий Помощник поможет ему на этом пути, проводя пользователя через все этапы решения задачи, снабжая необходимой информацией, информируя о возникших ошибках, позволяя сделать откат и вернуться к предыдущему этапу. В программных продуктах Microsoft, например, подобные Помощники или Мастера (Assistants, Wizards) сопровождают нас на каждом шагу, начиная с этапа инсталляции приложения. Кроме того, что Помощники предназначены для обеспечения помощи в решении некоторой конкретной задачи и могут вести диалог с пользователем, они могут обладать еще двумя важными качествами:
Assistant, я предпочитаю Rocky и позволяю себе в минуты отдыха играться с ним, заставляя его выполнять различные движения. Жаль только, что его анимация не подчиняется голосовым командам, например, "Принеси палку".В последнем предложении я не поставил запятые в обороте "по его мнению". Интеллектуальный Помощник, каковым, несомненно, является встроенная в Word система проверки правописания, тут же выдала мне соответствующую подсказку.
Помощник, встроенный в справочную систему Office 2000, и построенный на основе объекта Assistant, обладает всеми тремя качествами, - выдает справки, имеет видимый образ, и не один, и обладает интеллектуальностью. Следует отметить, что его интеллектуальные способности оставляют желать лучшего, но, несомненно, улучшились в сравнении с предыдущей версией. Он теперь, по крайней мере, понимает запросы, сделанные не только на английском языке, но и на русском.
Программист, использующий объект Assistant для собственных целей, получает Помощника с анимацией, но, конечно, не обладающего никакой интеллектуальностью. Добавить интеллектуальность дело довольно не простое, хотя и возможное.
Начнем рассмотрение объекта Assistant и связанных с ним объектов, с формального изучения его свойств. Структура объекта Assistant довольно проста:
(рис 7.1) Структура объекта AssistantВ объект Assistant вложен объект . В свою очередь в объект вложены две коллекции - CheckBoxes (кнопки выбора) и Labels (метки) с элементами классов CheckBox и Label соответственно. Обратите внимание, коллекции называются именно так и не имеют приставки , как показано на рисунке, взятом из документации, и не изменившимся в новой версии.
Объект - это диалоговое окно специального вида. При его проектировании в нем можно создать до пяти элементов каждой коллекции. Метки задают текстовые сообщения, адресованные пользователю. Обычно они имеют вид нумерованного списка или списка-бюллетеня и определяют порядок действий пользователя или возможные причины ошибки. Вторая коллекция с кнопками выбора позволяет пользователю сделать тот или иной выбор. Анализируя полученную информацию, программа может выполнять действия, предписанные выбором пользователя.
Как это мы уже не раз делали, зададим сводку основных свойств таблицей:
| Свойство | Назначение |
|---|---|
Animation |
Возвращает или устанавливает тип анимации образа Assistant. Если свойство применяется к объекту Assistant, то он "оживает" сразу же при включении. Если же оно применяется к объекту , то анимация возникает только при появлении баллончика. Может быть значением одной из 34-х констант типа MsoAnimationType. |
AssistWithAlerts, AssistWithHelp, AssistWithWizards |
Булевы свойства, имеющие значение True, если Assistant используется для выдачи предупреждений (заменяя окно MsgBox ), в ответ на нажатие клавиши F1 (Help), и при выдаче справочных сообщений, когда работают различные Мастера |
BalloonError |
Возвращает значение, указывающее на тип последней ошибки объекта . |
FeatureTips |
Булево свойство, которому дается значение True, когда желательно получать советы о наиболее эффективных способах использования свойств приложения. |
FileName |
Возвращает или устанавливает имя файла, содержащего графический образ Assistant. Файл имеет уточнение act, например файл со скрепкой - Clippit.act. Заметим, что могут быть заданы только стандартные для Office 97 файлы. Собственные образы задавать нельзя, но число стандартных образов расширяется. |
GuessHelp |
Это именно то булево свойство, установив значение которого, равным True, Вы получаете |
HighPriorityTips, KeyboardShortcutTips, MouseTips |
Советы имеют разный приоритет. Если свойство имеет значение True, то будут выдаваться советы только наивысшего приоритета. Следующие два булевы свойства включают возможность выдачи информации о горячих клавишах и наиболее эффективном использовании мыши. |
NewBalloon |
Является по существу центральным свойством, поскольку позволяет создать новый объект . После чего можно нужным образом определить свойства этого объекта. Напомним, что баллончик определяет основные возможности Assistant. |
Sounds |
Булево свойство, включающее звук в процессе анимации. |
TipOfDay |
Булево свойство, включающее или отключающее "Совет дня" при открытии приложения Office 97. |
Visible |
Делает видимым или невидимым объект Assistant, сворачивая его в кнопку на панели инструментов. |
Новые свойства в Office 2000 |
Назначение |
On |
Новое булево свойство позволяет включать и выключать Помощника. |
В Office 2000 не произошло изменений в методах объекта Assistant. Он по-прежнему имеет следующие методы: StartWizard, ActivateWizard, EndWizard, Help, Move и ResetTips. Методы этого объекта используются реже, чем свойства и я ограничусь их кратким описанием.
Методы StartWizard, ActivateWizard, EndWizard применяются при создании пользовательских Мастеров. Первым должен быть запущен метод StartWizard, возвращающий идентификатор (длинное целое) Помощника. Этот идентификатор затем используется в методах ActivateWizard и EndWizard, соответственно активизирующих и деактивирующих Помощника.
Метод Help выводит стандартное сообщение Помощника справочной системы Office 2000 с заголовком "What would you like to do?"
Метод Move перемещает Помощника в указанную параметрами left и top позицию на экране
Метод ResetTips очищает журнал советов, в связи с чем могут вновь появляться уже данные советы.
В заключение рассказа о свойствах и методах объекта Assistant приведем пример, в котором поменяем образ объекта Assistant и некоторые его свойства:
Public Sub ChooseAss() With Assistant Debug.Print .FileName 'Задаем образ Помощника '.FileName = "dot.acs" .FileName = "Offcat.acs" '.FileName = "Rocky.acs" 'Его анимационное поведение .Animation = msoAnimationGreeting .Animation = msoAnimationGetAttentionMinor 'Другие свойства .AssistWithHelp = True .FeatureTips = True .GuessHelp = True .HighPriorityTips = True .Visible = True End With End Sub
Взгляните на кошечку, которая будет сопровождать теперь выдачу советов и справок. Задавая свойство Animation, можно подобрать ее поведение, отвечающее данному моменту.
(рис 7.2) "Мурка" в роли Помощника (объекта Assistant)Обратите внимание, - на вопрос, заданный на естественном русском языке, выдана точная справка. Этого не было в предыдущей версии.
Можно изменить свойства объекта Assistant, но в каждый момент существует только один такой объект. C ним можно связать произвольное число объектов , которые я называю баллончиками. Поясним происхождение термина. Реплики рисованных персонажей комиксов или карикатур художники нередко помещают в кружок - "баллончик", выдуваемый изо рта.
У объекта Assistant нет коллекции объектов (а жаль), но можно создать необходимое число переменных этого класса или массив из таких объектов. Вот пример:
Public Sub Balls() Dim i As Integer 'Создание объектов Balloons Dim FirstBall As Balloon, LastBall As Balloon Dim ArrOfBall(3) As Balloon With Assistant .FileName = "OffCat.acs" Set FirstBall = .NewBalloon FirstBall.Show .FileName = "Rocky.acs" Set LastBall = .NewBalloon LastBall.Show For i = 1 To 3 Set ArrOfBall(i) = .NewBalloon ArrOfBall(i).Show Next i FirstBall.Show End With End Sub
Здесь созданы две переменные и массив из трех элементов класса . По ходу дела внешний вид объекта Assistant меняется, но все баллончики одинаковы, в момент рождения они пусты и имеют единственную кнопку "ОК". Рассмотрим, как можно наполнить содержанием эти объекты и задать их свойства.
Объекты предназначены для ведения диалога с пользователем и фактически являются специальным видом диалоговых окон. Любое диалоговое окно, а значит и объект может быть модальным и немодальным. Из модальных окон нельзя выйти, не закончив диалог. Обычно, для этого нужно щелкнуть одну из кнопок этого окна - Ok или Cancel. В модальном объекте эти кнопки, как правило, присутствуют, но их наличие не является обязательным. Если щелкнуть любую кнопку в функций, позволяющий организовать реакцию на выбор, сделанный пользователем в немодальном окне.
Объект имеет свойство Mode с тремя возможными значениями:
MsoModeModal - в этом случае диалог с объектом Balloon является модальным. Его обычно используют для вывода предупреждений, требующих особого внимания или получения ответа от пользователя, без которого дальнейшая работа не может быть продолжена.MsoModeModeless - в этом случае окно становится немодальным и оно может оставаться открытым, в то время как продолжается работа над приложением в других его окнах. Такие объекты удобны, например, при выдаче справочной информации, которая должна быть все время под рукой.MsoModeAutoDown - задает специальный вид С двумя свойствами этого объекта: Animation и Mode мы уже знакомы. Первое из них задает анимацию объекта Assistant при вызове его метода Show, в тот момент, когда показывается объект . Рассмотрим подробнее другие свойства
Heading - позволяет прочесть или установить строку, задающую текст заголовка.Text - На вершине объекта Balloon сразу после заголовка может появляться некоторый текст. Его и устанавливает свойство Text. Оба элемента являются необязательными. Заметьте, что Heading и Text могут включать и графику. Последняя задается строкой, имеющей следующий синтаксис: {<type> <location> [<factor>]}. Первый параметр задает тип графического файла (bmp или Icon - Слева от заголовка можно добавить специальный значок для привлечения внимания. Возможные значки задаются следующими константами: msoIconAlert, msoIconNone, или msoIconTip.Button - Внутрь баллончика можно поместить некоторое количество кнопок заранее предустановленного типа. К ним, конечно, относятся кнопки: Ok, Cancel, Next, Close, Это не все свойства объекта . Есть еще несколько важных для понимания свойств, но мы расскажем о них чуть позднее. А сейчас небольшой пример конструирования объекта с некоторыми из рассмотренных свойств:
Public Sub OneBall()
Dim Text1 As String, Text2 As String, Text3 As String
Dim Text4 As String, Text5 As String
Dim myPath As String
myPath = ActiveDocument.Path
'Формирование свойства Text
Text1 = "Хочешь знать, как перевезти с берега на берег"
'Вставка графики в середину текста
Text2 ="{wmf " myPath "\wolf.wmf}"; " Волка," vbCrLf
Text3 = "{wmf " myPath "\goat.wmf}" " Козу" " И "
Text4 = "{wmf " myPath "\cabbage.wmf}" " Капусту" vbCrLf vbCrLf
Text5 = "Соблюдая 3 правила?"
Dim FirstBall As Balloon
Set FirstBall = Assistant.NewBalloon
With FirstBall
.Heading = "Волк, Коза и Капуста"
.Icon = msoIconAlert
.Text = Text1 Text2 Text3 Text4 Text5
.Button = msoButtonSetYesNo
.Show
End With
End Sub
Вот как выглядит это диалоговое окно баллончика с картинками, вставленными в текст:
(рис 7.3) Объект Balloon с заданными свойствамиЗаметьте, следует быть внимательным при задании свойства Text, включающего картинки. При наличии ошибок диалоговое окно не будет открыто, но сообщений об ошибке не появится.
У объекта есть две коллекции - Labels с элементами Label и CheckBoxes с элементами CheckBox. В каждой из коллекций может содержаться не более пяти элементов. Элементами Labels являются метки, для которых, как правило, задается свойство Text, определяющее метку. Метки имеют тип, задающий их оформление. Все метки должны быть одного типа, так что настала пора рассказать еще об одном свойстве объекта . Тип меток задается свойством BalloonType объекта и имеет три возможных значения:
Списки первых двух типов позволяют проинформировать пользователя о тех или иных предоставляемых возможностях. Конечно, для этой цели можно также использовать свойство Text самого объекта , но метки удобнее, поскольку информация предоставляется в структурированном виде.
Третий тип меток используется для получения информации от пользователя, который выбирает одну из нескольких (до пяти) возможностей, щелчком соответствующей кнопки. Метод Show, возвращающий номер нажатой кнопки, позволяет узнать, какая кнопка была выбрана. Тем самым появляется возможность организовать дальнейшие действия в зависимости от сделанного выбора.
Вместе или вместо меток третьего типа можно использовать свойство Button, благодаря которому в баллончике также появляются кнопки, а метод Show и в этом случае возвращает номер нажатой кнопки. Кнопки со стандартными именами, задаваемые Button, часто бывают полезными, но, конечно, не всегда приемлемы. Благодаря свойству Text у кнопок - меток, можно задать "свои" кнопки со своими именами.
Совместное использование меток третьего типа и свойства Button стало теперь возможным - я приведу пример такого использования.
Флажки (кнопки выбора), задаваемые элементами CheckBox, используются для той же цели, что и кнопки - они позволяют определить выбор пользователя. Существенное отличие состоит в том, что пользователь может выбрать не одну из предоставляемых ему возможностей, а несколько, взводя соответствующие флажки. Когда флажок взведен, то свойство Checked соответствующего элемента из коллекции CheckBoxes получает значение True. Каждое из этих свойств можно затем проверить и использовать при выборе последующих действий в программе.
Приведем пример, в котором действуют два объекта
Public Sub CheckingHobbies() Dim FirstBall As Balloon, LastBall As Balloon Dim i As Integer 'Первый баллончик выясняет увлечения Assistant.FileName = "Rocky.acs" Set FirstBall = Assistant.NewBalloon With FirstBall .Heading = "Ваши увлечения" .Checkboxes(1).Text = "Футбол" .Checkboxes(2).Text = "Теннис" .Checkboxes(3).Text = "Шахматы" .Checkboxes(4).Text = "Плавание" .Checkboxes(5).Text = "Горные лыжи" .Show End With 'Второй баллончик уведомляет об увлечениях Assistant.FileName = "OffCat.acs" Set LastBall = Assistant.NewBalloon Dim Count As Integer Count = 0 With LastBall .Heading = "Ваши увлечения" .BalloonType = msoBalloonTypeBullets For i = 1 To 5 If FirstBall.Checkboxes(i).Checked Then Count = Count + 1 .Labels(Count).Text = FirstBall.Checkboxes(i).Text End If Next i If Count > 0 Then .Text = "Вы любите:" Else .Text = "Вы ничего не любите" End If .Show End With End Sub
А теперь взгляните на картинки, которые будут появляться в процессе выполнения этой процедуры.

(рис 7.5) Объект Balloon выясняет увлечения(рис 7.4) Объект Balloon уведомляет об увлеченияхФлажки и метки могут применяться одновременно, хотя вряд ли в этом есть смысл. Если пользователь должен сделать единственный выбор - применяйте метки, в случае множественного выбора - используйте флажки. В следующем примере я слегка модифицировал задачу выбора увлечения для того, чтобы продемонстрировать возможности анализа результата выбора, используя значение, возвращаемое методом Show:
Public Sub CheckingHobbies1()
'В данном примере для задания предпочтений используются метки
'и возможности анализа результата работы метода Show
Dim FirstBall As Balloon, LastBall As Balloon
Dim i As Integer
Dim Answer As MsoBalloonButtonType
'баллончик выясняет увлечения
Set FirstBall = Assistant.NewBalloon
With FirstBall
.Heading = "Ваш любимый вид спорта?"
.BalloonType = msoBalloonTypeButtons
.Labels(1).Text = "Футбол"
.Labels(2).Text = "Теннис"
.Labels(3).Text = "Шахматы"
.Labels(4).Text = "Плавание"
.Labels(5).Text = "Горные лыжи"
.Button = msoButtonSetBackNextClose
Answer = .Show
End With
'Анализ пользовательского выбора
Select Case Answer
Case 1
MsgBox ("Футбол - любимая игра миллионов.")
Case 2
MsgBox ("Теннис - красивый вид спорта.")
Case 3
MsgBox ("Шахматы - игра мыслителей.")
Case 4
MsgBox ("Плавание - нет ничего полезнее.")
Case 5
MsgBox ("Горные лыжи - спорт избранных.")
Case msoBalloonButtonBack
MsgBox ("Показать предыдущий список игр?")
Case msoBalloonButtonNext
MsgBox ("Показать следующий список игр?")
Case Else
MsgBox ("Вы совсем не спортсмен!")
End Select
End Sub
В нашем диалоговом окне три Answer, получающей результат метода Show, и на то, как она используется в Select. На следующем рисунке показан момент выбора пользователем одной из кнопок:
(рис 7.6) Организация выбора одной из многих возможностей
Процедура обратного вызова ( процедуру программиста. Естественно, что для процедур система определяет форму их вызова - имя процедуры, число и типы формальных параметров (но не их имена, которые могут быть произвольными).
процедуры необходимы при немодальном диалоге, организованном объектами . Система вызывает процедуру, передавая ей в качестве одного из параметров номер кнопки, которую выбрал пользователь в окне немодального диалога. Напомним, что при модальном диалоге этот номер возвращает метод Show. Организовать модальный диалог достаточно просто, а с не модальным всегда возникают некоторые сложности. В данном случае они преодолеваются за счет использования процедуры обратного вызова. Эту процедуру пишет сам программист, но вызывает ее система, передавая в процедуру номер кнопки, известный ей в момент вызова. Используя полученный параметр, конечно, нетрудно написать тело самой процедуры так, чтобы она правильно реагировала на выбор, сделанный пользователем.
Теперь, когда общая идея понятна, уточним некоторые детали. Прежде всего заметим, что объект имеет еще одно ранее не описанное важное свойство . Значением этого свойства является строка, задающая имя процедуры. Заметьте, что в данном случае Вы сами определяете имя процедуры и сообщаете его системе. Но число параметров и их типы все-таки фиксированы. Процедура, имя которой Вы указали в свойстве , должна иметь следующий синтаксис:
< имя процедуры> (Ball As Balloon, NumberOfButton As Long, iPriv As Long)
Повторяем, имена формальных параметров могут быть произвольными. Важно только понимать, что первый параметр задает объект , вызвавший немодальный диалог, второй - номер кнопки, выбранной пользователем (это может быть системная кнопка или кнопка, определенная меткой). Третий параметр, как правило, не используется в теле процедуры. Он необходим системному Wizard (Мастеру), работающему с объектом Assistant. Конечно, если Вы пишите свой собственный пользовательский Wizard, то этот параметр понадобится. В соответствии с этим синтаксисом необходимо написать
Public Sub UnModal()
Dim FirstBall As Balloon
Dim Text1 As String, Text2 As String
Dim Text3 As String, Text4 As String
Dim myPath As String
myPath = ActiveDocument.Path
'Формирование свойства Text
'Вставка графики в начало текста
Text1 = "{wmf " myPath " /Cabbage.wmf}"
Text2 = "Вы уже перевезли на другой берег "
Text3 = "Волка и Козу! Осталось съездить за капустой."
Text4 = "Отправляясь назад, Вы возьмете с собой: "
Set FirstBall = Assistant.NewBalloon
With FirstBall
.Mode = msoModeModeless
.Callback = "Answer"
.Icon = msoIconAlert
.Heading = "ВОЛК, КОЗА И КАПУСТА"
.Text = Text1 Text2 Text3 Text4
.BalloonType = msoBalloonTypeButtons
.Button = msoButtonSetNone
.Labels(1).Text = "Волка"
.Labels(2).Text = "Козу"
.Labels(3).Text = "Капусту"
.Labels(4).Text = "Никого"
.Show
End With
End Sub
Public Sub Answer(Ball As Balloon, Count As Long, iPriv As Long)
'Анализ принятого решения
Select Case Count
Case 1
Call Explain("Это возможное, но не лучшее решение!")
Case 2
Call Explain("Это правильно!")
Case 3
Call Explain("Это невозможно!")
Case 4
Call Explain("Ужасная трагедия: Волк съест Козу!")
Case Else
'Пропускаем
End Select
' При желании можно закрыть окно диалога
Ball.Close
End Sub
Public Sub Explain(Txt As String)
Dim ExplainBall As Balloon
Set ExplainBall = Assistant.NewBalloon
With ExplainBall
.Heading = "ВОЛК, КОЗА И КАПУСТА"
.Text = Txt
.Show
End With
End Sub
Здесь, как Вы видите, вместо переменной Answer появилась процедура Answer, которая и определяет реакцию на выбор пользователя. Заметьте, что в конце этой процедуры метод Close закрывает диалог. Если этого не делать, то после выдачи сообщения о неудачном решении, можно вернуться в окно немодального диалога и изменить свой выбор! В этом сила немодального диалога. Тем не менее, следует быть весьма аккуратным и во время закрыть окно немодального диалога. В противном случае это окно будет постоянно (до перезагрузки компьютера) сопровождать Помощника на экране. Сложность состоит в том, что локальная переменная, определяющая объект , может прекратить свое существование, а немодальное окно будет продолжать существовать. Поэтому лучше такие переменные определять как глобальные переменные модуля, тогда метод Close может быть вызван в любой из процедур, завершающих работу приложения.
Несколько слов о том, когда нужен такой "несерьезный" интерфейс с анимацией и разными актерами, выступающими в роли помощника. Он, на наш взгляд, подходит для пользователей и приложений определенного типа. Прежде всего, речь может идти об играх и обучающих системах.
В этих серьезных приложениях, ориентированных на юных или начинающих пользователей, такой интерфейс позволяет вести пользователя шаг за шагом по всей системе, демонстрируя ее возможности. В предыдущей лекции в качестве примера "документа-обложки" я рассмотрел создание известной игры для младших школьников "Волк, Коза и Капуста". В этой реализации не использовался объект Assistant, для того чтобы выдержать чистоту эксперимента и иметь возможность экспорта полученной реализации в чистый VB, создав затем исполняемый файл или ActiveX. При подготовке этой лекции я добавил к этой игре объект Assistant, поручив ему вести весь диалог по ходу игры, сообщать о правилах игры, давать советы о действии, которое следует выполнить, уведомлять о неудачах, возникающих при неверном ходе.
Не возникло никаких принципиальных трудностей с добавлением объекта Assistant к уже имеющейся реализации игры. Понятно, что пришлось слегка изменить интерфейс, - в игре появились еще два визуальных объекта. Одним из них является Помощник, роль которого играет Рокки, вторым - остров, где живет Рокки. Чтобы дать представление о том, как теперь выглядит интерфейс игры, как выглядит диалог, приведу пару рисунков, отображающих некоторые моменты общения с Помощником "Рокки" в процессе игры:
(рис 7.7) Приветствие Рокки в момент начала игрыНа следующих двух рисунках Рокки рассказывает о правилах игры и дает совет по поводу очередного хода:

(рис 7.9) Рокки сообщает о правилах игры(рис 7.8) Рокки дает совет Я уже сказал, что никаких серьезных трудностей не возникло при введении Помощника для организации диалога. Достаточно просто, заменить сообщение, выдаваемое функцией MsgBox на сообщение, выдаваемое Помощником, используя его баллончики. Но здесь есть одно "но"! При работе с Помощником появляется больше возможностей и, поневоле, хочется организовать более живой и интересный диалог - использовать картинки, дать пользователю возможность выбора, проявить интеллект и предлагать подсказки в возникающих ситуациях.
О том, как в сообщения, появляющиеся в баллончиках, включать рисунки, было уже рассказано в этой лекции. Было также достаточно подробно рассказано и о том, как дать возможность пользователю выбирать и как затем анализировать его выбор. Поэтому давайте поговорим об "интеллекте" Помощника. Это трудная задача. Но в нашем простом примере она решаема. Давайте возложим на Помощника обязанность не только следить за соблюдением правил игры и выдавать сообщения при их нарушениях, но и пусть он дает советы, подсказывая, какой ход следует сделать в той или иной ситуации.
Общий подход решения последней задачи понятен, - необходимо следить за состоянием системы, в нашем случае игры. Когда пользователь обращается к Помощнику за советом, то, зная текущее состояние S, можно попытаться найти разумное решение R. Иногда, как в нашей простой игре, существует точное решение и, зная S, можно однозначно определить R, как функцию от S. В тех случаях, когда для поиска решения необходим перебор вариантов, проведение сложных вычислений или просто квалификация пользователя невысока, советы Помощника могут быть весьма ценными. Интеллектуальные Помощники незаменимы в играх и обучающих системах. Конечно, в серьезных задачах квалифицированный пользователь может принимать лучшие решения, но и там подсказки Помощника могут быть полезными.
В игре "Волк, Коза и Капуста" достаточно было ввести одну переменную, следящую за состоянием игры, изменять ее значение по ходу игры, и при обращении к Помощнику за советом, выдавать подсказку на основе анализа значения этой переменной.
Вот какие изменения пришлось сделать в реализации игры. Во-первых, я добавил новый модуль Dialogs, в который поместил процедуры и константы, необходимые для ведения диалога. Некоторые изменения пришлось ввести и в текст модуля WGC. В раздел объявлений этого модуля добавлены следующие строчки:
Public StateOfPlay As String 'Состояние игры Public Answer As MsoBalloonButtonType 'Выбор пользователя 'Другие общие параметры Public WidthOfRiver 'Ширина реки Public MyPath As String 'каталог, хранящий исходный документ и другие файлы игры
Изменения внесены и в процедуру инициализации:
Public Sub InitialStates() 'Задаем начальные состояния объектов и их образов StateOfMan = "LeftBank" StateOfWolf = "LeftBank" StateOfGoat = "LeftBank" StateOfCabbage = "LeftBank" StateOfBoat = "LeftBank" CountInBoat = 0 StateOfPlay = "InitState" 'Инициализация объектов формы With WGCForm .Man.Top = .LeftBank.Top + 15: .Man.Left = .LeftBank.Left + 10 .Man.Visible = True .Wolf.Top = .LeftBank.Top + 80: .Wolf.Left = .LeftBank.Left + 10 .Wolf.Visible = True .Goat.Top = .LeftBank.Top + 140: .Goat.Left = .LeftBank.Left + 10 .Goat.Visible = True .Cabbage.Top = .LeftBank.Top + 200: .Cabbage.Left = .LeftBank.Left + 10 .Cabbage.Visible = True .Boat.Top = .LeftBank.Top + 130: .Boat.Left = .LeftBank.Left + .LeftBank.Width .Boat.Visible = True WidthOfRiver = .Width - .LeftBank.Width - .RightBank.Width _ - .Boat.Width 'Поместить Рокки на остров Assistant.FileName = "Rocky.acs" 'Debug.Print Assistant.Left, Assistant.Top Assistant.Move XLeft:=.Left + .Island.Left + .Island.Width / 2, _ YTop:=.Top + .Island.Top + .Island.Height - 10 Assistant.Animation = msoAnimationCharacterSuccessMajor 'Assistant.AssistWithAlerts = False 'Assistant.AssistWithHelp = False 'Debug.Print Assistant.Left, Assistant.Top End With 'Путь к каталогу MyPath = ActiveDocument.Path 'Сформировать баллончики - диалоговые окна Call FormBalloons 'Инициализировать диалог Call Dialog1 End Sub
Я улучшил инициализацию, задав относительное расположение объектов, что позволяет менять размеры игрового поля, сохраняя взаимное расположение объектов. Наиболее серьезные дополнения выделены цветом фона. Как видите, здесь вводится объект Assistant и, используя метод Move, он помещается на свое место - остров, при этом задается его анимационное поведение. Далее вызываются две процедуры модуля Dialogs. В первой из них формируются объекты - баллончики разного типа, во второй - инициализируется начальный диалог Помощника, приглашающий к началу игры.
Других изменений в процедурах этого модуля не было, если не считать замены вызовов функции MsgBox на вызовы соответствующих функций модуля Dialogs, как, например, в процедуре TestingState:
Public Sub TestingState() 'Тестирование состояний With WGCForm 'Волк съел козу If (StateOfWolf = StateOfGoat) And (StateOfWolf < > StateOfMan) Then .Goat.Visible = False 'MsgBox Prompt:=Mes1 + vbCrLf + Mes3, Buttons:=vbCritical + vbOKOnly, Title:=Mes13 Call Dialog5 InitialStates End If 'Коза съела капусту If (StateOfCabbage = StateOfGoat) And (StateOfCabbage < < StateOfMan) Then .Cabbage.Visible = False 'MsgBox Prompt:=Mes1 + vbCrLf + Mes4, Buttons:=vbCritical + vbOKOnly, Title:=Mes13 Call Dialog6 InitialStates End If 'Слишком много пассажиров! If (CountInBoat > 2) Then If StateOfMan = "InBoat" Then .Man.Visible = False If StateOfWolf = "InBoat" Then .Wolf.Visible = False If StateOfGoat = "InBoat" Then .Goat.Visible = False If StateOfCabbage = "InBoat" Then .Cabbage.Visible = False 'MsgBox Prompt:=Mes1 + vbCrLf + Mes5, Buttons:=vbCritical + vbOKOnly, Title:=Mes13 Call Dialog7 InitialStates End If 'Конец игры - Все пассажиры собрались на правом берегу If (StateOfMan = "RightBank") And (StateOfWolf = "RightBank") And _ (StateOfGoat = "RightBank") And (StateOfCabbage = "RightBank") Then 'MsgBox Prompt:=Mes2 + vbCrLf + Mes6, Buttons:=vbExclamation + vbOKOnly, Title:=Mes14 Call Dialog8 End If End With End Sub
Приведем теперь текст модуля Dialogs:
Option Explicit
'Константы для организации диалогов
Public Const Mes1 = "Ужасно, нелепо и грустно! "
Public Const Mes2 = "Прекрасно, как славно,отлично! "
Public Const Mes3 = " Волк съел козу! "
Public Const Mes4 = " Коза съела капусту! "
Public Const Mes5 = " Лодка перевернулась и все утонули! "
Public Const Mes6 = " Вам это удалось! Все переправились!"
Public Const Mes7 = " Не удалось дотащить "
Public Const Mes8 = " Человека! "
Public Const Mes9 = " Волка! "
Public Const Mes10 = " Козу! "
Public Const Mes11 = " Капусту! "
Public Const Mes12 = " Повторите попытку! "
Public Const Mes13 = " Беда!"
Public Const Mes14 = " Радость! "
Public Const Mes15 = " Лодку! "
Public Const Txt1 = "Привет! Я Рокки." vbCrLf _
"Щелкни по острову, если захочешь поговорить со мной."
Public Const Txt2 = "Волк, Коза и Капуста!"
'Public Const Txt3 = "{wmf " MyPath "\goat.wmf}"
'Public Const Txt4 = "{wmf " MyPath "\cabbage.wmf}"
Public Const Txt5 = ""
'Массив баллончиков - диалоговых окон Рокки
Public RockyBalloons(1 To 10) As Balloon
Public Sub Dialog()
'Начальный диалог при открытии игры
'Анализ состояния игры
Select Case StateOfPlay
Case "InitState"
Call Dialog1
Case "State1"
Call Dialog2
Case "State2"
Call Dialog9
Case "StateFinish"
Call Dialog10
Case Else
End Select
End Sub
Public Sub OneBall()
Dim Text1 As String, Text2 As String, Text3 As String
Dim Text4 As String, Text5 As String
Dim MyPath As String
MyPath = ActiveDocument.Path
'Формирование свойства Text
Text1 = "Хочешь знать, как перевезти с берега на берег"
' Вставка графики в середину текста
Text2 = "{wmf " MyPath "\wolf.wmf}" " Волка," vbCrLf
Text3 = "{wmf " MyPath "\goat.wmf}" " Козу" " И "
Text4 = "{wmf " MyPath "\cabbage.wmf}" " Капусту?" vbCrLf vbCrLf
'Text5 = "Соблюдая 3 правила?"
Dim FirstBall As Balloon
Set FirstBall = Assistant.NewBalloon
With FirstBall
.Heading = "Волк, Коза и Капуста"
.Icon = msoIconAlert
.Text = Text1 Text2 Text3 Text4
.Button = msoButtonSetYesNo
.Show
End With
End Sub
Public Sub FormBalloons()
'Инициализация баллончиков
Dim I As Integer
For I = 1 To 10
Set RockyBalloons(I) = Assistant.NewBalloon
RockyBalloons(I).Heading = Txt2
RockyBalloons(I).Icon = msoIconAlertInfo
Next I
FormBall1
FormBall2
FormBall3
FormBall4
FormBall5
FormBall6
FormBall7
'FormBall8
End Sub
Public Sub FormBall1()
'Формирование свойства Text - знакомство
With RockyBalloons(1)
.Text = Txt1
.Button = msoButtonSetOK
End With
End Sub
Public Sub Dialog1()
RockyBalloons(1).Show
StateOfPlay = "State1" 'Игра началась
End Sub
Public Sub FormBall2()
Dim Text1 As String, Text2 As String, Text3 As String
Dim Text4 As String, Text5 As String
'Формирование свойства Text
Text1 = "Нужно срочно перевезти с берега на берег"
' Вставка графики в середину текста
Text2 = "{wmf " MyPath "\wolf.wmf}" " Волка," vbCrLf
Text3 = "{wmf " MyPath "\goat.wmf}" " Козу" " И "
Text4 = "{wmf " MyPath "\cabbage.wmf}" " Капусту?" vbCrLf vbCrLf
Text5 = "Хочешь знать правила игры?"
With RockyBalloons(2)
.Text = Text1 Text2 Text3 Text4 Text5
.Button = msoButtonSetYesNo
End With
End Sub
Public Sub Dialog2()
Answer = RockyBalloons(2).Show
Select Case Answer
Case msoBalloonButtonYes 'Нажата кнопка Yes
'Показать правила игры
Call Dialog3
Case msoBalloonButtonNo 'Нажата кнопка No
'Предложить начать играть
Call Dialog4
End Select
End Sub
Public Sub FormBall3()
Dim Text1 As String, Text2 As String, Text3 As String
Dim Text4 As String, Text5 As String
'Формирование переменных Text
Text1 = "В лодке, используемой для перевоза," _
" может находиться не более двух путников" _
" (человек, волк, коза и капуста - это путники)." vbCrLf _
"При попытке посадить большее число путников лодка перевернется. "
Text2 = "Если оставить в лодке или на берегу волка и козу без присмотра человека," _
vbCrLf "то волк немедленно съест козу."
Text3 = "Если оставить в лодке или на берегу капусту и козу без присмотра человека," _
vbCrLf "то коза немедленно съест капусту."
Text4 = "Без человека лодка не может переплыть на другой берег."
Text5 = "Начинайте играть! Желаю успеха!"
With RockyBalloons(3)
.BalloonType = msoBalloonTypeNumbers
.Labels(1).Text = Text1
.Labels(2).Text = Text2
.Labels(3).Text = Text3
.Labels(4).Text = Text4
.Labels(5).Text = Text5
End With
End Sub
Public Sub Dialog3()
RockyBalloons(3).Show
StateOfPlay = "State2" 'Правила заданы
End Sub
Public Sub FormBall4()
RockyBalloons(4).Text = "Начинайте играть! Желаю успеха!"
End Sub
Public Sub Dialog4()
RockyBalloons(4).Show
StateOfPlay = "State2" 'Правила заданы
End Sub
Public Sub FormBall5()
RockyBalloons(5).Icon = msoIconAlertCritical
End Sub
Public Sub Dialog5()
RockyBalloons(5).Text = Mes1 + vbCrLf + Mes3
RockyBalloons(5).Show
StateOfPlay = "State1" 'Начало игры
End Sub
Public Sub Dialog6()
RockyBalloons(5).Text = Mes1 + vbCrLf + Mes4
RockyBalloons(5).Show
StateOfPlay = "State1" 'Начало игры
End Sub
Public Sub Dialog7()
RockyBalloons(5).Text = Mes1 + vbCrLf + Mes5
RockyBalloons(5).Show
StateOfPlay = "State1" 'Начало игры
End Sub
Public Sub FormBall6()
RockyBalloons(6).Icon = msoIconAlert
RockyBalloons(6).Text = Mes2 + vbCrLf + Mes6
End Sub
Public Sub Dialog8()
RockyBalloons(6).Show
StateOfPlay = "StateFinish" 'Конец игры
End Sub
Public Sub Dialog9()
'Совет!
'Rule1: Если волк и коза на одном берегу, то увези козу.
'Rule2: Если капуста и коза на одном берегу, то увези капусту.
If (StateOfWolf = StateOfGoat) Then
RockyBalloons(7).Text = "Увези козу!"
ElseIf (StateOfCabbage = StateOfGoat) Then
RockyBalloons(7).Text = "Увези капусту!"
Else
RockyBalloons(7).Text = "Тут моя помощь не нужна!"
End If
RockyBalloons(7).Show
End Sub
Public Sub FormBall7()
RockyBalloons(7).Icon = msoIconTip
End Sub
Public Sub Dialog10()
RockyBalloons(6).Text = "Приходите, поиграем еще раз! Рокки будет ждать."
RockyBalloons(6).Show
StateOfPlay = "StateFinish" 'Конец игры
End Sub
Я не буду комментировать процедуры этого модуля. Все что нужно было сказать, уже сказано. Отмечу только процедуру Dialog9, которая вызывается, когда Рокки должен дать совет. Заметьте, его интеллектуальность определяется двумя правилами типа "если… то". Если не выполняются условия ни одного из этих правил, то Рокки полагает, что ситуация очень простая и его советы не нужны, поскольку можно принимать любое решение, допустимое правилами игры.
На этом мы и закончим разговор об организации диалогов с использованием возможностей объекта Assistant.
Всякий раз, когда разработчик создает очередное решение, одна из серьезных проблем, стоящих перед ним, состоит в организации интерфейса своей системы. Хороший интерфейс, - привлекательный и понятный пользователю, во многом определяет успех предлагаемого решения. Диалог с пользователем - важная часть интерфейса. Во многих случаях для организации диалога достаточно обычных диалоговых окон, открываемых в нужный момент с выдачей подходящего сообщения. Зачастую для организации диалога предпочтительнее более выразительные средства и тут незаменим Помощник (объект Assistant ), хорошо знакомый пользователям Office 2000, поскольку именно он обеспечивает диалог со справочной системой, может организовать подсказки и выдачу советов. Давайте познакомимся с объектом Assistant поближе и научимся использовать его в своих решениях. Объект Assistant, задающий Помощника, появился в предыдущей версии Office 97. В новой версии он сохранил свои основные свойства и поведение.
Вначале несколько слов о Помощнике. Идея Помощников (Мастеров, Агентов) в программировании не нова. Сегодня эта технология приобрела широкую популярность. В любом достаточно сложном приложении, в котором пользователю отводится активная роль, полезно создать некоторую совокупность Помощников пользователя. Пользователь будет выбирать, какую задачу он хочет решить в тот или иной момент, а соответствующий Помощник поможет ему на этом пути, проводя пользователя через все этапы решения задачи, снабжая необходимой информацией, информируя о возникших ошибках, позволяя сделать откат и вернуться к предыдущему этапу. В программных продуктах Microsoft, например, подобные Помощники или Мастера (Assistants, Wizards) сопровождают нас на каждом шагу, начиная с этапа инсталляции приложения. Кроме того, что Помощники предназначены для обеспечения помощи в решении некоторой конкретной задачи и могут вести диалог с пользователем, они могут обладать еще двумя важными качествами:
Assistant, я предпочитаю Rocky и позволяю себе в минуты отдыха играться с ним, заставляя его выполнять различные движения. Жаль только, что его анимация не подчиняется голосовым командам, например, "Принеси палку".В последнем предложении я не поставил запятые в обороте "по его мнению". Интеллектуальный Помощник, каковым, несомненно, является встроенная в Word система проверки правописания, тут же выдала мне соответствующую подсказку.
Помощник, встроенный в справочную систему Office 2000, и построенный на основе объекта Assistant, обладает всеми тремя качествами, - выдает справки, имеет видимый образ, и не один, и обладает интеллектуальностью. Следует отметить, что его интеллектуальные способности оставляют желать лучшего, но, несомненно, улучшились в сравнении с предыдущей версией. Он теперь, по крайней мере, понимает запросы, сделанные не только на английском языке, но и на русском.
Программист, использующий объект Assistant для собственных целей, получает Помощника с анимацией, но, конечно, не обладающего никакой интеллектуальностью. Добавить интеллектуальность дело довольно не простое, хотя и возможное.
Начнем рассмотрение объекта Assistant и связанных с ним объектов, с формального изучения его свойств. Структура объекта Assistant довольно проста:
(рис 7.1) Структура объекта AssistantВ объект Assistant вложен объект . В свою очередь в объект вложены две коллекции - CheckBoxes (кнопки выбора) и Labels (метки) с элементами классов CheckBox и Label соответственно. Обратите внимание, коллекции называются именно так и не имеют приставки , как показано на рисунке, взятом из документации, и не изменившимся в новой версии.
Объект - это диалоговое окно специального вида. При его проектировании в нем можно создать до пяти элементов каждой коллекции. Метки задают текстовые сообщения, адресованные пользователю. Обычно они имеют вид нумерованного списка или списка-бюллетеня и определяют порядок действий пользователя или возможные причины ошибки. Вторая коллекция с кнопками выбора позволяет пользователю сделать тот или иной выбор. Анализируя полученную информацию, программа может выполнять действия, предписанные выбором пользователя.
Как это мы уже не раз делали, зададим сводку основных свойств таблицей:
| Свойство | Назначение |
|---|---|
Animation |
Возвращает или устанавливает тип анимации образа Assistant. Если свойство применяется к объекту Assistant, то он "оживает" сразу же при включении. Если же оно применяется к объекту , то анимация возникает только при появлении баллончика. Может быть значением одной из 34-х констант типа MsoAnimationType. |
AssistWithAlerts, AssistWithHelp, AssistWithWizards |
Булевы свойства, имеющие значение True, если Assistant используется для выдачи предупреждений (заменяя окно MsgBox ), в ответ на нажатие клавиши F1 (Help), и при выдаче справочных сообщений, когда работают различные Мастера |
BalloonError |
Возвращает значение, указывающее на тип последней ошибки объекта . |
FeatureTips |
Булево свойство, которому дается значение True, когда желательно получать советы о наиболее эффективных способах использования свойств приложения. |
FileName |
Возвращает или устанавливает имя файла, содержащего графический образ Assistant. Файл имеет уточнение act, например файл со скрепкой - Clippit.act. Заметим, что могут быть заданы только стандартные для Office 97 файлы. Собственные образы задавать нельзя, но число стандартных образов расширяется. |
GuessHelp |
Это именно то булево свойство, установив значение которого, равным True, Вы получаете |
HighPriorityTips, KeyboardShortcutTips, MouseTips |
Советы имеют разный приоритет. Если свойство имеет значение True, то будут выдаваться советы только наивысшего приоритета. Следующие два булевы свойства включают возможность выдачи информации о горячих клавишах и наиболее эффективном использовании мыши. |
NewBalloon |
Является по существу центральным свойством, поскольку позволяет создать новый объект . После чего можно нужным образом определить свойства этого объекта. Напомним, что баллончик определяет основные возможности Assistant. |
Sounds |
Булево свойство, включающее звук в процессе анимации. |
TipOfDay |
Булево свойство, включающее или отключающее "Совет дня" при открытии приложения Office 97. |
Visible |
Делает видимым или невидимым объект Assistant, сворачивая его в кнопку на панели инструментов. |
Новые свойства в Office 2000 |
Назначение |
On |
Новое булево свойство позволяет включать и выключать Помощника. |
В Office 2000 не произошло изменений в методах объекта Assistant. Он по-прежнему имеет следующие методы: StartWizard, ActivateWizard, EndWizard, Help, Move и ResetTips. Методы этого объекта используются реже, чем свойства и я ограничусь их кратким описанием.
Методы StartWizard, ActivateWizard, EndWizard применяются при создании пользовательских Мастеров. Первым должен быть запущен метод StartWizard, возвращающий идентификатор (длинное целое) Помощника. Этот идентификатор затем используется в методах ActivateWizard и EndWizard, соответственно активизирующих и деактивирующих Помощника.
Метод Help выводит стандартное сообщение Помощника справочной системы Office 2000 с заголовком "What would you like to do?"
Метод Move перемещает Помощника в указанную параметрами left и top позицию на экране
Метод ResetTips очищает журнал советов, в связи с чем могут вновь появляться уже данные советы.
В заключение рассказа о свойствах и методах объекта Assistant приведем пример, в котором поменяем образ объекта Assistant и некоторые его свойства:
Public Sub ChooseAss() With Assistant Debug.Print .FileName 'Задаем образ Помощника '.FileName = "dot.acs" .FileName = "Offcat.acs" '.FileName = "Rocky.acs" 'Его анимационное поведение .Animation = msoAnimationGreeting .Animation = msoAnimationGetAttentionMinor 'Другие свойства .AssistWithHelp = True .FeatureTips = True .GuessHelp = True .HighPriorityTips = True .Visible = True End With End Sub
Взгляните на кошечку, которая будет сопровождать теперь выдачу советов и справок. Задавая свойство Animation, можно подобрать ее поведение, отвечающее данному моменту.
(рис 7.2) "Мурка" в роли Помощника (объекта Assistant)Обратите внимание, - на вопрос, заданный на естественном русском языке, выдана точная справка. Этого не было в предыдущей версии.
Можно изменить свойства объекта Assistant, но в каждый момент существует только один такой объект. C ним можно связать произвольное число объектов , которые я называю баллончиками. Поясним происхождение термина. Реплики рисованных персонажей комиксов или карикатур художники нередко помещают в кружок - "баллончик", выдуваемый изо рта.
У объекта Assistant нет коллекции объектов (а жаль), но можно создать необходимое число переменных этого класса или массив из таких объектов. Вот пример:
Public Sub Balls() Dim i As Integer 'Создание объектов Balloons Dim FirstBall As Balloon, LastBall As Balloon Dim ArrOfBall(3) As Balloon With Assistant .FileName = "OffCat.acs" Set FirstBall = .NewBalloon FirstBall.Show .FileName = "Rocky.acs" Set LastBall = .NewBalloon LastBall.Show For i = 1 To 3 Set ArrOfBall(i) = .NewBalloon ArrOfBall(i).Show Next i FirstBall.Show End With End Sub
Здесь созданы две переменные и массив из трех элементов класса . По ходу дела внешний вид объекта Assistant меняется, но все баллончики одинаковы, в момент рождения они пусты и имеют единственную кнопку "ОК". Рассмотрим, как можно наполнить содержанием эти объекты и задать их свойства.
Объекты предназначены для ведения диалога с пользователем и фактически являются специальным видом диалоговых окон. Любое диалоговое окно, а значит и объект может быть модальным и немодальным. Из модальных окон нельзя выйти, не закончив диалог. Обычно, для этого нужно щелкнуть одну из кнопок этого окна - Ok или Cancel. В модальном объекте эти кнопки, как правило, присутствуют, но их наличие не является обязательным. Если щелкнуть любую кнопку в функций, позволяющий организовать реакцию на выбор, сделанный пользователем в немодальном окне.
Объект имеет свойство Mode с тремя возможными значениями:
MsoModeModal - в этом случае диалог с объектом Balloon является модальным. Его обычно используют для вывода предупреждений, требующих особого внимания или получения ответа от пользователя, без которого дальнейшая работа не может быть продолжена.MsoModeModeless - в этом случае окно становится немодальным и оно может оставаться открытым, в то время как продолжается работа над приложением в других его окнах. Такие объекты удобны, например, при выдаче справочной информации, которая должна быть все время под рукой.MsoModeAutoDown - задает специальный вид С двумя свойствами этого объекта: Animation и Mode мы уже знакомы. Первое из них задает анимацию объекта Assistant при вызове его метода Show, в тот момент, когда показывается объект . Рассмотрим подробнее другие свойства
Heading - позволяет прочесть или установить строку, задающую текст заголовка.Text - На вершине объекта Balloon сразу после заголовка может появляться некоторый текст. Его и устанавливает свойство Text. Оба элемента являются необязательными. Заметьте, что Heading и Text могут включать и графику. Последняя задается строкой, имеющей следующий синтаксис: {<type> <location> [<factor>]}. Первый параметр задает тип графического файла (bmp или Icon - Слева от заголовка можно добавить специальный значок для привлечения внимания. Возможные значки задаются следующими константами: msoIconAlert, msoIconNone, или msoIconTip.Button - Внутрь баллончика можно поместить некоторое количество кнопок заранее предустановленного типа. К ним, конечно, относятся кнопки: Ok, Cancel, Next, Close, Это не все свойства объекта . Есть еще несколько важных для понимания свойств, но мы расскажем о них чуть позднее. А сейчас небольшой пример конструирования объекта с некоторыми из рассмотренных свойств:
Public Sub OneBall()
Dim Text1 As String, Text2 As String, Text3 As String
Dim Text4 As String, Text5 As String
Dim myPath As String
myPath = ActiveDocument.Path
'Формирование свойства Text
Text1 = "Хочешь знать, как перевезти с берега на берег"
'Вставка графики в середину текста
Text2 ="{wmf " myPath "\wolf.wmf}"; " Волка," vbCrLf
Text3 = "{wmf " myPath "\goat.wmf}" " Козу" " И "
Text4 = "{wmf " myPath "\cabbage.wmf}" " Капусту" vbCrLf vbCrLf
Text5 = "Соблюдая 3 правила?"
Dim FirstBall As Balloon
Set FirstBall = Assistant.NewBalloon
With FirstBall
.Heading = "Волк, Коза и Капуста"
.Icon = msoIconAlert
.Text = Text1 Text2 Text3 Text4 Text5
.Button = msoButtonSetYesNo
.Show
End With
End Sub
Вот как выглядит это диалоговое окно баллончика с картинками, вставленными в текст:
(рис 7.3) Объект Balloon с заданными свойствамиЗаметьте, следует быть внимательным при задании свойства Text, включающего картинки. При наличии ошибок диалоговое окно не будет открыто, но сообщений об ошибке не появится.
У объекта есть две коллекции - Labels с элементами Label и CheckBoxes с элементами CheckBox. В каждой из коллекций может содержаться не более пяти элементов. Элементами Labels являются метки, для которых, как правило, задается свойство Text, определяющее метку. Метки имеют тип, задающий их оформление. Все метки должны быть одного типа, так что настала пора рассказать еще об одном свойстве объекта . Тип меток задается свойством BalloonType объекта и имеет три возможных значения:
Списки первых двух типов позволяют проинформировать пользователя о тех или иных предоставляемых возможностях. Конечно, для этой цели можно также использовать свойство Text самого объекта , но метки удобнее, поскольку информация предоставляется в структурированном виде.
Третий тип меток используется для получения информации от пользователя, который выбирает одну из нескольких (до пяти) возможностей, щелчком соответствующей кнопки. Метод Show, возвращающий номер нажатой кнопки, позволяет узнать, какая кнопка была выбрана. Тем самым появляется возможность организовать дальнейшие действия в зависимости от сделанного выбора.
Вместе или вместо меток третьего типа можно использовать свойство Button, благодаря которому в баллончике также появляются кнопки, а метод Show и в этом случае возвращает номер нажатой кнопки. Кнопки со стандартными именами, задаваемые Button, часто бывают полезными, но, конечно, не всегда приемлемы. Благодаря свойству Text у кнопок - меток, можно задать "свои" кнопки со своими именами.
Совместное использование меток третьего типа и свойства Button стало теперь возможным - я приведу пример такого использования.
Флажки (кнопки выбора), задаваемые элементами CheckBox, используются для той же цели, что и кнопки - они позволяют определить выбор пользователя. Существенное отличие состоит в том, что пользователь может выбрать не одну из предоставляемых ему возможностей, а несколько, взводя соответствующие флажки. Когда флажок взведен, то свойство Checked соответствующего элемента из коллекции CheckBoxes получает значение True. Каждое из этих свойств можно затем проверить и использовать при выборе последующих действий в программе.
Приведем пример, в котором действуют два объекта
Public Sub CheckingHobbies() Dim FirstBall As Balloon, LastBall As Balloon Dim i As Integer 'Первый баллончик выясняет увлечения Assistant.FileName = "Rocky.acs" Set FirstBall = Assistant.NewBalloon With FirstBall .Heading = "Ваши увлечения" .Checkboxes(1).Text = "Футбол" .Checkboxes(2).Text = "Теннис" .Checkboxes(3).Text = "Шахматы" .Checkboxes(4).Text = "Плавание" .Checkboxes(5).Text = "Горные лыжи" .Show End With 'Второй баллончик уведомляет об увлечениях Assistant.FileName = "OffCat.acs" Set LastBall = Assistant.NewBalloon Dim Count As Integer Count = 0 With LastBall .Heading = "Ваши увлечения" .BalloonType = msoBalloonTypeBullets For i = 1 To 5 If FirstBall.Checkboxes(i).Checked Then Count = Count + 1 .Labels(Count).Text = FirstBall.Checkboxes(i).Text End If Next i If Count > 0 Then .Text = "Вы любите:" Else .Text = "Вы ничего не любите" End If .Show End With End Sub
А теперь взгляните на картинки, которые будут появляться в процессе выполнения этой процедуры.

(рис 7.5) Объект Balloon выясняет увлечения(рис 7.4) Объект Balloon уведомляет об увлеченияхФлажки и метки могут применяться одновременно, хотя вряд ли в этом есть смысл. Если пользователь должен сделать единственный выбор - применяйте метки, в случае множественного выбора - используйте флажки. В следующем примере я слегка модифицировал задачу выбора увлечения для того, чтобы продемонстрировать возможности анализа результата выбора, используя значение, возвращаемое методом Show:
Public Sub CheckingHobbies1()
'В данном примере для задания предпочтений используются метки
'и возможности анализа результата работы метода Show
Dim FirstBall As Balloon, LastBall As Balloon
Dim i As Integer
Dim Answer As MsoBalloonButtonType
'баллончик выясняет увлечения
Set FirstBall = Assistant.NewBalloon
With FirstBall
.Heading = "Ваш любимый вид спорта?"
.BalloonType = msoBalloonTypeButtons
.Labels(1).Text = "Футбол"
.Labels(2).Text = "Теннис"
.Labels(3).Text = "Шахматы"
.Labels(4).Text = "Плавание"
.Labels(5).Text = "Горные лыжи"
.Button = msoButtonSetBackNextClose
Answer = .Show
End With
'Анализ пользовательского выбора
Select Case Answer
Case 1
MsgBox ("Футбол - любимая игра миллионов.")
Case 2
MsgBox ("Теннис - красивый вид спорта.")
Case 3
MsgBox ("Шахматы - игра мыслителей.")
Case 4
MsgBox ("Плавание - нет ничего полезнее.")
Case 5
MsgBox ("Горные лыжи - спорт избранных.")
Case msoBalloonButtonBack
MsgBox ("Показать предыдущий список игр?")
Case msoBalloonButtonNext
MsgBox ("Показать следующий список игр?")
Case Else
MsgBox ("Вы совсем не спортсмен!")
End Select
End Sub
В нашем диалоговом окне три Answer, получающей результат метода Show, и на то, как она используется в Select. На следующем рисунке показан момент выбора пользователем одной из кнопок:
(рис 7.6) Организация выбора одной из многих возможностей
Процедура обратного вызова ( процедуру программиста. Естественно, что для процедур система определяет форму их вызова - имя процедуры, число и типы формальных параметров (но не их имена, которые могут быть произвольными).
процедуры необходимы при немодальном диалоге, организованном объектами . Система вызывает процедуру, передавая ей в качестве одного из параметров номер кнопки, которую выбрал пользователь в окне немодального диалога. Напомним, что при модальном диалоге этот номер возвращает метод Show. Организовать модальный диалог достаточно просто, а с не модальным всегда возникают некоторые сложности. В данном случае они преодолеваются за счет использования процедуры обратного вызова. Эту процедуру пишет сам программист, но вызывает ее система, передавая в процедуру номер кнопки, известный ей в момент вызова. Используя полученный параметр, конечно, нетрудно написать тело самой процедуры так, чтобы она правильно реагировала на выбор, сделанный пользователем.
Теперь, когда общая идея понятна, уточним некоторые детали. Прежде всего заметим, что объект имеет еще одно ранее не описанное важное свойство . Значением этого свойства является строка, задающая имя процедуры. Заметьте, что в данном случае Вы сами определяете имя процедуры и сообщаете его системе. Но число параметров и их типы все-таки фиксированы. Процедура, имя которой Вы указали в свойстве , должна иметь следующий синтаксис:
< имя процедуры> (Ball As Balloon, NumberOfButton As Long, iPriv As Long)
Повторяем, имена формальных параметров могут быть произвольными. Важно только понимать, что первый параметр задает объект , вызвавший немодальный диалог, второй - номер кнопки, выбранной пользователем (это может быть системная кнопка или кнопка, определенная меткой). Третий параметр, как правило, не используется в теле процедуры. Он необходим системному Wizard (Мастеру), работающему с объектом Assistant. Конечно, если Вы пишите свой собственный пользовательский Wizard, то этот параметр понадобится. В соответствии с этим синтаксисом необходимо написать
Public Sub UnModal()
Dim FirstBall As Balloon
Dim Text1 As String, Text2 As String
Dim Text3 As String, Text4 As String
Dim myPath As String
myPath = ActiveDocument.Path
'Формирование свойства Text
'Вставка графики в начало текста
Text1 = "{wmf " myPath " /Cabbage.wmf}"
Text2 = "Вы уже перевезли на другой берег "
Text3 = "Волка и Козу! Осталось съездить за капустой."
Text4 = "Отправляясь назад, Вы возьмете с собой: "
Set FirstBall = Assistant.NewBalloon
With FirstBall
.Mode = msoModeModeless
.Callback = "Answer"
.Icon = msoIconAlert
.Heading = "ВОЛК, КОЗА И КАПУСТА"
.Text = Text1 Text2 Text3 Text4
.BalloonType = msoBalloonTypeButtons
.Button = msoButtonSetNone
.Labels(1).Text = "Волка"
.Labels(2).Text = "Козу"
.Labels(3).Text = "Капусту"
.Labels(4).Text = "Никого"
.Show
End With
End Sub
Public Sub Answer(Ball As Balloon, Count As Long, iPriv As Long)
'Анализ принятого решения
Select Case Count
Case 1
Call Explain("Это возможное, но не лучшее решение!")
Case 2
Call Explain("Это правильно!")
Case 3
Call Explain("Это невозможно!")
Case 4
Call Explain("Ужасная трагедия: Волк съест Козу!")
Case Else
'Пропускаем
End Select
' При желании можно закрыть окно диалога
Ball.Close
End Sub
Public Sub Explain(Txt As String)
Dim ExplainBall As Balloon
Set ExplainBall = Assistant.NewBalloon
With ExplainBall
.Heading = "ВОЛК, КОЗА И КАПУСТА"
.Text = Txt
.Show
End With
End Sub
Здесь, как Вы видите, вместо переменной Answer появилась процедура Answer, которая и определяет реакцию на выбор пользователя. Заметьте, что в конце этой процедуры метод Close закрывает диалог. Если этого не делать, то после выдачи сообщения о неудачном решении, можно вернуться в окно немодального диалога и изменить свой выбор! В этом сила немодального диалога. Тем не менее, следует быть весьма аккуратным и во время закрыть окно немодального диалога. В противном случае это окно будет постоянно (до перезагрузки компьютера) сопровождать Помощника на экране. Сложность состоит в том, что локальная переменная, определяющая объект , может прекратить свое существование, а немодальное окно будет продолжать существовать. Поэтому лучше такие переменные определять как глобальные переменные модуля, тогда метод Close может быть вызван в любой из процедур, завершающих работу приложения.
Несколько слов о том, когда нужен такой "несерьезный" интерфейс с анимацией и разными актерами, выступающими в роли помощника. Он, на наш взгляд, подходит для пользователей и приложений определенного типа. Прежде всего, речь может идти об играх и обучающих системах.
В этих серьезных приложениях, ориентированных на юных или начинающих пользователей, такой интерфейс позволяет вести пользователя шаг за шагом по всей системе, демонстрируя ее возможности. В предыдущей лекции в качестве примера "документа-обложки" я рассмотрел создание известной игры для младших школьников "Волк, Коза и Капуста". В этой реализации не использовался объект Assistant, для того чтобы выдержать чистоту эксперимента и иметь возможность экспорта полученной реализации в чистый VB, создав затем исполняемый файл или ActiveX. При подготовке этой лекции я добавил к этой игре объект Assistant, поручив ему вести весь диалог по ходу игры, сообщать о правилах игры, давать советы о действии, которое следует выполнить, уведомлять о неудачах, возникающих при неверном ходе.
Не возникло никаких принципиальных трудностей с добавлением объекта Assistant к уже имеющейся реализации игры. Понятно, что пришлось слегка изменить интерфейс, - в игре появились еще два визуальных объекта. Одним из них является Помощник, роль которого играет Рокки, вторым - остров, где живет Рокки. Чтобы дать представление о том, как теперь выглядит интерфейс игры, как выглядит диалог, приведу пару рисунков, отображающих некоторые моменты общения с Помощником "Рокки" в процессе игры:
(рис 7.7) Приветствие Рокки в момент начала игрыНа следующих двух рисунках Рокки рассказывает о правилах игры и дает совет по поводу очередного хода:

(рис 7.9) Рокки сообщает о правилах игры(рис 7.8) Рокки дает советЯ уже сказал, что никаких серьезных трудностей не возникло при введении Помощника для организации диалога. Достаточно просто, заменить сообщение, выдаваемое функцией MsgBox на сообщение, выдаваемое Помощником, используя его баллончики. Но здесь есть одно "но"! При работе с Помощником появляется больше возможностей и, поневоле, хочется организовать более живой и интересный диалог - использовать картинки, дать пользователю возможность выбора, проявить интеллект и предлагать подсказки в возникающих ситуациях.
О том, как в сообщения, появляющиеся в баллончиках, включать рисунки, было уже рассказано в этой лекции. Было также достаточно подробно рассказано и о том, как дать возможность пользователю выбирать и как затем анализировать его выбор. Поэтому давайте поговорим об "интеллекте" Помощника. Это трудная задача. Но в нашем простом примере она решаема. Давайте возложим на Помощника обязанность не только следить за соблюдением правил игры и выдавать сообщения при их нарушениях, но и пусть он дает советы, подсказывая, какой ход следует сделать в той или иной ситуации.
Общий подход решения последней задачи понятен, - необходимо следить за состоянием системы, в нашем случае игры. Когда пользователь обращается к Помощнику за советом, то, зная текущее состояние S, можно попытаться найти разумное решение R. Иногда, как в нашей простой игре, существует точное решение и, зная S, можно однозначно определить R, как функцию от S. В тех случаях, когда для поиска решения необходим перебор вариантов, проведение сложных вычислений или просто квалификация пользователя невысока, советы Помощника могут быть весьма ценными. Интеллектуальные Помощники незаменимы в играх и обучающих системах. Конечно, в серьезных задачах квалифицированный пользователь может принимать лучшие решения, но и там подсказки Помощника могут быть полезными.
В игре "Волк, Коза и Капуста" достаточно было ввести одну переменную, следящую за состоянием игры, изменять ее значение по ходу игры, и при обращении к Помощнику за советом, выдавать подсказку на основе анализа значения этой переменной.
Вот какие изменения пришлось сделать в реализации игры. Во-первых, я добавил новый модуль Dialogs, в который поместил процедуры и константы, необходимые для ведения диалога. Некоторые изменения пришлось ввести и в текст модуля WGC. В раздел объявлений этого модуля добавлены следующие строчки:
Public StateOfPlay As String 'Состояние игры Public Answer As MsoBalloonButtonType 'Выбор пользователя 'Другие общие параметры Public WidthOfRiver 'Ширина реки Public MyPath As String 'каталог, хранящий исходный документ и другие файлы игры
Изменения внесены и в процедуру инициализации:
Public Sub InitialStates() 'Задаем начальные состояния объектов и их образов StateOfMan = "LeftBank" StateOfWolf = "LeftBank" StateOfGoat = "LeftBank" StateOfCabbage = "LeftBank" StateOfBoat = "LeftBank" CountInBoat = 0 StateOfPlay = "InitState" 'Инициализация объектов формы With WGCForm .Man.Top = .LeftBank.Top + 15: .Man.Left = .LeftBank.Left + 10 .Man.Visible = True .Wolf.Top = .LeftBank.Top + 80: .Wolf.Left = .LeftBank.Left + 10 .Wolf.Visible = True .Goat.Top = .LeftBank.Top + 140: .Goat.Left = .LeftBank.Left + 10 .Goat.Visible = True .Cabbage.Top = .LeftBank.Top + 200: .Cabbage.Left = .LeftBank.Left + 10 .Cabbage.Visible = True .Boat.Top = .LeftBank.Top + 130: .Boat.Left = .LeftBank.Left + .LeftBank.Width .Boat.Visible = True WidthOfRiver = .Width - .LeftBank.Width - .RightBank.Width _ - .Boat.Width 'Поместить Рокки на остров Assistant.FileName = "Rocky.acs" 'Debug.Print Assistant.Left, Assistant.Top Assistant.Move XLeft:=.Left + .Island.Left + .Island.Width / 2, _ YTop:=.Top + .Island.Top + .Island.Height - 10 Assistant.Animation = msoAnimationCharacterSuccessMajor 'Assistant.AssistWithAlerts = False 'Assistant.AssistWithHelp = False 'Debug.Print Assistant.Left, Assistant.Top End With 'Путь к каталогу MyPath = ActiveDocument.Path 'Сформировать баллончики - диалоговые окна Call FormBalloons 'Инициализировать диалог Call Dialog1 End Sub
Я улучшил инициализацию, задав относительное расположение объектов, что позволяет менять размеры игрового поля, сохраняя взаимное расположение объектов. Наиболее серьезные дополнения выделены цветом фона. Как видите, здесь вводится объект Assistant и, используя метод Move, он помещается на свое место - остров, при этом задается его анимационное поведение. Далее вызываются две процедуры модуля Dialogs. В первой из них формируются объекты - баллончики разного типа, во второй - инициализируется начальный диалог Помощника, приглашающий к началу игры.
Других изменений в процедурах этого модуля не было, если не считать замены вызовов функции MsgBox на вызовы соответствующих функций модуля Dialogs, как, например, в процедуре TestingState:
Public Sub TestingState() 'Тестирование состояний With WGCForm 'Волк съел козу If (StateOfWolf = StateOfGoat) And (StateOfWolf < > StateOfMan) Then .Goat.Visible = False 'MsgBox Prompt:=Mes1 + vbCrLf + Mes3, Buttons:=vbCritical + vbOKOnly, Title:=Mes13 Call Dialog5 InitialStates End If 'Коза съела капусту If (StateOfCabbage = StateOfGoat) And (StateOfCabbage < < StateOfMan) Then .Cabbage.Visible = False 'MsgBox Prompt:=Mes1 + vbCrLf + Mes4, Buttons:=vbCritical + vbOKOnly, Title:=Mes13 Call Dialog6 InitialStates End If 'Слишком много пассажиров! If (CountInBoat > 2) Then If StateOfMan = "InBoat" Then .Man.Visible = False If StateOfWolf = "InBoat" Then .Wolf.Visible = False If StateOfGoat = "InBoat" Then .Goat.Visible = False If StateOfCabbage = "InBoat" Then .Cabbage.Visible = False 'MsgBox Prompt:=Mes1 + vbCrLf + Mes5, Buttons:=vbCritical + vbOKOnly, Title:=Mes13 Call Dialog7 InitialStates End If 'Конец игры - Все пассажиры собрались на правом берегу If (StateOfMan = "RightBank") And (StateOfWolf = "RightBank") And _ (StateOfGoat = "RightBank") And (StateOfCabbage = "RightBank") Then 'MsgBox Prompt:=Mes2 + vbCrLf + Mes6, Buttons:=vbExclamation + vbOKOnly, Title:=Mes14 Call Dialog8 End If End With End Sub
Приведем теперь текст модуля Dialogs:
Option Explicit
'Константы для организации диалогов
Public Const Mes1 = "Ужасно, нелепо и грустно! "
Public Const Mes2 = "Прекрасно, как славно,отлично! "
Public Const Mes3 = " Волк съел козу! "
Public Const Mes4 = " Коза съела капусту! "
Public Const Mes5 = " Лодка перевернулась и все утонули! "
Public Const Mes6 = " Вам это удалось! Все переправились!"
Public Const Mes7 = " Не удалось дотащить "
Public Const Mes8 = " Человека! "
Public Const Mes9 = " Волка! "
Public Const Mes10 = " Козу! "
Public Const Mes11 = " Капусту! "
Public Const Mes12 = " Повторите попытку! "
Public Const Mes13 = " Беда!"
Public Const Mes14 = " Радость! "
Public Const Mes15 = " Лодку! "
Public Const Txt1 = "Привет! Я Рокки." vbCrLf _
"Щелкни по острову, если захочешь поговорить со мной."
Public Const Txt2 = "Волк, Коза и Капуста!"
'Public Const Txt3 = "{wmf " MyPath "\goat.wmf}"
'Public Const Txt4 = "{wmf " MyPath "\cabbage.wmf}"
Public Const Txt5 = ""
'Массив баллончиков - диалоговых окон Рокки
Public RockyBalloons(1 To 10) As Balloon
Public Sub Dialog()
'Начальный диалог при открытии игры
'Анализ состояния игры
Select Case StateOfPlay
Case "InitState"
Call Dialog1
Case "State1"
Call Dialog2
Case "State2"
Call Dialog9
Case "StateFinish"
Call Dialog10
Case Else
End Select
End Sub
Public Sub OneBall()
Dim Text1 As String, Text2 As String, Text3 As String
Dim Text4 As String, Text5 As String
Dim MyPath As String
MyPath = ActiveDocument.Path
'Формирование свойства Text
Text1 = "Хочешь знать, как перевезти с берега на берег"
' Вставка графики в середину текста
Text2 = "{wmf " MyPath "\wolf.wmf}" " Волка," vbCrLf
Text3 = "{wmf " MyPath "\goat.wmf}" " Козу" " И "
Text4 = "{wmf " MyPath "\cabbage.wmf}" " Капусту?" vbCrLf vbCrLf
'Text5 = "Соблюдая 3 правила?"
Dim FirstBall As Balloon
Set FirstBall = Assistant.NewBalloon
With FirstBall
.Heading = "Волк, Коза и Капуста"
.Icon = msoIconAlert
.Text = Text1 Text2 Text3 Text4
.Button = msoButtonSetYesNo
.Show
End With
End Sub
Public Sub FormBalloons()
'Инициализация баллончиков
Dim I As Integer
For I = 1 To 10
Set RockyBalloons(I) = Assistant.NewBalloon
RockyBalloons(I).Heading = Txt2
RockyBalloons(I).Icon = msoIconAlertInfo
Next I
FormBall1
FormBall2
FormBall3
FormBall4
FormBall5
FormBall6
FormBall7
'FormBall8
End Sub
Public Sub FormBall1()
'Формирование свойства Text - знакомство
With RockyBalloons(1)
.Text = Txt1
.Button = msoButtonSetOK
End With
End Sub
Public Sub Dialog1()
RockyBalloons(1).Show
StateOfPlay = "State1" 'Игра началась
End Sub
Public Sub FormBall2()
Dim Text1 As String, Text2 As String, Text3 As String
Dim Text4 As String, Text5 As String
'Формирование свойства Text
Text1 = "Нужно срочно перевезти с берега на берег"
' Вставка графики в середину текста
Text2 = "{wmf " MyPath "\wolf.wmf}" " Волка," vbCrLf
Text3 = "{wmf " MyPath "\goat.wmf}" " Козу" " И "
Text4 = "{wmf " MyPath "\cabbage.wmf}" " Капусту?" vbCrLf vbCrLf
Text5 = "Хочешь знать правила игры?"
With RockyBalloons(2)
.Text = Text1 Text2 Text3 Text4 Text5
.Button = msoButtonSetYesNo
End With
End Sub
Public Sub Dialog2()
Answer = RockyBalloons(2).Show
Select Case Answer
Case msoBalloonButtonYes 'Нажата кнопка Yes
'Показать правила игры
Call Dialog3
Case msoBalloonButtonNo 'Нажата кнопка No
'Предложить начать играть
Call Dialog4
End Select
End Sub
Public Sub FormBall3()
Dim Text1 As String, Text2 As String, Text3 As String
Dim Text4 As String, Text5 As String
'Формирование переменных Text
Text1 = "В лодке, используемой для перевоза," _
" может находиться не более двух путников" _
" (человек, волк, коза и капуста - это путники)." vbCrLf _
"При попытке посадить большее число путников лодка перевернется. "
Text2 = "Если оставить в лодке или на берегу волка и козу без присмотра человека," _
vbCrLf "то волк немедленно съест козу."
Text3 = "Если оставить в лодке или на берегу капусту и козу без присмотра человека," _
vbCrLf "то коза немедленно съест капусту."
Text4 = "Без человека лодка не может переплыть на другой берег."
Text5 = "Начинайте играть! Желаю успеха!"
With RockyBalloons(3)
.BalloonType = msoBalloonTypeNumbers
.Labels(1).Text = Text1
.Labels(2).Text = Text2
.Labels(3).Text = Text3
.Labels(4).Text = Text4
.Labels(5).Text = Text5
End With
End Sub
Public Sub Dialog3()
RockyBalloons(3).Show
StateOfPlay = "State2" 'Правила заданы
End Sub
Public Sub FormBall4()
RockyBalloons(4).Text = "Начинайте играть! Желаю успеха!"
End Sub
Public Sub Dialog4()
RockyBalloons(4).Show
StateOfPlay = "State2" 'Правила заданы
End Sub
Public Sub FormBall5()
RockyBalloons(5).Icon = msoIconAlertCritical
End Sub
Public Sub Dialog5()
RockyBalloons(5).Text = Mes1 + vbCrLf + Mes3
RockyBalloons(5).Show
StateOfPlay = "State1" 'Начало игры
End Sub
Public Sub Dialog6()
RockyBalloons(5).Text = Mes1 + vbCrLf + Mes4
RockyBalloons(5).Show
StateOfPlay = "State1" 'Начало игры
End Sub
Public Sub Dialog7()
RockyBalloons(5).Text = Mes1 + vbCrLf + Mes5
RockyBalloons(5).Show
StateOfPlay = "State1" 'Начало игры
End Sub
Public Sub FormBall6()
RockyBalloons(6).Icon = msoIconAlert
RockyBalloons(6).Text = Mes2 + vbCrLf + Mes6
End Sub
Public Sub Dialog8()
RockyBalloons(6).Show
StateOfPlay = "StateFinish" 'Конец игры
End Sub
Public Sub Dialog9()
'Совет!
'Rule1: Если волк и коза на одном берегу, то увези козу.
'Rule2: Если капуста и коза на одном берегу, то увези капусту.
If (StateOfWolf = StateOfGoat) Then
RockyBalloons(7).Text = "Увези козу!"
ElseIf (StateOfCabbage = StateOfGoat) Then
RockyBalloons(7).Text = "Увези капусту!"
Else
RockyBalloons(7).Text = "Тут моя помощь не нужна!"
End If
RockyBalloons(7).Show
End Sub
Public Sub FormBall7()
RockyBalloons(7).Icon = msoIconTip
End Sub
Public Sub Dialog10()
RockyBalloons(6).Text = "Приходите, поиграем еще раз! Рокки будет ждать."
RockyBalloons(6).Show
StateOfPlay = "StateFinish" 'Конец игры
End Sub
Я не буду комментировать процедуры этого модуля. Все что нужно было сказать, уже сказано. Отмечу только процедуру Dialog9, которая вызывается, когда Рокки должен дать совет. Заметьте, его интеллектуальность определяется двумя правилами типа "если… то". Если не выполняются условия ни одного из этих правил, то Рокки полагает, что ситуация очень простая и его советы не нужны, поскольку можно принимать любое решение, допустимое правилами игры.
На этом мы и закончим разговор об организации диалогов с использованием возможностей объекта Assistant.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.