Click here to Skip to main content
15,396,145 members
Articles / Desktop Programming / MFC
Article
Posted 30 Dec 2002

Stats

200.6K views
5K downloads
65 bookmarked

CPianoCtrl - A Display Piano Control

Rate me:
Please Sign up or sign in to vote.
4.80/5 (40 votes)
14 Mar 2008MIT5 min read
An article about using the CPianoCtrl class

Introduction

A few months ago, I wrote a Code Project article about a class wrapper library I created for the low-level Windows MIDI API. To demonstrate my library, I created a simple application that included a piano display for playing the notes via the mouse. As it turns out, there was some interest in the piano control itself. Unfortunately, for a variety of reasons, the piano control I had created for that project wasn't suited for general use, so I decided to write the control over completely from scratch so that it can be used in many different contexts.

The CPianoCtrl and CPianoCtrlListener Classes

The CPianoCtrl class represents a keyboard piano display. It is a custom control derived from the MFC CWnd class. It displays an interactive keyboard which allows you to play notes with the mouse. By itself, the control doesn't produce any sound. It's up to you to connect a CPianoCtrl object to a sound source. This is done through the CPianoCtrlListener class.

The CPianoCtrlListener is an abstract class. Derived classes can attach themselves to a CPianoCtrl object. When a note is played or released, the CPianoCtrl object will notify all of its listeners that a note event has taken place. For example, a CPianoCtrlListener derived class could respond to an event by playing a MIDI note corresponding to the note played on a CPianoCtrl object it is registered with.

Keys on a CPianoCtrl object can be activated directly by calling the NoteOn and NoteOff functions. This can be useful when you want to turn on and off notes on the keyboard by a means other than the mouse. For example, you could parse a MIDI file and have the notes on the keyboard play to the notes in the file. Furthermore, since you can change the color of the keys that are being played, each MIDI track could have its own color.

Note Range and Characteristics

The CPianoCtrl class can have up to 128 keys (0 - 127). The range is set with the Initialize method or the SetNoteRange method. You specify the lowest note of the range and the highest note of the range. The lowest note must be less than the highest note and both the lowest note and the highest note must be natural. This is an important point that bears repeating: The lowest note and the highest note on the keyboard must be natural. This limitation has to do with avoiding situations in which a black key is the lowest or highest note. In such cases, there would be a white key fragment leftover. This would not be impossible to deal with. However, it makes things easier and clearer to simply avoid this situation altogether.

Notes are represented by integer values. The number 0 is considered a C note. As you go up from 0, you are ascending the chromatic scale. Therefore, 0 equals C, 1 equals C#, 2 equals D, etc. After you've reached the B note (the first B note is number 11), the scale starts over from C.

A CPianoCtrl can be displayed in one of three ways: Vertical left, vertical right, and horizontal. Vertical left displays the control vertically with the keys facing to the right, vertical right displays the control vertically with the keys facing left, and horizontal displays the control horizontally. The mode of display is determined by passing a constant to a control's constructor. Those constants are VERTICAL_LEFT, VERTICAL_RIGHT, and HORIZONTAL.

Using the CPianoCtrl Class

To use the CPianoCtrl class in a dialog based application, perform the following steps:

  1. In the resource editor, place a custom control onto the dialog box.
  2. Set the class name in the custom control's property box to match the CPianoCtrl's class name.
  3. Add a CPianoCtrl instance variable to the dialog class.
  4. Add a DDX_Control call in the DoDataExchange method in the dialog class. For example, if your dialog class was named CPianoDlg, the CPianoCtrl variable was named m_PianoCtrl, and the Id for the control was IDC_PIANOCTRL, you would place the following in the dialog class' DoDataExchange function:

    C++
    void CPianoDlg::DoDataExchange(CDataExchange* pDX)
    {
        CDialog::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(CPianoDlg)
            // NOTE: the ClassWizard will add DDX and DDV calls here
        //}}AFX_DATA_MAP
        DDX_Control(pDX, IDC_PIANOCTRL, m_PianoCtrl);
    }
  5. In the dialog class' OnInitDialog function, initialize the CPianoCtrl object by calling its initialize function. Here, you will pass the desired note range and optionally the note-on color.

To use the control dynamically within a dialog box or within a window, perform the following steps:

  1. Add a CPianoCtrl instance variable to your class. This can be a pointer to a CPianoCtrl object, but if so, you will need to allocate memory for it before using it and deallocate its memory after you are done with it.
  2. Call the CPianoCtrl object's Create function. Here, you will pass the parent window, the CPianoCtrl's position and size, its Id, and optionally its window style.
  3. Call the CPianoCtrl object's Initialize function. Here, you will pass the desired note range and optionally the note-on color.

The Demonstration Project

The VC++ demonstration project allows you to interact with three CPianoCtrl controls. You can change their range dynamically. Also, you can change the color used to indicate that a note is being played. You will notice that as you click on the keys you will not hear any sound. That's because the control by itself does not produce a sound. It must be connected to a sound source. If you would like to see an example of this, check out my updated MIDI wrapper article. In that demonstration application, I derive a class from the CPianoCtrl class specifically designed to work with my MIDI library and play MIDI notes.

I hope you find this control useful. Please let me know if you have any suggestions, bug reports, or would just like to tell me how you are using the control. Take care!

History

  • 1st March, 2003 - Added the ability to display control vertically
  • 14th March, 2008 - Updated source code and demo project, changed license to MIT

License

This article, along with any associated source code and files, is licensed under The MIT License

Share

About the Author

