home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK11 / MFC / SAMPLES / SPEAKN / SPEAKN.CP$ / speakn
Encoding:
Text File  |  1992-03-18  |  7.2 KB  |  251 lines

  1. // speakn.cpp : Defines the class behaviors for the SpeakN application.
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and Microsoft
  9. // QuickHelp documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12. //
  13.  
  14. #include "speakn.h"
  15. #include <mmsystem.h>
  16.  
  17. /////////////////////////////////////////////////////////////////////////////
  18. // Sound helpers
  19.  
  20. static void PlaySound(LPCSTR lpszSound)
  21. {
  22.     HRSRC hRes; // resource handle to wave file
  23.     HGLOBAL hData;
  24.     BOOL bOk = FALSE;
  25.     if ((hRes = ::FindResource(AfxGetResourceHandle(), lpszSound,
  26.       "sound")) != NULL &&
  27.       (hData = ::LoadResource(AfxGetResourceHandle(), hRes)) != NULL)
  28.     {
  29.         // found the resource, play it
  30.         bOk = sndPlaySound((LPCSTR)::LockResource(hData),
  31.             SND_MEMORY|SND_SYNC|SND_NODEFAULT);
  32.         FreeResource(hData);
  33.     }
  34.     if (!bOk)
  35.         AfxGetApp()->m_pMainWnd->MessageBox("Can't play sound");
  36. }
  37.  
  38. inline static void PlaySound(UINT nIDS)
  39.     { PlaySound(MAKEINTRESOURCE(nIDS)); }
  40.  
  41. /////////////////////////////////////////////////////////////////////////////
  42. // CSpeakNDlg
  43.  
  44. BEGIN_MESSAGE_MAP(CSpeakNDlg, CModalDialog)
  45.     ON_COMMAND(IDC_REPLAY_SOUND, OnReplaySound)
  46.     ON_COMMAND(IDC_GIVE_UP, OnGiveUp)
  47.     ON_COMMAND(IDC_PICTURE, OnReplaySound)
  48.     ON_EN_CHANGE(IDC_INPUT_EDIT, OnUpdateStatus)
  49. END_MESSAGE_MAP()
  50.  
  51. BOOL CSpeakNDlg::LoadLesson(LPCSTR lpLessonName)
  52. {
  53.     // load lesson from resource
  54.     HRSRC hRes; // resource handle to lesson data
  55.     HGLOBAL hData;
  56.     if ((hRes = ::FindResource(AfxGetResourceHandle(), lpLessonName,
  57.       "lesson")) == NULL ||
  58.       (hData = ::LoadResource(AfxGetResourceHandle(), hRes)) == NULL)
  59.         return FALSE;
  60.     m_lpszNextQuestion = (LPCSTR)::LockResource(hData);
  61.     return TRUE;
  62. }
  63.  
  64. BOOL CSpeakNDlg::OnInitDialog()
  65. {
  66.     ASSERT(m_targetWord.IsEmpty());     // not started yet
  67.  
  68.     // set the font of the prompt text to something bigger
  69.     LOGFONT logfont;
  70.     memset(&logfont, 0, sizeof(logfont));
  71.     logfont.lfHeight = 40;
  72.     logfont.lfWeight = FW_BOLD;
  73.     strcpy(logfont.lfFaceName, "Arial");        // TrueType font
  74.     VERIFY(m_biggerFont.CreateFontIndirect(&logfont));
  75.     PromptText().SetFont(&m_biggerFont);
  76.     InputEdit().SetFont(&m_biggerFont);
  77.  
  78.     // load the bitmaps for bitmap buttons
  79.     VERIFY(m_replayButton.AutoLoad(IDC_REPLAY_SOUND, this));
  80.     InputEdit().ShowWindow(FALSE);      // start with input disabled
  81.  
  82.     // load initial picture
  83.     VERIFY(m_pictureButton.SubclassDlgItem(IDC_PICTURE, this));
  84.     VERIFY(m_pictureButton.LoadBitmaps("intro", NULL, NULL));
  85.  
  86.     // Make the dialog visible, and update
  87.     ShowWindow(TRUE);       // SHOW_OPENWINDOW
  88.     UpdateWindow();
  89.  
  90.     PlaySound(IDSOUND_WELCOME);
  91.     AdvanceLesson();
  92.     return TRUE;
  93. }
  94.  
  95. void CSpeakNDlg::OnReplaySound()
  96. {
  97.     InputEdit().SetFocus();
  98.     PlaySound(m_targetWord);
  99. }
  100.  
  101. void CSpeakNDlg::OnOK()
  102. {
  103.     // check results
  104.     CString result;
  105.     InputEdit().GetWindowText(result);
  106.     if (result != m_targetWord)
  107.     {
  108.         PlaySound(IDSOUND_INCORRECT);
  109.         MessageBox("Please try again", "Incorrect Guess");
  110.         return;
  111.     }
  112.     PlaySound(IDSOUND_CORRECT);
  113.     AdvanceLesson();
  114. }
  115.  
  116. void CSpeakNDlg::OnGiveUp()
  117. {
  118.     PlaySound(IDSOUND_GIVEUP);
  119.     InputEdit().SetWindowText(m_targetWord);        // show answer
  120.     OnReplaySound();
  121.     AdvanceLesson();
  122. }
  123.  
  124. /////////////////////////////////////////////////////////////////////////////
  125. // Advancing to the next lesson
  126.  
  127. void CSpeakNDlg::AdvanceLesson()
  128. {
  129.     if (*m_lpszNextQuestion == '\0')
  130.     {
  131.         // out of questions
  132.         PlaySound(IDSOUND_GOODBYE);
  133.         EndDialog(IDOK);
  134.         return;
  135.     }
  136.     // lesson resource points to 1 keyword string per lesson
  137.     m_targetWord = m_lpszNextQuestion;
  138.     m_lpszNextQuestion += m_targetWord.GetLength() + 1;
  139.     m_targetWord.MakeUpper();       // just in case
  140.     int nBoxes = m_targetWord.GetLength();
  141.  
  142.     PlaySound(IDSOUND_QUESTION);
  143.  
  144.     // draw the picture (bitmap with the same name as the target)
  145.     if (!m_pictureButton.LoadBitmaps(m_targetWord))
  146.     {
  147.         MessageBox("Picture unavailable");
  148.         VERIFY(m_pictureButton.LoadBitmaps("intro", NULL, NULL));
  149.             // go back to the initial bitmap
  150.     }
  151.     m_pictureButton.Invalidate(TRUE);
  152.     CBEdit* pEdit = &InputEdit();
  153.     pEdit->SetWindowText("");           // clear out the edit
  154.  
  155.     m_pictureButton.UpdateWindow();     // draw the picture now
  156.  
  157.     // adjust boxed edit item to be centered and the right size
  158.     CRect rect;         // get edit control size
  159.     pEdit->GetWindowRect(&rect);
  160.     ScreenToClient(&rect);                  // in parent coordinate
  161.     int xMid = (rect.left + rect.right) / 2;
  162.     RC rc;              // get pen input info
  163.     VERIFY(pEdit->GetRC(&rc));
  164.     TEXTMETRIC tm;      // get size of font
  165.     {
  166.         CClientDC dc(this);
  167.         CFont* pOldFont = dc.SelectObject(&m_biggerFont);
  168.         dc.GetTextMetrics(&tm);
  169.         dc.SelectObject(pOldFont);
  170.     }
  171.  
  172.     // set input guides to match big font
  173.     const int xGap = 8;
  174.     const int yGap = 8;
  175.     rc.guide.cHorzBox = nBoxes;
  176.     rc.guide.cxBox = tm.tmMaxCharWidth + tm.tmMaxCharWidth / 3; // 4/3
  177.     rc.guide.cyBox = tm.tmHeight;
  178.     rc.guide.cyBase = tm.tmAscent + yGap;               // uppercase
  179.     int cxEdit = rc.guide.cxBox * nBoxes + yGap;        // extra room for sides
  180.     rect.left = xMid - cxEdit / 2;
  181.     rect.right = xMid + cxEdit / 2;
  182.     rect.bottom = rect.top + tm.tmHeight + yGap;        // extra space
  183.     pEdit->MoveWindow(rect);
  184.     VERIFY(pEdit->SetRC(&rc));
  185.     pEdit->Invalidate(TRUE);
  186.     pEdit->ShowWindow(TRUE);
  187.  
  188.     OnUpdateStatus();               // set appropriate face
  189.     OnReplaySound();                // ask question
  190. }
  191.  
  192. /////////////////////////////////////////////////////////////////////////////
  193. // Happy face status indicator
  194.  
  195. void CSpeakNDlg::OnUpdateStatus()
  196. {
  197.     CString result;
  198.     InputEdit().GetWindowText(result);
  199.  
  200.     UINT nIDI = IDI_FACE_NEUTRAL;       // default
  201.     if (result == m_targetWord)
  202.         nIDI = IDI_FACE_HAPPIER;        // exact match
  203.     else if (result.IsEmpty())
  204.         nIDI = IDI_FACE_NEUTRAL;        // not started yet
  205.     else if (result[0] == m_targetWord[0])
  206.         nIDI = IDI_FACE_HAPPY;          // first letter correct
  207.     else
  208.         nIDI = IDI_FACE_SAD;            // not even close
  209.     HICON hNew = ::LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(nIDI));
  210.     ASSERT(hNew != NULL);
  211.     ::DestroyIcon(StatusFace().SetIcon(hNew));
  212.     UpdateWindow();                 // draw everything now
  213.  
  214.     if (nIDI == IDI_FACE_HAPPIER)
  215.     {
  216.         // exact match - automatic advance
  217.         OnReplaySound();
  218.         PlaySound(IDSOUND_CORRECT);
  219.         AdvanceLesson();
  220.     }
  221. }
  222.  
  223. /////////////////////////////////////////////////////////////////////////////
  224. // CSpeakNApp
  225.  
  226. BOOL CSpeakNApp::InitInstance()
  227. {
  228.     // Must have PenWindows installed
  229.     if (GetSystemMetrics(SM_PENWINDOWS) == NULL)
  230.     {
  231.         MessageBox(NULL, "This application requires Microsoft Windows for"
  232.             " Pen Computing", "SpeakNPen", MB_OK);
  233.         return FALSE;
  234.     }
  235.  
  236.     // Creates a simple dialog and do it
  237.     CSpeakNDlg mainDlg;
  238.     if (!mainDlg.LoadLesson("SAMPLE1"))
  239.         return FALSE;
  240.     m_pMainWnd = &mainDlg;
  241.     mainDlg.DoModal();
  242.  
  243.     // that's all, quit app
  244.     ::PostQuitMessage(0);
  245.     return TRUE;
  246. }
  247.  
  248. CSpeakNApp theApp;
  249.  
  250. /////////////////////////////////////////////////////////////////////////////
  251.