Make your own free website on

Solve this Problem 


This page will have queries which I am not able to solve. Please help if you know the answer.


Can you solve the following MS Visual C++ (6.0) problem:
3.13.13Problem: The Piano
Piano is a multi-document multi-view application that allows composers to record and play simple musical scores. Each view is a form that displays 13 piano keys (these are simply elongated buttons). Pressing one of these buttons either plays a beep of a particular frequency and duration (Windows NT only) or plays a wave file (if the computer is equipped with a sound card). If the view is in recording mode, then an object representing the note played is stored in a musical score (i.e., a list of notes encapsulated by the document class). The [Duration Control] scroll bar allows users to alter the duration of the next note to be created/played. The [Record] and [Stop Recording] buttons turn the recording mode on and off, respectively. When the recording mode is off, the [Play] button plays back the current score. The [Clear] button erases the score. Naturally, users can save and load scores.

The [Sounds] menu allows users to associate different sounds with the piano keys. [Sounds]/[Beep Mode] toggles between playing a beep and playing a wave file. A check mark next to this item indicates that beep mode is on. In addition, the [Sounds] menu contains 13 other items, one for each key. Selecting any of these items displays a [File Dialog] that allows users to select a wave file to be played when the corresponding key is pressed.
Implement the Piano application.      CNote
Begin by using the [Insert]/[New Class ...] menu to create a class called CNote. Instances of CNote represent musical notes. Each CNote encapsulates three integer variables:
m_frequency = frequency in Hz
m_duration = duration in milliseconds
m_id = number of steps above C (= -1 to 12)
We use m_id = -1 to indicate a rest "note", m_id = 0 is C, m_id = 1 is C#, etc., and m_id = 12 is high C.
The CNote constructor expects a duration and an id as inputs:
CNote::CNote(int id /* = 0 */, int dur /* = 100 */) { ??? }
The appropriate frequency is computed by the constructor using the formula:
m_frequency = int(256 * pow(1.05496, id));
This works because 256 represents the frequency of C, and 1.05496 is 21/12, the frequency ratio of a half step. If id = -1, the rest note, then f = 30000 Hz, which should be inaudible.      CPianoDoc
You'll need to add the following include directives at the top of PianoDoc.h:
#include <afxtempl.h>
#include "Note.h"
#include <mmsystem.h> // may require a sound card
Instances of the CPianoDoc class encapsulate:
m_beep = TRUE if beep mode is on, FALSE otherwise
m_score = a CList of recorded CNotes
m_sounds =
a CMap of associations between CNote id's and wave file names
The CPianoDoc class provides member functions for playing a single note, playing all of the notes in m_score, adding a note to m_score, changing the wave file associated with a note:
class CPianoDoc : public CDocument
BOOL m_beep; // beep vs. wave mode
void AddSound(int id);
void AddNote(CNote& n);
void Play(CNote note);
void Play();
// etc.
CList<CNote, CNote&> m_score;
CMap<int, int, CString, CString&> m_sounds;
If beep mode is on, Play(CNote note) calls the global Beep() function:
Beep(note.m_frequency, note.m_duration);
Unfortunately, only the Windows NT platform pays attention to this function's parameters. If beep mode is off, Play() uses note.m_id to look up the corresponding wave file, then calls the PlaySound() function declared in <mmsystem.h> and defined in winmm.lib:
PlaySound(waveFile, NULL, SND_FILENAME | SND_SYNC);
Readers can search the on-line documentation for a complete description of PlaySound(). In order to successfully link a program that calls PlaySound(), readers will have to use the [Project Settings] dialog box (select the [Project]/[Settings] menu item) to add the sound card driver. Set the [Settings For:] list box to "All Configurations", select the [Link] tab, and type "winmm.lib" at the end of the libraries listed in the [Object/library modules:] edit box:

(Of course the winmm.lib may not be present if you haven't installed some sort of sound card on your system.)
Readers can handle all of the [Sounds] menu items in CPianoDoc. For example, here's the handler for [Sounds]/[D Sound]:
void CPianoDoc::OnSoundsDsound()
AddSound(2); // m_id of D = 2
The AddSound() function creates and displays a file dialog box, then enters the path of the selected wave file in the m_sounds map:
void CPianoDoc::AddSound(int id)
static LPCTSTR path = NULL;
CFileDialog dialog(TRUE, NULL, path);
path = dialog.GetPathName();
m_sounds[id] = path;
}      CPianoView
The CPianoView objects encapsulate two variables:
#include "Note.h"

class CPianoView : public CFormView
int m_duration; // wired to scroll bar by Class Wizard
BOOL m_recording; // = TRUE if recording
// etc.
We haven't seen scroll bars, yet. OnInitialUpdate() is a good place to initialize the range and thumb tab position:
void CPianoView::OnInitialUpdate()
CScrollBar* pSB = (CScrollBar*) GetDlgItem(IDC_DURATION);
pSB->SetScrollRange(50, 250);
Adjusting a horizontal scroll bar sends the WM_HSCROLL message to the scroll bar's parent window (which is CPianoView in our case). Use the Class Wizard to add a handler for this message. This handler has two responsibilities: move the thumb tab to where the user adjusted it to (otherwise it will snap back), and update m_duration. Scroll bars will be explained in the next chapter.
void CPianoView::OnHScroll(
UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
int pos = pScrollBar->GetScrollPos();
if (pScrollBar != NULL && GetDocument()->m_beep))
switch (nSBCode)
case SB_LINELEFT: // left arrow
if (pos - 10 > 0)
pos = pos - 10;
pos = 0;
case SB_LINERIGHT: // right arrow
if (pos + 10 < 255)
pos = pos + 10;
pos = 255;
} // switch
} // if
CFormView::OnHScroll(nSBCode, nPos, pScrollBar);

--   BoB Hall

[FrontPage Save Results Component]

Please write your answer here


Click Here!



Hello Bob: I was browsing through your code, which I found helpfull and I was wondering. In your OnHScroll method, you test to see if pScrollBar is NULL, however, you use it the line before. If it is NULL (because of a System Scroll Bar) won't that through an exception? i.e. NULL->GetScrollPos() = error? If there is a miss-understanding on this, please send me an E-mail at Thank you, Dan