Many months ago, I created a piano control using MFC.
Having begun using C# over the past year, I decided recently to recreate the control for the .Net framework. However, after taking another look at the challenge of representing the piano keyboard as a GUI control, I decided to take a different approach.
One of the challenges of creating the piano control for MFC was deciding how to represent the piano keys. The first version of the control divided each key into one or more rectangles. In the second version, I switched to using regions. With both approaches, each piano key was simply a set of coordinates encapsulated in piano key classes and held by the
CPianoCtrl class. The task of determining which key is being played fell to this class and had to be done manually. This involved a certain amount of grunt work with capturing mouse events and using hit detection. I wanted to avoid this with the C# version/.Net version.
To overcome having to detect manually which key is being played, I made the piano key itself a control. Each piano key, then, is responsible for responding to mouse events; each key knows when it is being held and released. All that is necessary is for the piano key control to listen for mouse events and respond appropriately when they occur. This made the task of managing the piano keys and mouse events much easier.
There are four basic piano key shapes:
- L Shaped (notes C and F)
- Backwards L Shaped (notes E and B)
- Upside down T Shaped (notes D, G, and A)
- Rectangled Shaped (all flat keys)
With the MFC piano control, I created a hierarchy of piano key classes representing these different shapes. In retrospect, this may have been overkill. With the C# version, I created a single piano key control class and made the key shape a property of this class.
In addition to shapes, piano keys, at least the GUI version of them, also have orientation. A piano key can be oriented vertically or horizontally. When oriented horizontally, the back of the key can can face either to the left or right. Orientation is another aspect I made a property of the piano key control class.
Piano Key Events
StateChanged event is the only event that is generated when a piano key is triggered or released. After receiving this event, you can query the state of the key using the
IsKeyOn() method. This method returns true if the key has been turned on or false if it is off.
The demo shows the
PianoKey control with various shapes and orientations. There is a collection of
PianoKey controls grouped together to form a piano keyboard. One approach that I have found useful is to use the
Tag property of the
Control class for storing data relevant to an individual control. I used this approach with the group of piano keys giving each one of them an id number that can be retrieved when the
StateChanged event is triggered.
In the future, I may create a piano control class which manages a collection of piano keys. But for now, I think the
PianoKey control class can be useful in and of itself. I hope you enjoy this class, and I welcome any suggestions or comments.
- 02/09/2004 Article Submitted