:: Главная :: Проекты :: MSAgent :: Музыка :: Гостевая :: Форум ::

Главная

О сайте

Гостевая книга
Форум

Проекты

О разделе

Animals v1.7.2r2
ReadIt v1.2
LittleHelper
EasyTester v1.3
EasyTester v2.0

MS Agent

Отступление

MSAgent в Delphi
MSAgent+MSBalloon
Новый DlgBalloon
SpeechAPI в Delphi

MSAgent и SAPI

Speech API часть2
- Работа с тегами
- Атрибуты голоса
- Диалоги
Синтез речи в файл
Обзор говорящих программ
Насосная станция

Музыка

Моя музыка

Альфред Шнитке
Музыка А. Шнитке

Голосование
Применяете ли вы технологию MSAgent в своих приложениях?
Да, применяю
Собираюсь применить
Лишняя фишка

Поиграть с MSA

Персонаж:

Позиция:
X: Y:
 
Величина:

%

Поговорить:
Примечание: Поиграть с персонажем можно только, если у вас установлен MSAgent v2.0, а проговорить при установленных голосовых функций. Все компоненты можно скачать тут.

Подписка
Ваш e-mail:
Раздел:
 

MS Agent в Delphi

MS Agent - это обычный активный элемент ActiveX. Этот компонент активно используется Microsoft в пакете MS Office. Да, MS Agent это та самая скрепка, кошка, собачка или кто там у вас... появляющаяся при загрузке приложений MS Office.

Если вы уже скачали и установили MS Agent v2.0, то приступим к установке его в среду Delphi, else goto Насосная станция.

Запустите Delphi, откройте меню Component и выберите Install ActiveX control... Попытайтесь найти в списке Microsoft Agent Control 2.0 (Version 2.0), если его там нет, то нажмите кнопку Add и найдите вручную файл Agentctl.dll. Теперь можно нажимать кнопку Install...

Фотка окна импорта ActiveX

По умолчанию компонент помещается на вкладку ActiveX (а на какую еще нормальный ActiveX может поместиться?). Все! Теперь можно приступать непосредственно к программированию.

MS Agent имеет большое количество интерфейсов, но для начала нам понадобится немногое:

  • IAgentCtlCharacterEx - Самый основной интерфейс. С его помощью проводятся все действия с персонажем
  • IAgentCtlRequest - Состояние агента, запрос который выполняется персонажем в каждый момент времени доступен через этот интерфейс, поэтому он часто используется для синхронизации при работе с несколькими персонажами одновременно
  • IAgentCtlAnimationNames - Для перебора различных анимаций персонажа
  • IAgentCtlBalloonEx - Для управления баллоном, в котором персонаж выводит читаемый текст или свои мысли

Сейчас мы попробуем сделать так, чтобы при загрузке приложения появлялся какой-нибудь персонаж. В секцию private вставим нужные для работы переменные:

private
   { Private declarations}
   Req: IAgentCtlRequest;{Будет хранить текущее действие персонажа}
   Chars: IAgentCtlCharacterEx;{Хранит сам персонаж для обращения к нему}
public
   { Public declarations }
end;

Теперь пропишем обработчик события OnCreate главной формы.

procedure TForm1.FormCreate(Sender: TObject);
begin
Agent1.Characters.Load('MyAgent', 'Genie.acs'); {Здесь мы загружаем персонаж из файла 'merlin.acs' под именем 'Merlin'. Вы можете здесь вписать свое имя и имя файла, имеющегося у вас персонажа}
Chars:= Agent1.Characters.Character('MyAgent') as IAgentCtlCharacterEx; {Запоминаем персонаж в переменной Chars}
Req:=Chars.Show(0);
{Наконец-то показываем персонаж, и запоминаем, что он делает в данное вермя. Будем всегда так поступать, т.к. это понадобится, если мы вдруг пожелаем остановить анимацию в ходе ее выполнения}
end;

Не забудьте прописать выгрузку персонажа при закрытии формы:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Agent1.Characters.Unload('MyAgent');
end;

