程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言基礎知識 >> Microsoft Agent技術應用

Microsoft Agent技術應用

編輯:C語言基礎知識
Microsoft Agent技術應用
                                      --AgentShell的實現原理介紹

[摘要]
    本文介紹了如何應用Agent的以及AgentShell的實現原理和幾個重要的技術處理。

[關鍵詞]
    Agent,COM,角色,語音識別,語音合成。

    對Agent編程的方法主要有使用VB,VC等語言進行ActiveX調用,除此之外還有直接通過VC進行COM
編程調用。在VB中調用Agent是最簡單不過了,但由於VB程序本身存在諸多缺陷,很難在實際中應用。
而在VC中,由於Agent內部完全采用了UNICODE編碼,同時還要處理各種繁雜的COM接口,從而也存在一
定的問題。AgentShell是建立在Agent和應用程序之間的一個外殼程序,通過它可將Agent復雜的COM接
口封裝起來,轉變為簡單的函數調用,很好的實現對Agent的控制。同時AgentShell也作為一個獨立的程
序,可處理英文自動朗讀等功能,本文將詳細介紹其實現原理。
    (一) 原理介紹
    AgentShell和Agent Server的連接是通過COM調用來實現的,對於與應用程序的通信是通過WM_COPYDATA
消息來實現的, 下圖表示出AgentShell與其它程序的關系:
            [ Agent Server ]
                    |
              [ COM調用 ]
                    |
            [ AgentShell ]
                    |
                [ 消息 ]
                    |
            [ 應用程序 ]

  將一個Agent控制加載相應的動畫和語音碼我們稱之為“角色”,一般使用COM調用創建一個Agent角色,
要經過以下幾個過程:
            [ 初始化COM ]
                    |
          [ 連接Agent COM Sever,創建Agent控制 ]
                    |
          [ 注冊Agent控制的消息反應器(Notify Sink) ]
                    |
          [ 加載角色數據文件,創建一個角色(Character) ]
                    |
          [ 設置角色的語言、初始位置以及其它屬性 ]
                    |
            [ 顯示角色 ]

  AgentShell中定義以下全局變量來控制角色的屬性和動作:
  角色的消息ID:    long g_lNotifySinkID。
  角色ID: long g_lMyAgentID。
  Agent控制指針: IAgentEx *g_pAgentEx。
  角色指針: IAgentCharacterEx *g_pMyAgent。
  角色消息反應器指針: AgentNotifySink *g_pSink。

  使用以上變量可很容易的調用Agent的功能,如顯示角色:
    BOOL agentShow()
    {
        HRESULT hRes;
        long lRequestID;

        if( !g_pMyAgent)
            return FALSE;
        hRes = g_pMyAgent->Show(FALSE, &lRequestID);
        if (FAILED(hRes))
            return FALSE;
        return TRUE;
    }

    (二) 角色的語言處理
  目前Agent支持很多種語言,不僅是顯示,還有語音合成和語音識辨(對於中文,目前僅支持顯示)。
語言又分為主語言和子語言(或為副語言),如中文的主語言為中文(LANG_CHINESE),子語言則可為
簡體(SUBLANG_CHINESE_SIMPLIFIED)和繁體等。AgentShell中定義兩個全局變量表達角色的語種:

  主語言:DWORD g_nMainLang。
  子語言:DWORD g_nSubLang。
  這樣程序內必須根據當前語言的不同來顯示不同的信息,如程序退出時的問候信:
  首先定義不同的語言信息,可以為宏定義或資源數據:
  #define MES_GOODBYEL"Goodbye!"
  #define MES_GOODBYE_CH L"再見!"
  #define MES_GOODNIGHTL"Good night!"
  #define MES_GOODNIGHT_CH L"祝您晚安!"
  以下為實現退出提示代碼:
  void Goodbye()
  {
        if( g_bAgentOK)
        {
          SYSTEMTIME time;
          agentStop();
          agentShow();
          agentPlay(L"Wave");
          GetLocalTime(&time);
          // 根據時間不同提示不同信息
          if( g_nMainLang == LANG_ENGLISH)
          {
                // 提示英文信息
                if( time.wHour < 19)
                  agentSpeak(MES_GOODBYE);
                else
                  agentSpeak(MES_GOODNIGHT);
          }
          else
          {
                // 提示中文信息
                if( time.wHour < 19)
                  agentSpeak(MES_GOODBYE_CH);
                else
                  agentSpeak(MES_GOODNIGHT_CH);
          }
          agentHide();
          // 等待若干時間
          Sleep(MAX_QUIT_TIME);
        }
  }
  當然以上介紹的只是一種較為簡單的方法,僅在於描述這種原理。

    (三) 實現自動朗讀英文
  實現自動朗讀實際上是響應剪貼板消息的過程,當復制選種的文本信息時,系統自動發送WM_DRAWCLIPBOARD
消息給所有剪貼板監視隊列中的窗口,相應的窗口只要讀取當前剪貼板內的信息進行朗讀即可,具體實現如下:

  安裝剪貼板監視:
  void InstallClipSpy()
  {
        g_hNextWnd = SetClipboardViewer(g_hMainWnd);
  }
 
  主窗口的回調函數中相應剪貼板消息:
  LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
    // 剪貼板窗口隊列發生變化
    case WM_CHANGECBCHAIN:
    hwndRemove = (HWND)wParam; // handle of window being removed
    hwndNext = (HWND) lParam;
    if( hwndRemove == g_hNextWnd)
    {
        g_hNextWnd = hwndNext;
    }
    if( g_hNextWnd)
    {
        SendMessage(hwndNext, WM_CHANGECBCHAIN, wParam, lParam);
    }
    // 剪貼數據發生變化
    case WM_DRAWCLIPBOARD:
  // 是否自動閱讀
  if( g_bEnableRead)
  {
        // 閱讀剪貼板信息
        ReadClipText();
  }
  if( g_hNextWnd)
  {
        SendMessage(g_hNextWnd,WM_DRAWCLIPBOARD,wParam, lParam);
  }
  獲取剪貼板信息並且朗讀:
  void ReadClipText()
  {
        if( g_bAgentOK)
        {
          // 只有文本文件才朗讀
          if( IsClipboardFormatAvailable(CF_TEXT))
          {
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved