home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / WinCE / SDKWindowsCE / AutoPC / apcsdk10.exe / data1.cab / Win32_Samples / win32 / srapp / app.cpp next >
Encoding:
C/C++ Source or Header  |  1999-05-13  |  20.3 KB  |  736 lines

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2.  
  3. Copyright (c) 1998 Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     app.cpp
  8.  
  9. Abstract:
  10.  
  11.     SR App sample main application class implementation.
  12.  
  13. Environment:
  14.  
  15.     AutoPC
  16.  
  17. -------------------------------------------------------------------*/
  18. #include <Windows.h>
  19. #include <asfc.h>           
  20. #include <ascmnctl.h>  
  21. #include <keypad.h>
  22. #include <apcdebug.h>
  23.  
  24. #include "resource.h"
  25. #include "appsink.h"
  26. #include "app.h"
  27.  
  28. // macro to release an interface pointer and set it to zero
  29. #define RELEASE_IF(i)\
  30. if(i){\
  31.     i->Release();\
  32.     i=NULL; }
  33.  
  34. //------------------------------------------------------------------------------
  35. //
  36. // Main application Class
  37. //
  38. //--------------------------------------------------------------------------
  39.  
  40. //+-------------------------------------------------------------------------
  41. //
  42. //    Function: CSRApp::CSRApp
  43. //
  44. //    Synopsis: Contructor for CSRApp 
  45. //
  46. //    Arguments:     hInst -     Instance handle
  47. //                
  48. //---------------------------------------------------------------------------
  49. CSRApp::CSRApp( HINSTANCE hInst)
  50. {
  51.  
  52.     // Sinks
  53.     m_pFormEventSink    = NULL;
  54.     m_pAppMessageSink    = NULL;
  55.     m_pAppEventSink        = NULL;
  56.  
  57.     m_bstrAppName        = NULL;
  58.  
  59.     // Forms Manager/etc.
  60.     m_pManage            = NULL;          
  61.     m_pActiveForms        = NULL;        
  62.     m_pFmSys            = NULL;              
  63.  
  64.     m_hInst                = hInst;
  65.     m_hFC                = NULL;                
  66.     m_xres                = NULL;                
  67.     m_yres                = NULL;                
  68.     
  69.     // Forms
  70.     m_pMainForm            = NULL;
  71.     m_pColorsForm        = NULL;
  72.     m_pNumbersForm        = NULL;
  73.  
  74.     // Controls
  75.     m_pPLBMainFormMenu    = NULL;
  76.     m_pNumbersLabel        = NULL;
  77.  
  78.     // Speech and voice menus
  79.     m_pSpeech            = NULL;
  80.     m_pVMNumbersForm    = NULL;
  81.     m_pVMColorsForm        = NULL;
  82.  
  83.     // Init COM
  84.     CoInitializeEx( NULL, COINIT_MULTITHREADED );
  85.     m_idThread = GetCurrentThreadId();  // save the id of the main thread
  86. }
  87.  
  88. //+-------------------------------------------------------------------------
  89. //
  90. //    Function: CSRApp::~CSRApp
  91. //
  92. //    Synopsis: Destructor for CSRApp 
  93. //
  94. //    Arguments: void
  95. //                
  96. //---------------------------------------------------------------------------
  97. CSRApp::~CSRApp()
  98. {
  99.     if (m_pManage){
  100.         m_pManage->DeregisterStartedApplication(m_hFC, m_bstrAppName);
  101.     }
  102.  
  103.     // Release forms (uses macro defined at top of file)
  104.  
  105.     if(m_pMainForm) m_pMainForm->Close();
  106.     RELEASE_IF(m_pMainForm)
  107.  
  108.     if(m_pColorsForm) m_pColorsForm->Close();
  109.     RELEASE_IF(m_pColorsForm)
  110.  
  111.     if(m_pNumbersForm) m_pNumbersForm->Close();
  112.     RELEASE_IF(m_pNumbersForm)
  113.  
  114.     // Release controls
  115.     RELEASE_IF(m_pPLBMainFormMenu)
  116.     RELEASE_IF(m_pNumbersLabel)
  117.     
  118.     RELEASE_IF(m_pVMNumbersForm)
  119.     RELEASE_IF(m_pVMColorsForm)
  120.     RELEASE_IF(m_pSpeech)
  121.     
  122.     RELEASE_IF(m_pFmSys)
  123.     RELEASE_IF(m_pActiveForms)
  124.     RELEASE_IF(m_pManage)
  125.  
  126.     RELEASE_IF(m_pFormEventSink)
  127.     RELEASE_IF(m_pAppMessageSink)
  128.     RELEASE_IF(m_pAppEventSink)
  129.  
  130.     if(m_bstrAppName)
  131.     {
  132.         SysFreeString(m_bstrAppName);
  133.         m_bstrAppName = NULL;
  134.     }
  135.  
  136.     if(m_bstrNoColors)
  137.     {
  138.         SysFreeString(m_bstrNoColors);
  139.         m_bstrNoColors = NULL;
  140.     }
  141.  
  142.     if(m_bstrNoColorsTitle)
  143.     {
  144.         SysFreeString(m_bstrNoColorsTitle);
  145.         m_bstrNoColorsTitle = NULL;
  146.     }
  147.  
  148.     UnInitASFormsManager(); // uninitialize the forms manager
  149.     CoUninitialize();       // uninitialize COM
  150. }
  151.  
  152. //+-------------------------------------------------------------------------
  153. //
  154. //    Function: CSRApp::Init
  155. //
  156. //    Synopsis: Initialization for CSRApp 
  157. //
  158. //    Arguments: void
  159. //
  160. //  Returns: TRUE on success
  161. //
  162. //---------------------------------------------------------------------------
  163. BOOL 
  164. CSRApp::Init()
  165. {
  166.     HRESULT    hr;
  167.  
  168.     DEBUGCHK(g_pApp);
  169.  
  170.     //    get the app name from the resource script
  171.     if(!LoadBSTR(STR_APP_SHELL_NAME, &m_bstrAppName))
  172.         return FALSE;
  173.  
  174.     // Allocate BSTRs for other strings we use in program
  175.     if(!LoadBSTR(IDS_NOCOLORS, &m_bstrNoColors))
  176.         return FALSE;
  177.  
  178.     if(!LoadBSTR(IDS_NOCOLORS_TITLE, &m_bstrNoColorsTitle))
  179.         return FALSE;
  180.  
  181.     m_bstrNumbers = SysAllocStringLen(NULL, 50);
  182.     if(!m_bstrNumbers)
  183.         return FALSE;
  184.     
  185.     InitASFormsManager();   // Initialize the forms manager
  186.  
  187.     hr = CreateSinks();
  188.     if(FAILED(hr))
  189.         return FALSE;
  190.     DEBUGMSG(ZONE_VERBOSE, (L"SRApp: Sinks Created.\n"));
  191.  
  192.     hr = GetFormsManager();
  193.     if(FAILED(hr)) 
  194.         return FALSE;
  195.     DEBUGMSG(ZONE_VERBOSE, (L"SRApp: Got Forms manager.\n"));
  196.  
  197.     hr = CreateForms();
  198.     if(FAILED(hr)) 
  199.         return FALSE;
  200.     DEBUGMSG(ZONE_VERBOSE, (L"SRApp: Created forms.\n"));
  201.  
  202.     // Register the application with the forms manager. 
  203.     hr = m_pManage->RegisterStartedApplication(m_hFC, m_bstrAppName, 0, 0);
  204.     if(FAILED(hr)) 
  205.         return FALSE;
  206.     DEBUGMSG(ZONE_VERBOSE, (L"SRApp: Application registered.\n"));
  207.  
  208.     // move app to foreground
  209.     hr = m_pManage->MoveAppToForeground(GetCurrentProcessId(), 0, 0);
  210.     if(FAILED(hr))
  211.         return FALSE;
  212.     DEBUGMSG(ZONE_VERBOSE, (L"SRApp: Application brought to foreground.\n"));
  213.  
  214.     // Create the voice menu that will be used for or "Listen to Numbers" form
  215.     // Don't try and create the colors voice menu until the user selects that option
  216.     // from the main form menu
  217.     hr = CreateNumbersVoiceMenu();
  218.     if(FAILED(hr)) 
  219.         return FALSE;
  220.     
  221.     // Make the class message sink and the event sink for the app.
  222.     // This is so we can take direct key presses and process them.
  223.     hr = m_pManage->put_ClassMsgSink(m_pAppMessageSink);
  224.     if(FAILED(hr))
  225.         return FALSE;        
  226.     DEBUGMSG(ZONE_VERBOSE, (L"SRApp: App message sink attached to Forms Manager.\n"));
  227.  
  228.     hr = m_pManage->put_EventSink(m_pAppEventSink);
  229.     if(FAILED(hr)) 
  230.         return FALSE;
  231.     DEBUGMSG(ZONE_VERBOSE, (L"SRApp: Event sink attached to Forms Manager.\n"));
  232.  
  233.     if (m_pActiveForms && m_pMainForm)
  234.         m_pActiveForms->SetFocus(m_pMainForm);
  235.  
  236.     return TRUE;
  237. }
  238.  
  239. //+-------------------------------------------------------------------------
  240. //
  241. //    Function: CSRApp::CreateMainForm
  242. //
  243. //    Synopsis: Create the main form of this application
  244. //
  245. //    Arguments:     void
  246. //
  247. //     Returns:  S_OK on success
  248. //                
  249. //---------------------------------------------------------------------------
  250. HRESULT    
  251. CSRApp::CreateForms()
  252. {
  253.     BSTR     bstr;
  254.     HRESULT hr;
  255.  
  256.     bstr = NULL;
  257.  
  258.     //
  259.     // Create Main Menu form
  260.     //
  261.     DEBUGCHK(!m_pMainForm);
  262.     DEBUGCHK(m_pFormEventSink);
  263.  
  264.     // Load our form from a Dialog resource.  LoadFormResource CoCreates
  265.     // the form for us, and returns an IDispatch interface to it.
  266.     IDispatch* pDispMainForm = NULL;
  267.     hr = m_pManage->LoadFormResource(
  268.         (OLE_HANDLE)m_hInst,            // Application's instance handle
  269.         IDF_MAIN,                        // Forms ID
  270.         (IDispatch **)&pDispMainForm,    // Interface target
  271.         m_pFormEventSink);                // Event sink to attach to form
  272.  
  273.     if(FAILED(hr))
  274.         return E_FAIL;
  275.  
  276.     // Get the IASForm interface from our new form
  277.     hr = pDispMainForm->QueryInterface(IID_ASFORM, (PVOID *)&m_pMainForm);
  278.     if(FAILED(hr))
  279.         return E_FAIL;
  280.  
  281.     // Get a pointer to the menu Power List Box on the main form
  282.     IDispatch* pDispMainFormMenu = NULL;    
  283.     hr = m_pMainForm->ItemFromID(IDC_PLB_MENU, (IDispatch **)&pDispMainFormMenu);
  284.     if(FAILED(hr))
  285.         return E_FAIL;
  286.     
  287.     // Ask for the IASPowerListBox interface
  288.     hr = pDispMainFormMenu->QueryInterface(IID_ASPOWERLISTBOX, (PVOID *)&m_pPLBMainFormMenu);
  289.     if(FAILED(hr))
  290.         return E_FAIL;
  291.  
  292.     // Release the IDispatch interface we got from ItemFromID
  293.     pDispMainFormMenu->Release();
  294.  
  295.     // Add items from our menu resource to our main PLB menu
  296.     hr = m_pPLBMainFormMenu->AddItemsFromResource(
  297.         m_hInst,                        // Application's instance
  298.         MAKEINTRESOURCE(IDM_MAIN),         // menu resource
  299.         NULL);                            // menu state (not used)
  300.  
  301.     if(FAILED(hr))
  302.         return E_FAIL;
  303.  
  304.     // We have to Start our form after everything is set up
  305.     hr = m_pManage->Start(pDispMainForm);
  306.     if(FAILED(hr))
  307.         return E_FAIL;
  308.  
  309.     // Release our main form's IDispatch (we release the main form's IASForm 
  310.     // In the app class destructor)
  311.     pDispMainForm->Release();
  312.  
  313.     //
  314.     // Create Listen to Colors form
  315.     //
  316.     DEBUGCHK(!m_pColorsForm);
  317.     DEBUGCHK(m_pFormEventSink);
  318.  
  319.     IDispatch* pDispColorsForm = NULL;
  320.     hr = m_pManage->LoadFormResource(
  321.         (OLE_HANDLE)m_hInst,            // Application's instance handle
  322.         IDF_COLORS,                        // Form ID
  323.         (IDispatch **)&pDispColorsForm,    // Interface target
  324.         m_pFormEventSink);                // Sink to attach on creation
  325.  
  326.     if(FAILED(hr))
  327.         return E_FAIL;
  328.  
  329.     // Get the IASForm interface for our new form
  330.     hr = pDispColorsForm->QueryInterface(IID_ASFORM, (PVOID *)&m_pColorsForm);
  331.     if(FAILED(hr))
  332.         return E_FAIL;
  333.  
  334.     // Have to start the form after everything is set up
  335.     hr = m_pManage->Start(pDispColorsForm);
  336.     if(FAILED(hr))
  337.         return E_FAIL;
  338.  
  339.     // Release Colors form's IDispatch (release IASForm interface to Colors Form
  340.     // in app class' destructor)
  341.     pDispColorsForm->Release();
  342.  
  343.     // 
  344.     // Create Listen to Numbers form
  345.     //
  346.     DEBUGCHK(!m_pNumbersForm);
  347.     DEBUGCHK(m_pFormEventSink);
  348.  
  349.     IDispatch* pDispNumbersForm = NULL;
  350.     hr = m_pManage->LoadFormResource(
  351.         (OLE_HANDLE)m_hInst,            // Application's instance handle
  352.         IDF_NUMBERS,                    // Form ID
  353.         (IDispatch **)&pDispNumbersForm,// Interface target
  354.         m_pFormEventSink);                // Sink to attach to new form
  355.  
  356.     if(FAILED(hr))
  357.         return E_FAIL;
  358.  
  359.     // Get the IASForm interface to our ListenToNumbers form
  360.     hr = pDispNumbersForm->QueryInterface(IID_ASFORM, (PVOID *)&m_pNumbersForm);
  361.     if(FAILED(hr))
  362.         return E_FAIL;
  363.  
  364.     // Get an interface to the Label(static text) control on the Listen to numbers
  365.     // form 
  366.     IDispatch* pDispNumbersLabel = NULL;
  367.     m_pNumbersForm->ItemFromID(IDC_LABEL_NUMBERS, (IDispatch **)&pDispNumbersLabel);
  368.  
  369.     // Get the ASLabel interface to the label control
  370.     hr = pDispNumbersLabel->QueryInterface(IID_ASLABEL, (PVOID *)&m_pNumbersLabel);
  371.     if(FAILED(hr))
  372.         return E_FAIL;
  373.  
  374.     pDispNumbersLabel->Release();
  375.  
  376.     // Startup our numbers form
  377.     hr = m_pManage->Start(pDispNumbersForm);
  378.     if(FAILED(hr))
  379.         return E_FAIL;
  380.  
  381.     pDispNumbersForm->Release();
  382.  
  383.     return NOERROR;
  384. }
  385.  
  386. //+-------------------------------------------------------------------------
  387. //
  388. //    Function: CSRApp::LoadBSTR
  389. //
  390. //    Synopsis: Load a string and and put it into BSTR
  391. //
  392. //    Arguments:     uId     -     Resource id of string to load
  393. //                pBStr   -   Where to return the BSTR
  394. //
  395. //     Returns:  TRUE for success
  396. //                
  397. //---------------------------------------------------------------------------
  398. BOOL CSRApp::LoadBSTR(UINT uID, BSTR* pBStr)
  399. {
  400.     if(!pBStr)
  401.         return    FALSE;
  402.  
  403.     WCHAR wszTemp[128];
  404.     int iStringLen = 128;
  405.  
  406.     if((iStringLen = LoadStringW(m_hInst, uID, wszTemp, iStringLen)) == 0)
  407.     {
  408.         return(FALSE);
  409.     }        
  410.     
  411.     *pBStr = SysAllocString(wszTemp);
  412.     // see if the string was allocated
  413.     if (!(*pBStr))
  414.     {
  415.         return(FALSE);
  416.     }
  417.  
  418.     return(TRUE);
  419. }
  420.  
  421. //+-------------------------------------------------------------------------
  422. //
  423. //    Function: CSRApp::CreateSinks
  424. //
  425. //    Synopsis: Create default event and message sinks for the application
  426. //        (attached to the forms manager)
  427. //
  428. //    Arguments:     void
  429. //
  430. //     Returns:  S_OK on success
  431. //                
  432. //---------------------------------------------------------------------------
  433. HRESULT    CSRApp::CreateSinks()
  434. {
  435.     HRESULT             hr;
  436.     CFormEventSink*        pFormEventSink;
  437.     CAppMessageSink*    pMessageSink;
  438.     DWORD                 dwMainThreadId;
  439.  
  440.     pFormEventSink         = NULL;
  441.     pMessageSink           = NULL; 
  442.     dwMainThreadId         = GetCurrentThreadId();
  443.  
  444.     // Create an instance of our FormEventSink object, which implements IASEventSink,
  445.     // that we will attach to each of the form's we create. (ref count = 0)
  446.     pFormEventSink = new CFormEventSink(dwMainThreadId);  // create an event sink object
  447.  
  448.     if(!pFormEventSink) 
  449.         return E_OUTOFMEMORY;
  450.  
  451.     // Get an IASEventSink pointer from our object (ref count = 1)
  452.     hr = pFormEventSink->QueryInterface(IID_ASEVENTSINK, (PVOID *) &m_pFormEventSink);
  453.     if(FAILED(hr))
  454.     {
  455.         delete pFormEventSink;
  456.         return hr;
  457.     }
  458.  
  459.     // Create an instance of our AppMessageSink object, which implements IASClassMsgSink
  460.     // and IASEventSink, that we will attach to our forms manager. (ref count = 0)
  461.     pMessageSink = new CAppMessageSink(dwMainThreadId);  // create a message sink object
  462.     if(!pMessageSink) 
  463.         return E_OUTOFMEMORY;
  464.     
  465.     // Get an IASClassMsgSink pointer from our AppMessageSink object (ref count = 1)
  466.     hr = pMessageSink->QueryInterface(IID_ASCLASSMSGSINK, (PVOID *) &m_pAppMessageSink);
  467.     if(FAILED(hr))
  468.     {
  469.         delete pMessageSink;
  470.         return hr;
  471.     }
  472.  
  473.     // Get an IASEventSink pointer from our AppMessageSink object (ref count = 2)
  474.     hr = pMessageSink->QueryInterface(IID_ASEVENTSINK, (PVOID *) &m_pAppEventSink);
  475.     if (FAILED(hr))
  476.         return hr;
  477.  
  478.     return NOERROR;
  479. }
  480.  
  481.  
  482. //+-------------------------------------------------------------------------
  483. //
  484. //    Function: CApp::CreateNumbersVoiceMenu
  485. //
  486. //    Synopsis: Creates a voice menu containing 0-9 from a menu resource.    
  487. //
  488. //    Arguments:     void
  489. //
  490. //     Returns:  S_OK on success
  491. //                
  492. //---------------------------------------------------------------------------
  493. HRESULT    
  494. CSRApp::CreateNumbersVoiceMenu()
  495. {
  496.     HRESULT    hr;
  497.  
  498.     DEBUGCHK(m_pManage);
  499.     DEBUGCHK(!m_pSpeech);
  500.  
  501.     // Get our speech object from the form's manager
  502.     m_pManage->get_Speech(&m_pSpeech);
  503.  
  504.     if(!m_pSpeech)
  505.         return E_NOTIMPL;
  506.  
  507.     // Declare and fill in the necessary fields of a VCMDNAME structure
  508.     VCMDNAME vnNumbers;
  509.     memset(&vnNumbers, NULL, sizeof(VCMDNAME));            // Clear structure    
  510.     lstrcpy(vnNumbers.szApplication, L"SR App");        // Put in our application name
  511.     lstrcpy(vnNumbers.szState, L"SR App - Numbers");    // Put in voice menu name
  512.  
  513.     // First we create a voice menu, then we use AddVMenuCommandsFromResource to 
  514.     // to add items to it from a menu resource
  515.     hr = m_pSpeech->CreateVMenu(
  516.         NULL,                        // Null since we don't create a voice command
  517.         &vnNumbers,                    // Pointer to our VCMDNAME structure
  518.         m_hInst,                    // Application's instance handle
  519.         0,                            // Table size (0 since we aren't creating and words here
  520.         NULL,                        // Pointer to GrammerID table
  521.         0,                            // Flags (not APCSPCH_VM_USEEXISTING since we want a fresh VMenu)
  522.         &m_pVMNumbersForm);            // Interface to our new voice menu
  523.     if(FAILED(hr))
  524.         return E_FAIL;
  525.  
  526.     // Add Voice Menu Commands from a resource script to our newly created, blank, VoiceMenu
  527.     hr = m_pSpeech->AddVMenuCommandsFromResource(
  528.         m_pVMNumbersForm,            // Interface to our voice menu
  529.         m_hInst,                    // App instance handle
  530.         MAKEINTRESOURCE(IDVM_NUMBERS),//Resource ID
  531.         NULL,                        // Menu State (not used in this case)
  532.         0);                            // Flags (could be APCSPCH_VM_USEEXISTING if we were making this
  533.     if(FAILED(hr))                    // call several times to "build" a menu)
  534.         return E_FAIL;
  535.  
  536.     // Attach the voice menu to our Listen to Numbers form
  537.     hr = m_pNumbersForm->put_VoiceMenu(m_pVMNumbersForm);
  538.     if(FAILED(hr))
  539.         return E_FAIL;
  540.  
  541.     return S_OK;
  542. }
  543.  
  544. //+-------------------------------------------------------------------------
  545. //
  546. //    Function: CApp::CreateColorsVoiceMenu
  547. //
  548. //    Synopsis: Creates a voice menu containing the eight colors support by
  549. //        the Auto PC v1 devices.  First checks to see if all the words have 
  550. //        Speaker Dependent or Independent templates, if not, it returns E_FAIL.
  551. //
  552. //    Arguments:     void
  553. //
  554. //     Returns:  S_OK on success
  555. //                
  556. //---------------------------------------------------------------------------
  557. HRESULT
  558. CSRApp::CreateColorsVoiceMenu()
  559. {
  560.     HRESULT hr;
  561.  
  562.     // Check to see if all the words have been trained already
  563.     if(!IsColorWordsTrained()) return E_FAIL;
  564.  
  565.     // Declare and fill in the necessary fields of a VCMDNAME structure
  566.     VCMDNAME vnColors;
  567.     memset(&vnColors, NULL, sizeof(VCMDNAME));        // Clear the structure
  568.     lstrcpy(vnColors.szApplication, L"SR App");        // Add the application name
  569.     lstrcpy(vnColors.szState, L"SR App - Colors");    // Add the voice menu's name
  570.  
  571.     // Create a blank voice menu
  572.     hr = m_pSpeech->CreateVMenu(
  573.         NULL,                        // Null since we don't create a voice command
  574.         &vnColors,                    // Pointer to our VCMDNAME structure
  575.         m_hInst,                    // Application's instance handle
  576.         0,                            // Table size (0 since we aren't creating and words here
  577.         NULL,                        // Pointer to GrammerID table
  578.         0,                            // Flags (not APCSPCH_VM_USEEXISTING since we want a fresh VMenu)
  579.         &m_pVMColorsForm);            // Interface to our new voice menu
  580.     if(FAILED(hr))
  581.         return E_FAIL;
  582.  
  583.     // Add Voice Menu Commands from a resource script to our newly created, blank, VoiceMenu
  584.     hr = m_pSpeech->AddVMenuCommandsFromResource(
  585.         m_pVMColorsForm,            // Interface to our voice menu
  586.         m_hInst,                    // App instance handle
  587.         MAKEINTRESOURCE(IDVM_COLORS),//Resource ID
  588.         NULL,                        // Menu State (not used in this case)
  589.         0);                            // Flags, 0 since we want a fresh menu
  590.     if(FAILED(hr))
  591.         return E_FAIL;
  592.  
  593.     // Add "End" to our voice menu
  594.     hr = m_pSpeech->AddVMenuCommandsFromResource(
  595.         m_pVMColorsForm,            // Interface to our voice menu
  596.         m_hInst,                    // App instance handle
  597.         MAKEINTRESOURCE(IDVM_COLORS_END),//Resource ID
  598.         0,                            // Menu State (not used here)
  599.         APCSPCH_VM_USEEXISTING);    // Flags, USEEXISTING meands don't clear the voice menu, just add
  600.     if(FAILED(hr))                    // the items to it
  601.         return E_FAIL;
  602.  
  603.     // Attach the voice menu to the colors form
  604.     hr = m_pColorsForm->put_VoiceMenu(m_pVMColorsForm);
  605.     if(FAILED(hr))
  606.         return E_FAIL;
  607.  
  608.     return NOERROR;
  609.  
  610. }
  611.  
  612. BOOL
  613. CSRApp::IsColorWordsTrained()
  614. {
  615.     IVCmdUserWord* pVCmdUserWord;
  616.     DWORD dwQPFlags;
  617.  
  618.     // Get the SAPI (Speech Application Programming Interface) IVCmdUserWord 
  619.     // interface from our speech object so we can use its methods
  620.     HRESULT hr = m_pSpeech->QuerySpeechInterface(IID_IVCmdUserWord, (PVOID *)&pVCmdUserWord);
  621.     if(FAILED(hr))
  622.         return FALSE;
  623.  
  624.     WCHAR* szColors[8] =  { L"Black", L"Red", L"Green", L"Blue", 
  625.                             L"Yellow", L"Violet", L"Cyan", L"White" };
  626.  
  627.     for(int i=0; i < 8; i++)
  628.     {
  629.         // QueryPhrase tells us what templates are installed on the system
  630.         hr = pVCmdUserWord->QueryPhrase(szColors[i], &dwQPFlags);
  631.  
  632.         // If there is no enabled SpeakerIndependent or SpeakerDependent template,
  633.         // return FALSE
  634.         if( !((dwQPFlags & SRPHRASE_SI) && (dwQPFlags & SRPHRASE_SI_ENABLE)) &&
  635.             !((dwQPFlags & SRPHRASE_SD) && (dwQPFlags & SRPHRASE_SD_ENABLE)) )
  636.         {
  637.             DEBUGMSG(ZONE_VERBOSE, (L"%s template not in system.\n", szColors[i]));
  638.             pVCmdUserWord->Release();
  639.             return FALSE;
  640.         }
  641.     }
  642.  
  643.     pVCmdUserWord->Release();
  644.     return TRUE;
  645. }
  646.  
  647. //+-------------------------------------------------------------------------
  648. //
  649. //    Function: CSRApp::GetFormsManager
  650. //
  651. //    Synopsis: Create a forms manager object and get display dimensions
  652. //                also get the active forms object
  653. //
  654. //    Arguments:     void
  655. //
  656. //     Returns:  S_OK on success
  657. //                
  658. //---------------------------------------------------------------------------
  659. HRESULT    
  660. CSRApp::GetFormsManager()
  661. {
  662.        HRESULT hr;
  663.  
  664.     // Create the forms manager
  665.     hr = CoCreateInstance(
  666.         CLSID_FMMANAGE,            // Forms Manager's class ID
  667.         NULL,                    // Not using COM aggregation
  668.         CLSCTX_INPROC_SERVER,    // Create object in process
  669.         IID_FMMANAGE,             // Get us the IfmManage interface
  670.         (PVOID *) &m_pManage);    // Interface target
  671.  
  672.     if(FAILED(hr))
  673.         return hr;
  674.  
  675.     // Get the FormsContextHandle, which is basically which faceplate the forms
  676.     // manager will show it on (when we support multiple faceplates)
  677.     hr = m_pManage->GetFormsContextHandle(&m_hFC);
  678.     if(FAILED(hr))
  679.         return hr;
  680.  
  681.     // Get IfmSystem interface
  682.     hr = m_pManage->QueryInterface( IID_FMSYSTEM, (PVOID *) &m_pFmSys );
  683.     if(FAILED(hr))
  684.         return hr;
  685.  
  686.     // Get the X and Y resolution of the display we're on
  687.     hr = m_pFmSys->GetFormDisplayCaps( m_hFC, VERTRES, &m_yres);
  688.     if(FAILED(hr))
  689.         return hr;
  690.  
  691.     hr = m_pFmSys->GetFormDisplayCaps( m_hFC, HORZRES, &m_xres);
  692.     if(FAILED(hr))
  693.         return hr;
  694.             
  695.     // Get IASActiveForms interface
  696.     hr = m_pManage->QueryInterface(IID_ASACTIVEFORMS, (PVOID *) &m_pActiveForms);
  697.     if(FAILED(hr))
  698.         return hr;
  699.     
  700.     return NOERROR;
  701. }
  702.  
  703. //+-------------------------------------------------------------------------
  704. //
  705. //    Function: CSRApp::Quit
  706. //
  707. //    Synopsis: Post a WM_QUIT to the main thread
  708. //
  709. //    Arguments: void
  710. //
  711. //     Returns:  void
  712. //
  713. //---------------------------------------------------------------------------
  714.  
  715. void
  716.     CSRApp::Quit()
  717. {
  718.     ::PostThreadMessage(m_idThread, WM_QUIT, 0, 0);
  719.     return;
  720. }
  721.  
  722. void
  723. CSRApp::AddNumber(int iNum)
  724. {
  725.     WCHAR wszNewNumberBuffer[100];
  726.  
  727.     wszNewNumberBuffer[0] = '0';
  728.     wszNewNumberBuffer[0] += iNum;
  729.     wszNewNumberBuffer[1] = NULL;
  730.  
  731.     wcscat(m_bstrNumbers, wszNewNumberBuffer);
  732.     m_pNumbersLabel->put_Caption(m_bstrNumbers);
  733. }
  734.  
  735.  
  736.