Скомпилируйте и запустите проект. Ну как?

А теперь давайте попробуем сделать загрузку персонажа во время работы программы. То есть дадим возможность пользователю загружать персонаж самостоятельно из имеющихся у него на компьютере. Кстати, сейчас мы указывали только имя файла при загрузке пресонажа, без его пути. Поэтому сначала система будет искать персонаж в подпапке каталога с Windows "C:\Windows\MSAgent\Chars\", а если не найдет, то будет error.

Поместим на форму компонет OpenDialog, укажем маску файлов *.acs. Затем поместим на форму батон (ну, то есть Button) и определим обработчик события на щелчок мыши:

procedure TForm1.Button1Click(Sender: TObject);
begin
 if OpenDialog1.Execute then //Если выбрали файл 
   begin
    if Chars<>nil then {Если какой-то персонаж загружен, выгружаем его} 
      Agent1.Characters.Unload('MyAgent');
    Agent1.Characters.Load('MyAgent', OpenDialog1.FileName);
    Chars:= Agent1.Characters.Character('MyAgent') as IAgentCtlCharacterEx;
    Req:=Chars.Show(0);
   end;
end;

Теперь давайте поперемещаем наш персонаж по экрану. К примеру, вписываем в два поля редактирования координаты позиции агента, и по клику соответстующей кнопки персонаж перелетает на новое место. Два Edit'а обзовем PosX и PosY, а в OnClick "соответствующей кнопки" запишем:

procedure TForm1.Button2Click(Sender: TObject);
begin
  Chars.Stop(Req);
  {Останавливаем выполняемое действие.
Правда остановим его,в том случае если мы его запоминали}

Req:=Chars.MoveTo(StrToInt(PosX.Text), StrToInt(PosY.Text), 1); end;

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

Еще одно интересное замечание. Анализируя значение Req.Status можно выяснить следующую информацию о запросе к MS Agent'у:

0 - успешно выполнено
1 - аварийно завершено
2 - не закончено
3 - прервано
4 - выполняется

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

procedure ShowAgentAnim;
var
  AEnum: IEnumVariant;
  flag: Cardinal;
  V: OleVariant;
begin
 with Form1 do
   begin
    AEnum:=(Chars.AnimationNames.Enum) as IEnumVariant;
    {Получаем интерфейс анимаций агента}
    AEnum.Reset; //Сбрасываем список на первую анимацию
    ListBox1.Items.Clear;
    repeat
      AEnum.Next(1, V, flag);
      if VarToStr(V) <> '' Then
        ListBox1.Items.Add(V);
    until flag=0;
    {Флажок будет равен 0, когда мы узнали имя последней анимации}
   end;
end;

Еще одно отступление. Попробуйте сейчас скомпилировать проект. Если Delphi показывает ошибку в строчке AEnum: IEnumVariant - необъявленный идентификатор, то наверняка в списке включаемых модулей в секции uses отсутствует модуль ActiveX. Включите его вручную, и ошибка изчезнет, так как IEnumVariant объявлен именно в этом модульке.

Однако, замечено странное явление в Delphi7. Об этом многие писали мне, а так же в гостевой. В этой процедуре программа падает при выполнении в строке:

AEnum:=(Chars.AnimationNames.Enum) as IEnumVariant;

Падает с самым общим исключением EAccessViolation. Такое явление наблюдается только в Delphi7. При компиляции на Delphi6 в Win2000 - все нормально, а в Delphi5 на Win98 - тем более. До сих пор не разобрался точно в чем причина. Но есть некоторое решение проблемы. Я попробовал в Delphi7 на WinXP файлы созданные при импортировании агента (AgentObjects_TLB.pas, AgentServerObjects_TLB.pas - в папке
$Delphi\Imports) заменить файлами, созданными в Delphi5. На моей системе заработало, пишите, кому помогло, а кому нет. На всякий случай выкладываю эти файлы, если у кого нет. Качать здесь!

