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

  1. //--------------------------------------------------------------------------------------------
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  4. //  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  5. //  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  6. //  PARTICULAR PURPOSE.
  7. //
  8. //    Copyright (c) Microsoft Corporation, 1997 All Rights Reserved
  9. //
  10. //    Description:
  11. //        
  12. //        Contains the base application level code and classes for a simple Apollo application
  13. //
  14. //--------------------------------------------------------------------------------------------
  15. #include <Windows.h>        // standard windows header file
  16. #include <asfc.h>            // form and control interfaces
  17. #include <ascmnctl.h>        // common controls
  18. #include <keypad.h>            // so we can use the keypad (WM_REMOTE_KEYDOWN messages)
  19. #include <asstyles.h>
  20.  
  21. // App specific header files
  22. #include "resource.h"        // resource IDs
  23. #include "app.h"            // TTSApp definition
  24.  
  25. //------------------------------------------------------------------------------
  26. //
  27. // Main application Class
  28. //
  29. //--------------------------------------------------------------------------
  30.  
  31. //+-------------------------------------------------------------------------
  32. //
  33. //    Function: CTTSApp::CTTSApp
  34. //
  35. //    Synopsis: Contructor for CTTSApp 
  36. //
  37. //    Arguments:     hInst -     Instance handle
  38. //                
  39. //---------------------------------------------------------------------------
  40. CTTSApp::CTTSApp( HINSTANCE hInst)
  41. {
  42.     //initialize COM
  43.     CoInitializeEx( NULL, COINIT_MULTITHREADED );
  44.  
  45.     //Thread and instance handle
  46.     m_idThread            = GetCurrentThreadId();  // save the id of the main thread
  47.     m_hInst                = hInst;
  48.  
  49.     //Sinks
  50.     m_pFormEventSink    = NULL;
  51.     m_pAppMessageSink    = NULL;
  52.     m_pAppEventSink        = NULL;
  53.  
  54.     //Strings
  55.     m_bszAppName        = NULL;
  56.     m_bszMenuName        = NULL;
  57.     m_bszKeyFeedback    = NULL;
  58.     m_bszVoiceFeedback    = NULL;
  59.     m_bszMore            = NULL;
  60.     m_bszLess            = NULL;
  61.  
  62.     //Forms, form manager, and controls
  63.     m_pManage            = NULL;          
  64.     m_pForm                = NULL;
  65.     m_pListBox            = NULL;
  66.     
  67.     m_hFC                = NULL;                
  68.     m_xres                = NULL;                
  69.     m_yres                = NULL;                
  70.     m_pSpeech            = NULL;
  71.     m_dwKeyFeedback        = NULL;
  72.     m_dwVoiceFeedback    = NULL;
  73.     m_bExiting            = FALSE;
  74. }
  75.  
  76. //+-------------------------------------------------------------------------
  77. //
  78. //    Function: CTTSApp::~CTTSApp
  79. //
  80. //    Synopsis: Destructor for CTTSApp 
  81. //        Releases all interfaces and frees all strings.  Deregisters app with
  82. //        forms manager as well.
  83. //
  84. //    Arguments: void
  85. //                
  86. //---------------------------------------------------------------------------
  87. CTTSApp::~CTTSApp()
  88. {
  89.     //Tell the forms manager to deregister the application
  90.     if (m_pManage) {
  91.         m_pManage->DeregisterStartedApplication(m_hFC, m_bszAppName);
  92.     }
  93.  
  94.     //Delete all the form controls
  95.     DeleteFormControls();
  96.  
  97.     //Close and release the form
  98.     if (m_pForm) {
  99.         m_pForm->Close();
  100.         m_pForm->Release();     
  101.     }
  102.  
  103.     //Free app name string
  104.     if(m_bszAppName) SysFreeString(m_bszAppName);
  105.     if(m_bszMenuName) SysFreeString(m_bszMenuName);
  106.     if(m_bszKeyFeedback) SysFreeString(m_bszKeyFeedback);
  107.     if(m_bszVoiceFeedback) SysFreeString(m_bszVoiceFeedback);
  108.     if(m_bszMore) SysFreeString(m_bszMore);
  109.     if(m_bszLess) SysFreeString(m_bszLess);
  110.  
  111.  
  112.     //Release other interfaces we used
  113.     //Forms manager
  114.     if (m_pManage) m_pManage->Release();
  115.  
  116.     //Event sink attatched to form
  117.     if (m_pFormEventSink) m_pFormEventSink->Release();
  118.  
  119.     //Class msg sink attatched to forms manager
  120.     if (m_pAppMessageSink) m_pAppMessageSink->Release();
  121.  
  122.     //Event sink attatched to forms manager
  123.     if (m_pAppEventSink) m_pAppEventSink->Release();
  124.  
  125.     //Speech interface, thanks for the hard work!
  126.     if (m_pSpeech) m_pSpeech->Release();
  127.  
  128.     UnInitASFormsManager(); // uninitialize the forms manager
  129.     CoUninitialize();       // uninitialize COM
  130. }
  131.  
  132. //+-------------------------------------------------------------------------
  133. //
  134. //    Function: CTTSApp::Init
  135. //
  136. //    Synopsis: Initialization for CTTSApp 
  137. //
  138. //    Arguments: void
  139. //
  140. //  Returns: TRUE on success
  141. //
  142. //---------------------------------------------------------------------------
  143. BOOL CTTSApp::Init(VOID)
  144. {
  145.     HRESULT    hr;
  146.  
  147.     if( g_pApp == NULL ) return    FALSE;
  148.  
  149.     // Allocate strings
  150.     if(!LoadBSTR(STR_APP_SHELL_NAME, &m_bszAppName)) return FALSE;
  151.     if(!LoadBSTR(IDS_MENUNAME, &m_bszMenuName)) return FALSE;
  152.     if(!LoadBSTR(IDS_KEYFEEDBACK, &m_bszKeyFeedback)) return FALSE;
  153.     if(!LoadBSTR(IDS_VOICEFEEDBACK, &m_bszVoiceFeedback)) return FALSE;
  154.     if(!LoadBSTR(IDS_MORE, &m_bszMore)) return FALSE;
  155.     if(!LoadBSTR(IDS_LESS, &m_bszLess)) return FALSE;
  156.  
  157.     // Initialize the forms manager
  158.     hr = InitASFormsManager();   
  159.     if(FAILED(hr)) return FALSE;
  160.  
  161.     hr = CreateSinks();
  162.     if(FAILED(hr)) return FALSE;
  163.     
  164.     hr = GetFormsManager();
  165.     if(FAILED(hr)) return FALSE;
  166.  
  167.     hr = CreateMainForm();
  168.     if(FAILED(hr)) return FALSE;
  169.  
  170.     hr = SpeechInit();
  171.     if(FAILED(hr)) return FALSE;
  172.  
  173.     // Register the application with the forms manager. 
  174.     hr = m_pManage->RegisterStartedApplication(m_hFC, m_bszAppName, 0, 0);
  175.     if(FAILED(hr))    return FALSE;
  176.  
  177.     //Bring it to foreground (if it isn't brought up from shell)
  178.     hr = m_pManage->MoveAppToForeground(GetCurrentProcessId(), 0, 0);
  179.     if(FAILED(hr)) return FALSE;
  180.  
  181.     return TRUE;
  182. }
  183.  
  184. //+-------------------------------------------------------------------------
  185. //
  186. //    Function: CTTSApp::CreateMainForm
  187. //
  188. //    Synopsis: Create the main form of this application
  189. //
  190. //    Arguments:     void
  191. //
  192. //     Returns:  S_OK on success
  193. //                
  194. //---------------------------------------------------------------------------
  195. HRESULT    CTTSApp::CreateMainForm( VOID)
  196. {
  197.     HRESULT hr;
  198.  
  199.     // Create the form
  200.     hr = CoCreateInstance(CLSID_ASFORM, NULL, CLSCTX_INPROC_SERVER,
  201.         IID_ASFORM, (PVOID *) &m_pForm);
  202.     if (FAILED(hr)) goto LReturn;
  203.     
  204.     // initialize the newly created form, attatch m_pFormEventSink
  205.     hr = m_pForm->Init(ID_MAINFORM, NULL, m_pFormEventSink); 
  206.     if (FAILED(hr)) goto LReturn;
  207.     
  208.     hr = m_pForm->put_Caption(m_bszAppName); //add a caption (for titlebar)
  209.     if (FAILED(hr)) goto LReturn;
  210.  
  211.     m_pForm->put_Visible(TRUE);          // make it visible   
  212.  
  213.     // create the forms controls
  214.     hr = CreateFormControls();
  215.     if (FAILED(hr)) goto LReturn;
  216.  
  217.     hr = m_pManage->Start(m_pForm); // start the form
  218.     if (FAILED(hr)) goto LReturn;
  219.  
  220. LReturn:
  221.     if (FAILED(hr)) 
  222.     {           
  223.         // there was an error. Cleanup
  224.         if (m_pForm) 
  225.         {
  226.             m_pForm->Close();   // close the form
  227.             m_pForm->Release();
  228.             m_pForm = NULL;
  229.         }
  230.     }
  231.  
  232.     return(hr);
  233. }
  234.  
  235. //+-------------------------------------------------------------------------
  236. //
  237. //    Function: CTTSApp::SpeechInit
  238. //
  239. //    Synopsis: Initialize the speech for the CApp object
  240. //
  241. //    Arguments:     void
  242. //
  243. //     Returns:  S_OK on success
  244. //                
  245. //---------------------------------------------------------------------------
  246. HRESULT    CTTSApp::SpeechInit(void)
  247. {
  248.     HRESULT hr;
  249.  
  250.     //grab the speech interface from the form
  251.     hr = m_pForm->get_Speech(&m_pSpeech);
  252.     if(FAILED(hr)) return E_FAIL;
  253.  
  254.     hr = GetFeedbackLevels();
  255.     if(FAILED(hr)) return E_FAIL;
  256.     
  257.     //Make sure we get notifications when Speakdone and on Speak progress
  258.     hr = m_pSpeech->SetMsgOptions(NULL, NULL, VTXTF_SPEAKDONE | VTXTF_SPEAK);
  259.     if(FAILED(hr)) return E_FAIL;
  260.  
  261.     return( S_OK);
  262. }
  263.  
  264. //+-------------------------------------------------------------------------
  265. //
  266. //    Function: CTTSApp::GetFeedbackLevels
  267. //
  268. //    Synopsis: Queries the speech interface and gets the current feedback
  269. //        level for Key and Voice 
  270. //
  271. //    Arguments: void
  272. //
  273. //     Returns:  S_OK on success
  274. //                
  275. //---------------------------------------------------------------------------
  276.  
  277. HRESULT CTTSApp::GetFeedbackLevels(void)
  278. {
  279.     HRESULT hr;
  280.     hr = m_pSpeech->QueryFeedbackLevel(&m_dwKeyFeedback, &m_dwVoiceFeedback, NULL, 0);
  281.     return hr;
  282. }
  283.  
  284. //+-------------------------------------------------------------------------
  285. //
  286. //    Function: CTTSApp::SpeakStop
  287. //
  288. //    Synopsis: Stops the speech output
  289. //
  290. //    Arguments:     void
  291. //
  292. //     Returns:  void
  293. //                
  294. //---------------------------------------------------------------------------
  295. void CTTSApp::SpeakStop(VOID)
  296. {
  297.     //Stop speech output
  298.     if (m_pSpeech)
  299.     {
  300.         m_pSpeech->Speak(NULL,0);
  301.     }
  302. }
  303.  
  304.  
  305. //+-------------------------------------------------------------------------
  306. //
  307. //    Function: CTTSApp::SetFocusOnId
  308. //
  309. //    Synopsis: Puts the power list box's focus on specified ID
  310. //
  311. //    Arguments:     long - ID of list box item to give focus
  312. //
  313. //     Returns:  void
  314. //                
  315. //---------------------------------------------------------------------------
  316.  
  317. void CTTSApp::SetFocusOnId(long lId)
  318. {
  319.     m_pListBox->put_FocusId(lId);
  320. }
  321.  
  322. //+-------------------------------------------------------------------------
  323. //
  324. //    Function: CTTSApp::LoadBSTR
  325. //
  326. //    Synopsis: Load a string and and put it into BSTR
  327. //        Only handles strings < 128 chars
  328. //
  329. //    Arguments:     uId     -     Resource id of string to load
  330. //                pBStr   -   Where to return the BSTR
  331. //
  332. //     Returns:  TRUE for success
  333. //                
  334. //---------------------------------------------------------------------------
  335. BOOL CTTSApp::LoadBSTR(UINT uID, BSTR* pBStr)
  336. {
  337.     if(!pBStr)
  338.         return FALSE;
  339.  
  340.     WCHAR wszTemp[128];        //Buffer for resource string
  341.     int iStringLen = 127;
  342.  
  343.     if((iStringLen = LoadStringW(m_hInst, uID, wszTemp, iStringLen)) == 0)
  344.         return(FALSE);
  345.     
  346.     *pBStr = SysAllocString(wszTemp);
  347.  
  348.     // see if the string was allocated
  349.     if (!(*pBStr))
  350.         return(FALSE);
  351.  
  352.     return(TRUE);
  353. }
  354.  
  355. //+-------------------------------------------------------------------------
  356. //
  357. //    Function: CTTSApp::CreateSinks
  358. //
  359. //    Synopsis: Creates Event and Class MSG sink for forms manager, and Even sink
  360. //        for the Form itself.
  361. //
  362. //    Arguments:     void
  363. //
  364. //     Returns:  S_OK on success
  365. //                
  366. //---------------------------------------------------------------------------
  367. HRESULT    CTTSApp::CreateSinks( VOID)
  368. {
  369.     HRESULT             hr = S_OK;
  370.     CFormEventSink *    pFormEventSink = NULL;
  371.     CAppMessageSink    *   pMessageSink = NULL;
  372.  
  373.     pFormEventSink = new CFormEventSink();  // create an event sink object
  374.     if (!pFormEventSink) 
  375.         return E_OUTOFMEMORY;
  376.  
  377.     //Get its IASEventSink interface (Form's Event Sink)
  378.     hr = pFormEventSink->QueryInterface(IID_ASEVENTSINK, (PVOID *) &m_pFormEventSink);
  379.     if (FAILED(hr)) {
  380.         delete pFormEventSink;
  381.         return E_FAIL;
  382.     }
  383.     
  384.     pMessageSink = new CAppMessageSink();  // create a message sink object
  385.     if (!pMessageSink) 
  386.         return E_OUTOFMEMORY;
  387.  
  388.     //Get its IASClassMsgSink interface (Form Manager(App)'s Class Msg Sink)
  389.     hr = pMessageSink->QueryInterface(IID_ASCLASSMSGSINK, (PVOID *) &m_pAppMessageSink);
  390.     if (FAILED(hr)) {
  391.         delete pMessageSink;
  392.         return E_FAIL;
  393.     }
  394.     
  395.     //Get its IASEventSink interface (Form Manager(App)'s Event Sink)
  396.     hr = pMessageSink->QueryInterface(IID_ASEVENTSINK, (PVOID *) &m_pAppEventSink);
  397.     if (FAILED(hr)) {
  398.         delete pMessageSink;
  399.         return E_FAIL;
  400.     }
  401.  
  402.     return(hr);
  403. }
  404.  
  405. //+-------------------------------------------------------------------------
  406. //
  407. //    Function: CTTSApp::GetFormsManager
  408. //
  409. //    Synopsis: Create a forms manager object and get display dimensions
  410. //                also get the active forms object
  411. //
  412. //    Arguments:     void
  413. //
  414. //     Returns:  S_OK on success
  415. //                
  416. //---------------------------------------------------------------------------
  417. HRESULT    CTTSApp::GetFormsManager( VOID)
  418. {
  419.        HRESULT hr;
  420.  
  421.     // Create the forms manager
  422.     hr = CoCreateInstance(
  423.         CLSID_FMMANAGE,            // Class ID
  424.         NULL,                    // Object NOT part of an aggregate
  425.         CLSCTX_INPROC_SERVER,    // Run object in process
  426.         IID_FMMANAGE,            // Get the IfmManage interface
  427.         (PVOID *) &m_pManage);    // Target
  428.     if(FAILED(hr)) return E_FAIL;
  429.  
  430.     // get a context handle (used to RegisterStartedApp, etc.)
  431.     hr = m_pManage->GetFormsContextHandle(&m_hFC);
  432.     if(FAILED(hr)) return E_FAIL;
  433.  
  434.     // Get IfmSystem interface (so we can get some system metrics)
  435.     IfmSystem * pFmSys;
  436.        hr = m_pManage->QueryInterface(IID_FMSYSTEM, (PVOID *) &pFmSys);
  437.     if(FAILED(hr)) return E_FAIL;
  438.  
  439.     hr = pFmSys->GetFormDisplayCaps(m_hFC, VERTRES, &m_yres);
  440.     if(FAILED(hr)) return E_FAIL;
  441.  
  442.     hr = pFmSys->GetFormDisplayCaps(m_hFC, HORZRES, &m_xres);
  443.     if(FAILED(hr)) return E_FAIL;
  444.  
  445.     if(pFmSys) pFmSys->Release();
  446.  
  447.     // attatched our Class Msg Sink to the form manager
  448.     hr = m_pManage->put_ClassMsgSink(m_pAppMessageSink);
  449.     if(FAILED(hr)) return E_FAIL;
  450.  
  451.     // attatched our Event sink to the form manager
  452.     hr = m_pManage->put_EventSink(m_pAppEventSink);
  453.     if(FAILED(hr)) return E_FAIL;
  454.  
  455.     return(hr);
  456. }
  457.  
  458. //+-------------------------------------------------------------------------
  459. //
  460. //    Function: CTTSApp::DeleteFormControls
  461. //
  462. //    Synopsis:Delete all the correct controls for the app form.
  463. //        Our form only has 1 control
  464. //
  465. //    Arguments: void
  466. //
  467. //     Returns:  void
  468. //
  469. //---------------------------------------------------------------------------
  470. VOID CTTSApp::DeleteFormControls( VOID)
  471. {
  472.     if (m_pListBox){
  473.         m_pListBox->Release();
  474.         m_pListBox=NULL;
  475.     }
  476.  
  477.     return;
  478. }
  479.  
  480. //+-------------------------------------------------------------------------
  481. //
  482. //    Function: CTTSApp::CreateFormControls
  483. //
  484. //    Synopsis: Create all the correct controls for the app form.
  485. //
  486. //    Arguments: void
  487. //
  488. //     Returns:  S_OK on success
  489. //                
  490. //---------------------------------------------------------------------------
  491. HRESULT    CTTSApp::CreateFormControls(VOID)
  492. {
  493.     HRESULT hr;
  494.  
  495.     // Create the power list box
  496.     hr=CoCreateInstance(
  497.         CLSID_ASPOWERLISTBOX,            // Class ID
  498.         NULL,                            // Object NOT part of an aggergate
  499.         CLSCTX_INPROC_SERVER,            // Load in process
  500.         IID_ASPOWERLISTBOX,                // We want this interface
  501.         (PVOID *)&m_pListBox);            // put it here
  502.     if (FAILED(hr)) return hr;
  503.  
  504.     int iCY = 18;
  505.         //APCGetSystemMetrics(m_hFC, ASM_CYTITLEBAR);
  506.     m_pListBox->SetBounds(0, iCY, m_xres, m_yres - iCY);
  507.  
  508.     m_pListBox->put_Caption(m_bszMenuName);    // give the power list box a name
  509.  
  510.     m_pForm->Add(m_pListBox, IDC_LISTBOX);    // add it to the form
  511.     m_pListBox->put_Sorted(FALSE);            // don't sort the list box
  512.  
  513.     BSTR bStr = NULL;
  514.  
  515.  
  516.     // Create each menu item.  For each, tell the list box to create the item, add the caption.
  517.     // Then free the string and release the interface.
  518.     // Create ReadMenu item:
  519.     IASPowerListBoxItem *pReadMenuPLB = NULL;
  520.     hr = m_pListBox->CreateItem((IASPowerListBoxItem**)(&pReadMenuPLB), IDM_READMENU, ASFC_PWRLB_TYPE_COMMAND);
  521.     if (SUCCEEDED(hr))
  522.     {
  523.         if(LoadBSTR(IDS_READMENU, &bStr))
  524.         {
  525.             pReadMenuPLB->put_Caption(bStr);
  526.             SysFreeString(bStr);
  527.             pReadMenuPLB->Release();
  528.         }
  529.     }
  530.  
  531.     // Create HelloWorld item:
  532.     IASPowerListBoxItem *pHelloWorldPLB = NULL;
  533.     hr = m_pListBox->CreateItem((IASPowerListBoxItem**)(&pHelloWorldPLB), IDM_HELLOWORLD, ASFC_PWRLB_TYPE_COMMAND);
  534.     if (SUCCEEDED(hr))
  535.     {
  536.         if(LoadBSTR(IDS_HELLOWORLD, &bStr))
  537.         {
  538.             pHelloWorldPLB->put_Caption(bStr);
  539.             SysFreeString(bStr);
  540.             pHelloWorldPLB->Release();
  541.         }
  542.     }
  543.  
  544.     // Create Welcome item:
  545.     IASPowerListBoxItem *pWelcomePLB = NULL;
  546.     hr = m_pListBox->CreateItem((IASPowerListBoxItem**)(&pWelcomePLB), IDM_WELCOME, ASFC_PWRLB_TYPE_COMMAND);
  547.     if (SUCCEEDED(hr))
  548.     {
  549.         if(LoadBSTR(IDS_WELCOME, &bStr))
  550.         {
  551.             pWelcomePLB->put_Caption(bStr);
  552.             SysFreeString(bStr);
  553.             pWelcomePLB->Release();
  554.         }
  555.     }
  556.  
  557.     // Create SpeakForm item:
  558.     IASPowerListBoxItem *pSpeakFormPLB = NULL;
  559.     hr = m_pListBox->CreateItem((IASPowerListBoxItem**)(&pSpeakFormPLB), IDM_SPEAKFORM, ASFC_PWRLB_TYPE_COMMAND);
  560.     if (SUCCEEDED(hr))
  561.     {
  562.         if(LoadBSTR(IDS_SPEAKFORM, &bStr))
  563.         {
  564.             pSpeakFormPLB->put_Caption(bStr);
  565.             SysFreeString(bStr);
  566.             pSpeakFormPLB->Release();
  567.         }
  568.     }
  569.  
  570.     // Create Feedback item:
  571.     IASPowerListBoxItem *pFeedbackPLB = NULL;
  572.     hr = m_pListBox->CreateItem((IASPowerListBoxItem**)(&pFeedbackPLB), IDM_FEEDBACK, ASFC_PWRLB_TYPE_COMMAND);
  573.     if (SUCCEEDED(hr))
  574.     {
  575.         if(LoadBSTR(IDS_FEEDBACK, &bStr))
  576.         {
  577.             pFeedbackPLB->put_Caption(bStr);
  578.             SysFreeString(bStr);
  579.             pFeedbackPLB->Release();
  580.         }
  581.     }
  582.  
  583.     // Create Exit item:
  584.     IASPowerListBoxItem *pExitPLB = NULL;
  585.     hr = m_pListBox->CreateItem((IASPowerListBoxItem**)(&pExitPLB), IDM_EXIT, ASFC_PWRLB_TYPE_COMMAND);
  586.     if (SUCCEEDED(hr))
  587.     {
  588.         if(LoadBSTR(IDS_EXIT, &bStr))
  589.         {
  590.             pExitPLB->put_Caption(bStr);
  591.             SysFreeString(bStr);
  592.             pExitPLB->Release();
  593.         }
  594.     }
  595.  
  596.     return(hr);
  597. }
  598.  
  599. //+-------------------------------------------------------------------------
  600. //
  601. //    Function: CTTSApp::ProcessMessage
  602. //
  603. //    Synopsis: Process a message received on the app main thread message queue
  604. //        This function is called by the Form's event sink. 
  605. //
  606. //    Arguments:     uMsg -         The message received
  607. //                wParam -     The wParam for the received message
  608. //                lParam -    The lParam for the received message
  609. //
  610. //     Returns:  void
  611. //
  612. //---------------------------------------------------------------------------
  613.  
  614. VOID CTTSApp::ProcessMessage(LONG uMsg, LONG wParam, LONG lParam)
  615. {
  616.     long lCurSel = 0;
  617.     long lCount = 0;
  618.     long lId = 0;
  619.     int i;
  620.     BSTR bstr;
  621.     IASPowerListBoxItem* pItem = NULL;
  622.     long lItemData = NULL;
  623.     IDispatch* pDisp = NULL;
  624.  
  625.     if(uMsg == WM_COMMAND && LOWORD(wParam) == IDC_LISTBOX && HIWORD(wParam) == LBN_DBLCLK) // Some option on menu selected
  626.     {
  627.         switch (HIWORD(lParam)) // ID of item selected in HIWORD(lParam)
  628.         {
  629.         // When the user selects the Read Menu option, section pass each of the 
  630.         // Menu items and its ID to the Speak function.  When the Speak function is about to
  631.         // say each section, it fires a VTXTF_SPEAK message with the bookmark ID in the
  632.         // lParam.
  633.         case IDM_READMENU:
  634.             m_pListBox->get_Count(&lCount);
  635.             for(i=0; i<lCount; i++)
  636.             {
  637.                 pDisp = NULL;
  638.                 m_pListBox->ItemAt(i, (IDispatch **)&pDisp);
  639.                 pDisp->QueryInterface(IID_ASPOWERLISTBOXITEM, (PVOID *)&pItem);
  640.                 pDisp->Release();
  641.                 pItem->get_Caption(&bstr);
  642.                 pItem->get_ItemId(&lId);
  643.                 pItem->Release();
  644.                 m_pSpeech->Speak(bstr, lId);
  645.             }
  646.             break;
  647.  
  648.         // When the Exit menu item is selected, we set a flag so we can exit
  649.         // after we get the VTXTF_SPEAKDONE messasge.
  650.         case IDM_EXIT:
  651.             m_bExiting = TRUE;
  652.  
  653.         case IDM_HELLOWORLD:
  654.         case IDM_WELCOME:
  655.             // read the list box item that has focus
  656.             pDisp = NULL;
  657.             m_pListBox->get_FocusIndex(&lCurSel);    // Gives us the index of the item in focus
  658.             m_pListBox->ItemAt(lCurSel,(IDispatch **)&pDisp);    // returns an IDispatch interface to the 
  659.                                                                 // item at our requested index
  660.             pDisp->QueryInterface(IID_ASPOWERLISTBOXITEM, (PVOID *)&pItem);
  661.             pDisp->Release();
  662.             pItem->get_Caption(&bstr);    // gets text of that item
  663.             pItem->Release();            // release the item pointer
  664.             m_pSpeech->Speak(bstr,0);    // Speak it
  665.             break;
  666.  
  667.         // Reads the feedback level for voice and key.  Feedback variables filled
  668.         // during SpeechInit, and whenever we receive a WM_SETTINGCHANGE(wParam=SPI_SETAPCFEEDBACK)
  669.         // message.
  670.         case IDM_FEEDBACK:
  671.             m_pSpeech->Speak(m_bszKeyFeedback, 0);    // Say "The key feedback level is"
  672.             if(m_dwKeyFeedback == APCSPCH_FB_MORE)    // Check our Key Feedback variable
  673.                 m_pSpeech->Speak(m_bszMore, 0);        // Say "More"
  674.             else m_pSpeech->Speak(m_bszLess, 0);    // Say "Less"
  675.             
  676.             m_pSpeech->Speak(m_bszVoiceFeedback, 0);// Say "The voice feedback level is"
  677.             if(m_dwVoiceFeedback == APCSPCH_FB_MORE)// Check out Voice Feedback variable
  678.                 m_pSpeech->Speak(m_bszMore, 0);        // Say "More"
  679.             else m_pSpeech->Speak(m_bszLess, 0);    // Say "Less"
  680.             break;
  681.  
  682.         // This tells the Form and the one and only control to Speak.
  683.         case IDM_SPEAKFORM:
  684.             m_pForm->Speak(NULL, ASFC_SPEAK_ALLITEMS, NULL);
  685. //            m_pListBox->Speak(ASFC_SPEAK_ALLITEMS, NULL, NULL);
  686.             break;
  687.  
  688.         default:
  689.             break;
  690.         } // end switch
  691.     } //end if command directed towards listbox
  692. }
  693.  
  694. //+-------------------------------------------------------------------------
  695. //
  696. //    Function: CTTSApp::OnSpeakDone
  697. //
  698. //    Synopsis: Called when a WM_SPCH_NOTIFY, wParam = VTXTF_SPEAKDONE message is received.
  699. //        Exits if m_bExiting flag is set to true.
  700. //
  701. //    Arguments:     none
  702. //
  703. //     Returns:  void
  704. //
  705. //---------------------------------------------------------------------------
  706.  
  707. void
  708. CTTSApp::OnSpeakDone()
  709. {
  710.  
  711.     if(m_bExiting) 
  712.         PostThreadMessage(m_idThread, WM_QUIT, 0, 0);
  713. }