MFC TIMERS & PROGRESS BARS; WINDOWS MULTIMEDIA THE WINDOWS TIMER-- An input device that notifies an app when a time interval has elapsed Application starts it & tells Windows the interval with SetTimer() Windows sends WM_TIMER message each time interval elapses Application stops and removes timer with KillTimer() Could be used to keep time--but not accurate CTime class to the rescue!! GetCurTime() member function returns hour, minute, and seconds Member functions can retrieve these values: GetHour(), GetMinute(), GetSecond() Clock Application <Show program in action>Use AppWizard to create a Dialog-Based MFC Application template Add the following controls to the dialog box: "Time:" static control "Current Time" static control (IDC_STATICTIME) (Will show the current time) Remove the "Cancel" Button Change the "OK" button to "Exit" Add the timer ID: In Resource View, right-click over "Clock" Resource Folder Select "Resource Symbols" Hit "New" Enter ID_CLK_TIMER Will assign an ID to the timer Starting the Clock Timer with a one-second interval In CClockDlg, Edit the OnInitDialog() function by adding: // TODO: Add extra initialization here SetTimer(ID_CLK_TIMER, 1000, NULL); Use ClassWizard to add m_sTime variable to IDC_STATICTIME control Type: CString Use ClassWizard to set up a message handler for WM_TIMER: Edit the resulting OnTimer() function: // TODO: Add your message handler code here and/or call default CTime t=CTime::GetCurrentTime(); m_sTime.Format("%d:%d:%d", t.GetHour(), t.GetMinute(), t.GetSecond()); UpdateData(FALSE); //Send to Static Current Time control Progress Bar Controls Used to indicate progress of an operation Lets user know what portion of an operation is not yet completed Encapsulated in CProgressCtrl Class Some Member Functions (kind of like Scroll bar functions): SetRange() & GetRange() -- range of the progress bar SetPos() & GetPos() -- current position OffsetPos() -- to increment current progress bar position SetStep() -- to set step amount for progress bar StepIt() -- to increment position by step amount TimerProgrss Application <Show program in action>
Set up an MFC Dialog-based Application template Add the timer ID: In Resource View, right-click over "TimerProgrss" Resource Folder Select "Resource Symbols" Hit "New" Enter ID_CNT_TIMER Will assign an ID to the timer Add following controls: "Interval:" static control IDC_INTERVAL Edit box "Max Count:" static control IDC_MAXCNT Edit box "Count:" static control Static control to hold current count (IDC_STATICCNT, "0") IDC_PROGCNT Progress Bar Remove the "Cancel" Button Change the "OK" button to "Exit" Use ClassWizard to add the following variables for the controls: Control ID Variable Name Variable Type ------------------------------------------------ IDC_PROGCNT m_Progress CProgressCtrl IDC_START m_Start CButton IDC_STATICCNT m_sCount CString IDC_INTERVAL m_iInterval int IDC_MAXCNT m_iMax int Add m_iCount member variable (int private) to the TimerProgrssDlg class (Right click on the clas) Use ClassWizard to add the following Message Map handler functions: CTimerProgrssDlcg -- WM_TIMER: OnTimer() IDC_START -- BN_CLICKED: OnStart() IDC_INTERVAL -- EN_CHANGE: OnChangeInterval() IDC_MAXCNT -- EN_CHANGE: OnChangeMaxcnt() Edit the OnInitDialog() function (initialization of controls): // TODO: Add extra initialization here m_iInterval=100; m_iMax=1000; UpdateData(FALSE); //Pass variable data to controls Edit the OnStart() function (initialize progress bar & start timer): // TODO: Add your control notification handler code here UpdateData(TRUE); //Get data from controls m_iCount=0; m_sCount.Format("%d", m_iCount); m_Progress.SetRange(0,m_iMax); //Set progress control m_Progress.SetPos(0); UpdateData(FALSE); //Pass new data back to controls m_Start.EnableWindow(FALSE); //disable Start button SetTimer(ID_CNT_TIMER,m_iInterval,NULL); //Start timer Edit the OnTimer() function (timeout, so count and update progress bar): // TODO: Add your message handler code here and/or call default m_iCount+=m_iInterval; //Increment count m_sCount.Format("%d", m_iCount); m_Progress.SetPos(m_iCount); //Set new prog bar position UpdateData(FALSE); //Pass data back to control if(m_iCount>=m_iMax) //If done, kill timer { KillTimer(ID_CNTTIMER); m_Start.EnableWindow(TRUE); // enable start button } Edit the OnChangeInterval() function (Get new interval from Interval control): // TODO: Add your control notification handler code here UpdateData(TRUE); // Get interval value from edit control Edit the OnChangeMaxcnt() function (Get new Max from Maxcount control): // TODO: Add your control notification handler code here UpdateData(TRUE); // Get maxcount value from edit control Build and Run the application. (You may have to make the some of the controls bigger) WINDOWS MULTIMEDIA Some multimedia devices: Waveform audio device (sound card) converts microphone & other analog audio to digitized samples can be stored as .WAV files can be played back Usually has a MIDI device plays music from short binary messages can be attached to a MIDI input device (music keyboard) CD Audio through the CD-ROM drive Video for Windows device (AVI video device) plays movie/animation files (.AVI) Video capture boards (different compression schemes) Laserdisc players & video cassette recorders Others Extensive Win32 API support for multimedia devices Low-level support High-level support MSDN online documentaton: Platform SDK/Graphics & Multimedia Services/Multimedia Reference MCI (Media Control Interface) High level multimedia control functions Has commands common to all MM hardware Possible since most use record/play metaphor Open a device for input or output If input, record If output, play When done, close Two forms of MCI Send command messages (like Windows messages) to MCI (need to include bit-encoded flags and C data structures) Send text strings to MCI Good for use from scripting languages with string functionality Simple to use MCI converts them to command messages mciSendString() function: error = mciSendString(szCmd, szRetStr, cSzRetStr, hCallback) szCmd--the mci command string (specifies command & device) szRetStr--return string buffer (NULL if none used) szSzRetStr--size of return string buffer (0 if none used) szCallback--Handle to Callback function (NULL if none used) Returns 0 if command is successful, error code if not Usually used as parameter to mciGetErrorString() Many command strings possible See MSDN online help: / Platform SDK / Graphics & Multimedia Services / Multimedia Reference / Multiemedia Command Strings Some Common MCI Command Strings: open -- initializes a device "open lpszDevice lpszOpenflags lpszFlags" Some device types: cdaudio -- Audio CD played on system's CD-ROM waveaudio -- .WAV audio files AVIVideo -- .AVI video files Some Examples: "open cdaudio" "open new type waveaudio alias mysound" (for recording) "open waveaudio!myclip.wav alias clip" play -- plays from an open device "play cdaudio" stop -- stops playing from an open device "stop clip" close -- closes an open device "close mysound" PlayCD Application <show program in action>
Create an MFC AppWizard (.exe) Dialog-based application template All Multimedia applications must #include the "mmsystem.h" header file So add: #include "mmsystem.h" at top of PlayCDDlg.h file Must also link in the WINMM.LIB library-- Project / Settings / Link Tab / Category: Input / Object-Library Modules Type in: WINMM.LIB Add "Play CD" and "Stop CD" buttons (IDC_BPLAY and IDC_BSTOP) Use ClassWizard to add Message Map BN_CLICKED handler functions for the two new buttons --> OnBplay() & OnBstop() Add code to OnBplay(): mciSendString("open cdaudio",NULL,0,NULL); mciSendString("play cdaudio",NULL,0,NULL); Add code to OnBstop(): mciSendString("stop cdaudio",NULL,0,NULL); mciSendString("close cdaudio",NULL,0,NULL); Build and run with an audio CD in the CD-ROM drive You may have to shut down autostart app launched when audio CD is inserted It may do stuff to "mute" & "volume" audio controls You may have to adjust them Recording and Playing Digital Sound (.WAV files) RecPlay Application <show program in action>
Want to: Begin and Stop recording Begin and Stop playback Save and read a .WAV file Use mciSendString() to issue command strings Keep track of what's happening with Booleans bRec and bPlay Use 5 buttons: ("Begin Rec", "End Rec", "Begin Play", "End Play", "Exit") Enable or Disable according to what's happening==> Need Button control variables (to access EnableWindow() function) Requirements: When app begins execution: Set bRec and bPlay to FALSE Disable "End Record", "End Play" buttons "Begin Rec" button pressed==> open new waveaudio device & record set bRec to TRUE disable: "Begin Rec", "Begin Play", "End Play" buttons enable: "End Rec" button "End Rec" button pressed==> stop device, save as .WAV file, close device set bRec to FALSE disable: "End Rec", "End Play" buttons enable: "Begin Rec", "Begin Play" buttons "Begin Play" button pressed==> open .WAV file & play set bPlay to TRUE disable: "Begin Rec", "Enc Rec", Begin Play" buttons enable: "End Play" button "End Play" button pressed==> stop & close device set bPlay to FALSE disable: "End Rec", "End Play" buttons enable: "Begin Rec", "Begin Play" buttons "Exit" button pressed==> if bPlay is TRUE: execute "End Play" button command function if bRec is TRUE: stop & close device (don't save incomplete recording) Exit RecPlay Application Details: Create an MFC AppWizard (.exe) Dialog-based application template Add: #include "mmsystem.h" at top of RecPlayDlg.h file Link in the WINMM.LIB library-- Project / Settings / Link Tab / Category: Input / Object-Library Modules Type in: WINMM.LIB Create Buttons: "Begin Rec" (IDC_REC_BEG), "End Rec" (IDC_REC_END) "Begin Play" (IDC_PLAY_BEG), "End Play" (IDC_PLAY_END) Add private BOOL variables: bPlay, bRec (Right click class) Use ClassWizard to attach Command member variables to the buttons: m_cRecBeg, m_cRecEnd, m_ cPlayBeg, m_cPlayEnd (CButton derived) USe ClassWizard to add Message Map BN_CLICKED handler functions to each button --> OnRecBeg(), OnRecEnd(), OnPlayBeg(), OnPlayEnd(), OnOK() Edit OnInitDialog(): // TODO: Add extra initialization here bPlay=bRec=FALSE; m_cRecEnd.EnableWindow(FALSE); m_cPlayEnd.EnableWindow(FALSE); Edit OnRecBeg(): // TODO: Add your control notification handler code here mciSendString("open new type waveaudio alias myvoice",NULL,0,NULL); mciSendString("record myvoice",NULL,0,NULL); bRec=TRUE; m_cRecBeg.EnableWindow(FALSE); m_cRecEnd.EnableWindow(TRUE); m_cPlayBeg.EnableWindow(FALSE); m_cPlayEnd.EnableWindow(FALSE); Edit OnRecEnd(): // TODO: Add your control notification handler code here mciSendString("stop myvoice",NULL,0,NULL); mciSendString("save myvoice test.wav",NULL,0,NULL); mciSendString("close mysound",NULL,0,NULL); bRec=FALSE; m_cRecBeg.EnableWindow(TRUE); m_cRecEnd.EnableWindow(FALSE); m_cPlayBeg.EnableWindow(TRUE); m_cPlayEnd.EnableWindow(FALSE); Edit OnPlayBeg(): // TODO: Add your control notification handler code here mciSendString("open test.wav alias myvoice",NULL,0,NULL); mciSendString("play myvoice",NULL,0,NULL); bPlay=TRUE; m_cRecBeg.EnableWindow(FALSE); m_cRecEnd.EnableWindow(FALSE); m_cPlayBeg.EnableWindow(FALSE); m_cPlayEnd.EnableWindow(TRUE); Edit OnPlayEnd(): // TODO: Add your control notification handler code here mciSendString("stop myvoice",NULL,0,NULL); mciSendString("close myvoice",NULL,0,NULL); bPlay=FALSE; m_cRecBeg.EnableWindow(TRUE); m_cRecEnd.EnableWindow(FALSE); m_cPlayBeg.EnableWindow(TRUE); m_cPlayEnd.EnableWindow(FALSE); Edit OnOK(): // TODO: Add extra validation here if (bPlay) OnPlayEnd(); if(bRecording) { mciSendString("stop myvoice",NULL,0,NULL); mciSendString("close myvoice",NULL,0,NULL); } Build and run the application You may need to attach an external microphone and fool around with audio control and microphone settings Best to run "Sound Recorder" app first to make sure things are working: Start / Programs / Accessories / Entertainment / Sound Recorder