Теперь придется вставить нашу процедуру создания списка анимаций в обработчик события создания формы и в процедуру загрузки персонажа. Таким образом наши процедурки примут вид:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Agent1.Characters.Load('MyAgent', 'Genie.acs'); 
  Chars:= Agent1.Characters.Character('MyAgent') as IAgentCtlCharacterEx;
  ShowAgentAnim; //Создаем список анимаций 
  Req:=Chars.Show(0);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
 if OpenDialog1.Execute then 
   begin
    if Chars<>nil then
      Agent1.Characters.Unload('MyAgent');
    Agent1.Characters.Load('MyAgent', OpenDialog1.FileName);
    Chars:= Agent1.Characters.Character('MyAgent') as IAgentCtlCharacterEx;
    ShowAgentAnim; //Создаем список анимаций 
    Req:=Chars.Show(0);
   end;
end;

Ну и наконец создадим процедуру проигрывания анимаций по клику в ListBox'е:

procedure TForm1.ListBox1Click(Sender: TObject);
begin
  Chars.Stop(Req);
  Req:=Chars.Play(ListBox1.Items.Strings[ListBox1.ItemIndex])
end;

Самым интересным методом у MS Agent является , наверное, метод Speak:

function Speak(Text: OleVariant; Url: OleVariant): IAgentCtlRequest;

Персонаж прочитает вам голосом введенный текст. Правда для этого вам придется установить пакет речевых функций Speech API и какой-нибудь голосовой синтезатор - движок Text-To-Speech (TTS). Подробнее программирование речи в Delphi мы резберем в следующем резделе Speech API в Delphi, там мы продолжим совершенствовать проект, а сейчас посмотрим как синхронизировать два персонажа между собой, то есть попробуем устроить между ними небольшой диалог.

Естественно, что нам понадобится еще одна переменная Chars2: IAgentCtlCharacterEx, а для того чтобы достичь "понимания" между двумя персонажами такой вот метод:

function Wait(const WaitForRequest: IDispatch): IAgentCtlRequest;

Сохраните как-нибудь текущий проект, я, к примеру, его обозвал AgentTest, и попробуйте создать новый проект с таким кодом в создании формы:

procedure TForm1.FormCreate(Sender: TObject);
begin
Agent1.Characters.Load('MyAgent', 'Genie.acs');
Chars:=Agent1.Characters.Character('MyAgent') as IAgentCtlCharacterEx;
Chars.MoveTo(200, 200, 1);
Chars.Show(0);
Chars.Set_LanguageID($419);//Меняем язык на русский
Agent1.Characters.Load('MyAgent2', 'Merlin.acs');
Chars2:=Agent1.Characters.Character('MyAgent2') as IAgentCtlCharacterEx;
Chars2.Set_LanguageID($419);
Chars.Speak('Привет! '+Chars.Get_Description, '');
Chars.Play('GestureLeft');
Chars2.Wait(Chars.Speak('А вот и мой друг Мерлин!', '')); {Мерлин ждет пока его представит Джинн}
Chars2.MoveTo(400, 200, 0);
Chars2.Show(0); //А теперь появляется сам Мерлин
Chars.Play('RestPose');
Chars2.Speak('Привет!', '');
Chars.Play('LookLeft');
Chars.Wait(Chars2.Speak('Спасибо за представление!', ''));
Chars2.Wait(Chars.Play('Acknowledge'));
Chars.Play('LookLeft');
Chars.Wait(Chars2.Speak('Привет! '+Chars2.Get_Description, ''));
Chars2.Wait(Chars.Play('Congratulate'));
Chars.Play('RestPose');
Chars2.Speak('Пока!', '');
Chars2.Play('Wave');
Chars2.Hide(0);
end;

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

Готовые проекты можно скачать здесь:

Проект AgentTest (~200Кб) и AgentDialog (~187Кб)

 


 

 
   
Rambler's Top100
1:14 :2093 - 1:3155
© Copyright 2002-2004; Denis Butorin