home *** CD-ROM | disk | FTP | other *** search
/ Developing for Microsoft …tive Animated Characters / DEV_AGENTA.ISO / Examples / c / hello3 / Hello3.cpp next >
C/C++ Source or Header  |  1997-08-19  |  9KB  |  387 lines

  1. #include "Hello3.h"
  2. #include "AgtSvr_i.c"
  3. #include "Notify.h"
  4.  
  5.  
  6. //==========================================================================
  7. //
  8. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  9. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  10. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  11. //  PURPOSE.
  12. //
  13. //  Copyright (C) 1997 Microsoft Corporation.  All Rights Reserved.
  14. //
  15. //--------------------------------------------------------------------------
  16. //
  17. // This sample demonstrates loading 2 characters and synchronizing
  18. // their actions.
  19. //
  20. //==========================================================================
  21.  
  22.  
  23. // The AgentHRESULT object makes it easier to handle errors by
  24. // throwing a C++ exception when it is assigned a FAILED HRESULT.
  25. // You MUST use this object only in try/catch blocks.  By using
  26. // this object you don't have to check the return value after every
  27. // call into Microsoft Agent.
  28.  
  29. struct AgentHRESULT {
  30.  
  31.     AgentHRESULT& operator =(const HRESULT hRes) {
  32.         if (FAILED(hRes))
  33.             throw hRes;
  34.         return *this;
  35.     }
  36. };
  37.  
  38.  
  39. // Constants
  40.  
  41. static const LPWSTR kpwszGenie = L"\\Program Files\\Microsoft Agent\\characters\\genie.acs";
  42. static const LPWSTR kpwszMerlin = L"\\Program Files\\Microsoft Agent\\characters\\merlin.acs";
  43. static const LPTSTR kpszAppTitle = _T("Microsoft Agent Samples");
  44.  
  45.  
  46. // Globals
  47.  
  48. extern long g_lDone = 0;
  49.  
  50.  
  51. // Forward references
  52.  
  53. HRESULT LoadCharacter(IAgent *pAgent, 
  54.                       LPWSTR pwszPath, 
  55.                       long *plID, 
  56.                       IAgentCharacter **ppCharacter);
  57.  
  58. BOOL    InitAgent(IAgent **ppAgent, 
  59.                   long *plSinkID, 
  60.                   AgentNotifySink **ppSink);
  61.  
  62.  
  63.  
  64. extern "C" int PASCAL WinMain(HINSTANCE hInst,
  65.                               HINSTANCE hInstPrev,
  66.                               LPSTR lpCmdLine,
  67.                               int nCmdShow) {
  68.  
  69.     HRESULT                hRes;
  70.     AgentHRESULT        ahRes;
  71.     _TCHAR                szError[256];
  72.     BSTR                bszSpeak = NULL;
  73.     MSG                    msg;
  74.     long                lGenieID;
  75.     long                lMerlinID;
  76.     long                lRequestID;
  77.     long                lWaitID;
  78.     long                lNotifySinkID = -1;
  79.     IAgent               *pAgent;
  80.     IAgentCharacter    *pGenie = NULL;
  81.     IAgentCharacter       *pMerlin = NULL;
  82.     AgentNotifySink       *pSink = NULL;
  83.     
  84.  
  85.     // Initialize the app
  86.  
  87.     if (!InitAgent(&pAgent, &lNotifySinkID, &pSink))
  88.         return -1;
  89.  
  90.     try {
  91.  
  92.         // Load the characters
  93.  
  94.         ahRes = LoadCharacter(pAgent, kpwszGenie, &lGenieID, &pGenie);
  95.         ahRes = LoadCharacter(pAgent, kpwszMerlin, &lMerlinID, &pMerlin);
  96.  
  97.         // Position them
  98.  
  99.         ahRes = pGenie->MoveTo(0, 100, 0, &lRequestID);
  100.         ahRes = pMerlin->MoveTo(200, 100, 0, &lRequestID);
  101.  
  102.         // Show them
  103.  
  104.         ahRes = pGenie->Show(FALSE, &lRequestID);
  105.         ahRes = pMerlin->Show(FALSE, &lRequestID);
  106.  
  107.         // Have Genie gesture towards Merlin
  108.  
  109.         ahRes = pGenie->GestureAt(150, 100, &lRequestID);
  110.  
  111.         // And have Genie say hello to Merlin
  112.  
  113.         bszSpeak = SysAllocString(L"Hi there Merlin.");
  114.  
  115.         ahRes = pGenie->Speak(bszSpeak, NULL, &lWaitID);
  116.  
  117.         SysFreeString(bszSpeak);
  118.         bszSpeak = NULL;
  119.  
  120.         // Make Merlin wait for Genie to finish speaking
  121.  
  122.         ahRes = pMerlin->Wait(lWaitID, &lRequestID);
  123.  
  124.         // Have Merlin gesture towards Genie
  125.  
  126.         ahRes = pMerlin->GestureAt(0, 100, &lRequestID);
  127.  
  128.         // And then speak back to Genie
  129.  
  130.         bszSpeak = SysAllocString(L"Hi Genie.  See you later");
  131.  
  132.         ahRes = pMerlin->Speak(bszSpeak, NULL, &g_lDone);
  133.  
  134.         SysFreeString(bszSpeak);
  135.         bszSpeak = NULL;
  136.  
  137.     }
  138.     catch (HRESULT hResError) {
  139.  
  140.         hRes = hResError;
  141.  
  142.         wsprintf(szError, _T("An error occurred in Microsoft Agent, code = 0x%x"), hRes);
  143.  
  144.         MessageBox(NULL, 
  145.                    szError, 
  146.                    kpszAppTitle, 
  147.                    MB_OK | MB_ICONERROR);
  148.  
  149.         SysFreeString(bszSpeak);
  150.     }
  151.  
  152.     // Start the message loop.  A WM_QUIT message will be posted
  153.     // when we get the RequestComplete notification from Microsoft Agent.
  154.  
  155.     if (SUCCEEDED(hRes)) {
  156.         while (GetMessage(&msg, NULL, 0, 0) > 0)
  157.             DispatchMessage(&msg);
  158.     }
  159.  
  160.     // Release the character interfaces.  NOTE:  releasing the character
  161.     // interface does NOT make the character go away.  You must
  162.     // call Unload.
  163.  
  164.     if (pGenie) {
  165.         pGenie->Release();
  166.         pAgent->Unload(lGenieID);
  167.     }
  168.     
  169.     if (pMerlin) {
  170.         pMerlin->Release();
  171.         pAgent->Unload(lMerlinID);
  172.     }
  173.  
  174.     // Release the notify sink
  175.  
  176.     if (pSink) {
  177.         if (lNotifySinkID != -1)
  178.             pAgent->Unregister(lNotifySinkID);
  179.  
  180.         pSink->Release();
  181.     }
  182.  
  183.     // We're done
  184.  
  185.     pAgent->Release();
  186.  
  187.     OleUninitialize();
  188.  
  189.     return 0;
  190. }
  191.  
  192.  
  193. // This function checks to see if the version of Microsoft Agent
  194. // installed on the user's system is compatible with the version
  195. // we compiled with, i.e. it's version is greater than or equal to
  196. // constants defined in AgentServer.h.  Microsoft Agent guarantees
  197. // backward compatibility.
  198.  
  199. BOOL IsValidAgentVersion(IAgent *pAgent) {
  200.  
  201.     HRESULT hRes;
  202.     IDispatch *pdAgent = NULL;
  203.     ITypeInfo *pTypeInfo = NULL;
  204.     ITypeLib *pTypeLib = NULL;
  205.     TLIBATTR *pTypeLibAttr = NULL;
  206.     BOOL bValid = FALSE;
  207.     UINT uiIndex;
  208.  
  209.     __try {
  210.  
  211.         // Query for IDispatch
  212.  
  213.         hRes = pAgent->QueryInterface(IID_IDispatch, (LPVOID *)&pdAgent);
  214.  
  215.         if (FAILED(hRes))
  216.             __leave;
  217.  
  218.         // Get the TypeInfo
  219.  
  220.         hRes = pdAgent->GetTypeInfo(0, 0, &pTypeInfo);
  221.  
  222.         if (FAILED(hRes))
  223.             __leave;
  224.  
  225.         // Get it's containing TypeLib
  226.  
  227.         hRes = pTypeInfo->GetContainingTypeLib(&pTypeLib, &uiIndex);
  228.  
  229.         if (FAILED(hRes))
  230.             __leave;
  231.  
  232.         // Get the attributes of the TypeLib
  233.  
  234.         hRes = pTypeLib->GetLibAttr(&pTypeLibAttr);
  235.  
  236.         if (FAILED(hRes))
  237.             __leave;
  238.  
  239.         // Check the major and minor versions of the type library
  240.         // to those in AgentServer.h.
  241.  
  242.         if ((pTypeLibAttr->wMajorVerNum > AGENT_VERSION_MAJOR) ||
  243.             ((pTypeLibAttr->wMajorVerNum == AGENT_VERSION_MAJOR) &&
  244.              (pTypeLibAttr->wMinorVerNum >= AGENT_VERSION_MINOR)))
  245.             bValid = TRUE;
  246.  
  247.     }
  248.     __finally {
  249.     }
  250.  
  251.     if (pTypeLib) {
  252.  
  253.         if (pTypeLibAttr)
  254.             pTypeLib->ReleaseTLibAttr(pTypeLibAttr);
  255.  
  256.         pTypeLib->Release();
  257.     }
  258.  
  259.     if (pTypeInfo)
  260.         pTypeInfo->Release();
  261.  
  262.     if (pdAgent)
  263.         pdAgent->Release();
  264.  
  265.     return bValid;
  266. }
  267.  
  268.  
  269. BOOL InitAgent(IAgent **ppAgent, 
  270.                long *plSinkID, 
  271.                AgentNotifySink **ppSink) {
  272.  
  273.     HRESULT    hRes;
  274.     _TCHAR    szError[256];
  275.  
  276.     // Initialize OLE
  277.  
  278.     if (FAILED(OleInitialize(NULL))) {
  279.         MessageBox(NULL, 
  280.                    _T("There was an error initializing OLE."), 
  281.                    kpszAppTitle, 
  282.                    MB_OK | MB_ICONERROR);
  283.         return FALSE;
  284.     }
  285.  
  286.     // Create an instance of the Agent server
  287.  
  288.     hRes = CoCreateInstance(CLSID_AgentServer,
  289.                             NULL,
  290.                             CLSCTX_SERVER,
  291.                             IID_IAgent,
  292.                             (LPVOID *)ppAgent);
  293.     if (FAILED(hRes)) {
  294.  
  295.         wsprintf(szError, _T("There was an error initializing Microsoft Agent, code = 0x%x"), hRes);
  296.  
  297.         MessageBox(NULL, 
  298.                    szError, 
  299.                    kpszAppTitle, 
  300.                    MB_OK | MB_ICONERROR | MB_TOPMOST);
  301.         return FALSE;
  302.     }
  303.  
  304.     // Check to see if it is a compatible version
  305.  
  306.     if (!IsValidAgentVersion(*ppAgent)) {
  307.         (*ppAgent)->Release();
  308.         *ppAgent = NULL;
  309.         MessageBox(NULL,
  310.                    _T("The version of Microsoft Agent installed on this system is out of date.\nUpgrade to a new version of Microsoft Agent."),
  311.                    kpszAppTitle,
  312.                    MB_OK | MB_ICONEXCLAMATION | MB_TOPMOST);
  313.         return FALSE;
  314.     }
  315.  
  316.     // Create a notify sink
  317.  
  318.     *ppSink = new AgentNotifySink;
  319.  
  320.     if (*ppSink == NULL) {
  321.  
  322.         MessageBox(NULL, 
  323.                    _T("Out of memory!"), 
  324.                    kpszAppTitle, 
  325.                    MB_OK | MB_ICONERROR | MB_TOPMOST);
  326.  
  327.         return FALSE;
  328.     }
  329.  
  330.     (*ppSink)->AddRef();
  331.  
  332.     // And register it with Microsoft Agent
  333.  
  334.     hRes = (*ppAgent)->Register((IUnknown *)(*ppSink), plSinkID);
  335.  
  336.     if (FAILED(hRes))
  337.         return FALSE;
  338.     else
  339.         return TRUE;
  340. }
  341.  
  342.  
  343. HRESULT LoadCharacter(IAgent *pAgent, 
  344.                       LPWSTR pwszPath, 
  345.                       long *plID, 
  346.                       IAgentCharacter **ppCharacter) {
  347.  
  348.     VARIANT        vPath;
  349.     IDispatch  *pdCharacter;
  350.     HRESULT        hRes;
  351.     long        lRequestID;
  352.  
  353.     // Create a VARIANT for the path
  354.  
  355.     VariantInit(&vPath);
  356.  
  357.     vPath.vt = VT_BSTR;
  358.     vPath.bstrVal = SysAllocString(pwszPath);
  359.  
  360.     if (vPath.bstrVal == NULL)
  361.         return E_OUTOFMEMORY;
  362.  
  363.     // Load the character
  364.  
  365.     hRes = pAgent->Load(vPath, plID, &lRequestID);
  366.  
  367.     if (FAILED(hRes))
  368.         return hRes;
  369.  
  370.     // Get it's dispinterface
  371.  
  372.     hRes = pAgent->GetCharacter(*plID, &pdCharacter);
  373.  
  374.     if (FAILED(hRes))
  375.         return hRes;
  376.  
  377.     // Query for IAgentCharacter
  378.  
  379.     hRes = pdCharacter->QueryInterface(IID_IAgentCharacter, (LPVOID *)ppCharacter);
  380.  
  381.     // Release the IDispatch
  382.  
  383.     pdCharacter->Release();
  384.  
  385.     return hRes;
  386. }
  387.