home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
msdn_vcb
/
samples
/
vc98
/
mfc
/
advanced
/
speakn
/
speakn.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-03-26
|
8KB
|
304 lines
// speakn.cpp : Defines the class behaviors for the SpeakN application.
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#include "speakn.h"
#include <mmsystem.h>
/////////////////////////////////////////////////////////////////////////////
// Sound helpers
static void PlaySound(LPCTSTR lpszSound)
{
HRSRC hRes; // resource handle to wave file
HGLOBAL hData;
BOOL bOk = FALSE;
if ((hRes = ::FindResource(AfxGetResourceHandle(), lpszSound,
_T("sound"))) != NULL &&
(hData = ::LoadResource(AfxGetResourceHandle(), hRes)) != NULL)
{
// found the resource, play it
bOk = sndPlaySound((LPCTSTR)::LockResource(hData),
SND_MEMORY|SND_SYNC|SND_NODEFAULT);
FreeResource(hData);
}
if (!bOk)
{
static BOOL bReported = FALSE;
if (!bReported)
{
AfxMessageBox(IDS_CANNOT_PLAY_SOUND);
bReported = TRUE; // once please
}
}
}
inline static void PlaySound(UINT nIDS)
{ PlaySound(MAKEINTRESOURCE(nIDS)); }
/////////////////////////////////////////////////////////////////////////////
// CSpeakNDlg
CSpeakNDlg::CSpeakNDlg(BOOL bNoPen)
: CDialog(bNoPen ? IDD_NOPENDIALOG : CSpeakNDlg::IDD)
{
//{{AFX_DATA_INIT(CSpeakNDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_bNoPen = bNoPen;
m_lpszNextQuestion = NULL;
m_bNoAnswerCheck = FALSE;
}
BEGIN_MESSAGE_MAP(CSpeakNDlg, CDialog)
//{{AFX_MSG_MAP(CSpeakNDlg)
ON_COMMAND(IDC_REPLAY_SOUND, OnReplaySound)
ON_COMMAND(IDC_GIVE_UP, OnGiveUp)
ON_COMMAND(IDC_PICTURE, OnReplaySound)
ON_EN_CHANGE(IDC_INPUT_EDIT, OnUpdateStatus)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CSpeakNDlg::LoadLesson(LPCTSTR lpLessonName)
{
// load lesson from resource
HRSRC hRes; // resource handle to lesson data
HGLOBAL hData;
if ((hRes = ::FindResource(AfxGetResourceHandle(), lpLessonName,
_T("lesson"))) == NULL ||
(hData = ::LoadResource(AfxGetResourceHandle(), hRes)) == NULL)
return FALSE;
m_lpszNextQuestion = (LPCSTR)::LockResource(hData);
return TRUE;
}
void CSpeakNDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSpeakNDlg)
DDX_Control(pDX, IDOK, m_buttonNext);
//}}AFX_DATA_MAP
}
BOOL CSpeakNDlg::OnInitDialog()
{
UpdateData(FALSE); // call DoDataExchange to initialize m_buttonNext
m_buttonNext.EnableWindow(FALSE);
ASSERT(m_targetWord.IsEmpty()); // not started yet
// set the font of the prompt text to something bigger
LOGFONT logfont;
memset(&logfont, 0, sizeof(logfont));
logfont.lfHeight = 40;
logfont.lfWeight = FW_BOLD;
CString szFont;
szFont.LoadString(IDS_FONT_NAME); // TrueType font
lstrcpy(logfont.lfFaceName, szFont);
VERIFY(m_biggerFont.CreateFontIndirect(&logfont));
PromptText().SetFont(&m_biggerFont);
InputEdit().SetFont(&m_biggerFont);
// load the bitmaps for bitmap buttons
VERIFY(m_replayButton.AutoLoad(IDC_REPLAY_SOUND, this));
InputEdit().ShowWindow(FALSE); // start with input disabled
// load initial picture
VERIFY(m_pictureButton.SubclassDlgItem(IDC_PICTURE, this));
VERIFY(m_pictureButton.LoadBitmaps(_T("intro"), NULL, NULL));
// Make the dialog visible, and update
ShowWindow(TRUE); // SHOW_OPENWINDOW
UpdateWindow();
PlaySound(IDSOUND_WELCOME);
AdvanceLesson();
return FALSE; // focus already set
}
void CSpeakNDlg::OnReplaySound()
{
InputEdit().SetFocus();
PlaySound(m_targetRes);
}
void CSpeakNDlg::OnOK()
{
// check results
CString result;
InputEdit().GetWindowText(result);
if (result != m_targetWord)
{
PlaySound(IDSOUND_INCORRECT);
AfxMessageBox(IDS_TRY_AGAIN);
return;
}
PlaySound(IDSOUND_CORRECT);
AdvanceLesson();
}
void CSpeakNDlg::OnGiveUp()
{
PlaySound(IDSOUND_GIVEUP);
SetAnswerText(m_targetWord); // show answer
OnReplaySound();
AdvanceLesson();
}
void CSpeakNDlg::SetAnswerText(LPCTSTR lpsz)
{
// setting the window text for an edit control will cause EN_CHANGE
// control notifications, so we lock them out while setting the
// text programmatically
ASSERT(!m_bNoAnswerCheck);
m_bNoAnswerCheck = TRUE;
InputEdit().SetWindowText(lpsz);
m_bNoAnswerCheck = FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Advancing to the next lesson
void CSpeakNDlg::AdvanceLesson()
{
if (*m_lpszNextQuestion == '\0')
{
// out of questions
PlaySound(IDSOUND_GOODBYE);
EndDialog(IDOK);
return;
}
// The lesson resource consists of several pairs of words (that the user guesses)
// and bitmap resource names. The words and resource names are stored in the
// resource as ANSI text. This text must be converted to UNICODE.
#ifdef _UNICODE
TCHAR szT[20];
int nLen;
nLen = strlen(m_lpszNextQuestion);
mbstowcs(szT, m_lpszNextQuestion, nLen);
szT[nLen] = 0;
m_targetWord = szT;
m_lpszNextQuestion += nLen + 1;
nLen = strlen(m_lpszNextQuestion);
mbstowcs(szT, m_lpszNextQuestion, nLen);
szT[nLen] = 0;
m_targetRes = szT;
m_lpszNextQuestion += nLen + 1;
#else
m_targetWord = m_lpszNextQuestion;
m_lpszNextQuestion += m_targetWord.GetLength() + 1;
m_targetRes = m_lpszNextQuestion;
m_lpszNextQuestion += m_targetRes.GetLength() + 1;
#endif
m_targetWord.MakeUpper();
m_targetRes.MakeUpper();
PlaySound(IDSOUND_QUESTION);
// draw the picture (bitmap with the same name as the target)
if (!m_pictureButton.LoadBitmaps(m_targetRes))
{
AfxMessageBox(IDS_PICTURE_UNAVAILABLE);
VERIFY(m_pictureButton.LoadBitmaps(_T("intro"), NULL, NULL));
// go back to the initial bitmap
}
m_pictureButton.Invalidate(TRUE);
SetAnswerText(_T(""));
InputEdit().ShowWindow(TRUE);
OnUpdateStatus(); // set appropriate face
OnReplaySound(); // ask question
if (*m_lpszNextQuestion == '\0')
{
CString strDone;
strDone.LoadString(IDS_DONE);
m_buttonNext.SetWindowText(strDone);
}
}
/////////////////////////////////////////////////////////////////////////////
// Happy face status indicator
void CSpeakNDlg::OnUpdateStatus()
{
CString result;
InputEdit().GetWindowText(result);
UINT nIDI = IDI_FACE_NEUTRAL; // default
if (result == m_targetWord)
{
m_buttonNext.EnableWindow();
nIDI = IDI_FACE_HAPPIER; // exact match
}
else
{
m_buttonNext.EnableWindow(FALSE);
if (result.IsEmpty())
nIDI = IDI_FACE_NEUTRAL; // not started yet
else
{
nIDI = (_tcsncmp(m_targetWord, result, _tcslen(result)) == 0?
IDI_FACE_HAPPY : IDI_FACE_SAD);
}
}
HICON hNew = ::LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(nIDI));
ASSERT(hNew != NULL);
::DestroyIcon(StatusFace().SetIcon(hNew));
UpdateWindow(); // draw everything now
if (m_bNoAnswerCheck)
return; // don't update
if (nIDI == IDI_FACE_HAPPIER)
{
// exact match - automatic advance
OnReplaySound();
PlaySound(IDSOUND_CORRECT);
}
}
/////////////////////////////////////////////////////////////////////////////
// CSpeakNApp
BOOL CSpeakNApp::InitInstance()
{
Enable3dControls();
BOOL bNoPen = TRUE; // no pen-aware controls
// Creates a simple dialog and do it
CSpeakNDlg mainDlg(bNoPen);
if (!mainDlg.LoadLesson(_T("SAMPLE1")))
return FALSE;
m_pMainWnd = &mainDlg;
mainDlg.DoModal();
// that's all, quit app
::PostQuitMessage(0);
return TRUE;
}
CSpeakNApp NEAR theApp;
/////////////////////////////////////////////////////////////////////////////