Leslie Sanford
United States United States
Aside from dabbling in BASIC on his old Atari 1040ST years ago, Leslie's programming experience didn't really begin until he discovered the Internet in the late 90s. There he found a treasure trove of information about two of his favorite interests: MIDI and sound synthesis.

After spending a good deal of time calculating formulas he found on the Internet for creating new sounds by hand, he decided that an easier way would be to program the computer to do the work for him. This led him to learn C. He discovered that beyond using programming as a tool for synthesizing sound, he loved programming in and of itself.

Eventually he taught himself C++ and C#, and along the way he immersed himself in the ideas of object oriented programming. Like many of us, he gotten bitten by the design patterns bug and a copy of GOF is never far from his hands.

Now his primary interest is in creating a complete MIDI toolkit using the C# language. He hopes to create something that will become an indispensable tool for those wanting to write MIDI applications for the .NET framework.

Besides programming, his other interests are photography and playing his Les Paul guitars.

Comments and Discussions

 
GeneralPrecompiled header problem!! Pin
WREY7-Jan-03 12:43
MemberWREY7-Jan-03 12:43 
GeneralRe: Precompiled header problem!! Pin
Leslie Sanford7-Jan-03 16:08
MemberLeslie Sanford7-Jan-03 16:08 
GeneralRe: and a CGuitarCtrl control? Pin
Leslie Sanford3-Jan-03 6:29
MemberLeslie Sanford3-Jan-03 6:29 
GeneralRe: and a CGuitarCtrl control? Pin
Leslie Sanford3-Jan-03 6:54
MemberLeslie Sanford3-Jan-03 6:54 
GeneralRe: and a CGuitarCtrl control? Pin
Leslie Sanford3-Jan-03 6:58
MemberLeslie Sanford3-Jan-03 6:58 
GeneralScrew That; Here's What Guitar Players Need... Pin
Clinton Gallagher6-Jan-03 7:19
professionalClinton Gallagher6-Jan-03 7:19 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
leppie7-Jan-03 9:38
Memberleppie7-Jan-03 9:38 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Clinton Gallagher7-Jan-03 11:30
professionalClinton Gallagher7-Jan-03 11:30 
I had to get attention somehow right?

Not to say that I would turn my nose up at a virtual fretboard because I wouldn't but I believe the first choice most guitar players want is to learn covers and we need playback tools like I described. Other ideas may be even better.

I would like a virtual fretboard to learn scales and arpeggios. Each note lights up on the fret where the note is supposed to be played allowing the player to keep their eyes off the fretboard but helping to show where to fret the note so the fingers just start to fall into place. Use this with a pedal and the player can change the tempo at will without taking hands off the instrument.

The interface needs to be able to be mirrored, rotated and flipped to allow the player to assign the type of virtual representation that they can 'see' in their mind's eye as they watch the notes light up as they are fretted. Maybe a transparnet view like looking from the back of the neck and being able to see through the neck where the fingers are supposed to land. Does that make sense?

In fact looking through the back of the neck seems to be the best idead for a virtual fretboard now that I think about it. Most representations of the fretboard are like looking at somebody else playing the instrument and the mind has to mirror that and do a transformation. Fock that Wink | ;-)

Thanks for the linked resources. I'll review and save them. My development skills are not that sophisticated yet. I've learned ASP and now I'm into C# and focused on building a blogging and headline portal for business to publish mnarketing, advertising and rich media presentations. That's what they spend money to do on the tv, radio, newspaper and magazines so I figure that is how they will spend money to do it with the Internet.

I think the more developers learn OOP the faster you will see intelligent real-time arrangers integrated in a recording studio applications. After all, most software 'intelligence' is all about OOP and a term called heuristics as I understand it.

<%= clintonG
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Chris Sibert7-Jan-03 17:58
MemberChris Sibert7-Jan-03 17:58 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Clinton Gallagher8-Jan-03 13:34
professionalClinton Gallagher8-Jan-03 13:34 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Artemis7-Jan-03 15:51
MemberArtemis7-Jan-03 15:51 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Clinton Gallagher8-Jan-03 13:39
professionalClinton Gallagher8-Jan-03 13:39 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Artemis8-Jan-03 15:22
MemberArtemis8-Jan-03 15:22 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Clinton Gallagher9-Jan-03 9:55
professionalClinton Gallagher9-Jan-03 9:55 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Artemis9-Jan-03 15:38
MemberArtemis9-Jan-03 15:38 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Clinton Gallagher10-Jan-03 4:11
professionalClinton Gallagher10-Jan-03 4:11 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Artemis12-Jan-03 22:43
MemberArtemis12-Jan-03 22:43 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Clinton Gallagher13-Jan-03 3:57
professionalClinton Gallagher13-Jan-03 3:57 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Artemis13-Jan-03 15:48
MemberArtemis13-Jan-03 15:48 
GeneralRe: Screw That; Here's What Guitar Players Need... Pin
Clinton Gallagher14-Jan-03 6:06
professionalClinton Gallagher14-Jan-03 6:06 
General3D-ness Pin
NormDroid1-Jan-03 23:40
professionalNormDroid1-Jan-03 23:40 
GeneralRe: 3D-ness Pin
Leslie Sanford2-Jan-03 6:24
MemberLeslie Sanford2-Jan-03 6:24 
Generallinking error Pin
balak1-Jan-03 14:39
Memberbalak1-Jan-03 14:39 
GeneralRe: linking error Pin
Leslie Sanford1-Jan-03 15:53
MemberLeslie Sanford1-Jan-03 15:53 
GeneralRe: linking error Pin
balak1-Jan-03 18:20
Memberbalak1-Jan-03 18:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.