Introduction: 
This one was just for fun; the article describes a 
project used to build a simple piano keyboard that plays some not too terrific 
sounding notes courtesy of the Kernel32.dll's beep function.  Whilst the notes 
are set to be roughly the correct frequency, the sound produced will not 
encourage you to sell your piano and take up a new career as a concert computer 
keyboardist.  On the other hand, it is fun to mess with and likely it would be 
entertaining for someone in the 8 year old range (at least if you were not 
within earshot when the entertaining begins).
![keyboard-in-vb.net.gif]()
Figure 1:  A small keyboard
I suppose that if one were to look hard enough, you 
could probably come up with something useful that you can do with this keyboard 
(like annoy your cat).  It could probably be turned into something instructional 
that could be used to teach someone the notes associated with the keys or some 
swell thing like that (of course that may well take the fun out of messing with 
it).  Further, if you were to dodge using the beep function and use the 
PlaySound function from the winmm.dll, and if you had access to recorded wave 
files for each of the notes played on the piano, you could probably come up with 
something that sounds a lot better without losing all of the charm and elegant 
styling associated with this project.
Getting Started:
In order to get started, unzip the attachment and load 
the solution into Visual Studio 2005.  Examine the solution explorer and note 
that the project contains one class:
![solution-explorer-in-vb.net.gif]()
Figure 2:  The Solution Explorer Showing the Project 
Files
The small keyboard project's single class is a windows 
form; that form contains a collection of buttons used to simulate the appearance 
(if not the sound) of piano keyboard. 
The Code
I'm sure that it seems inconceivable that this much raw 
power can be packed into a single class but it is true; I just suppose that is 
part of the awe inspiring thing we know as .NET.  To have a look at the magic 
going on behind the scenes, open up the class into the code view window and take 
a look.  The first thing that you will note is that the code imports 
System.Runtime.InteropServices.  This is necessary to support the DllImport 
function used in the first section of code following the class declaration:
Imports 
System.Runtime.InteropServices
 
Public
Class frmKeyboard
 
    <DllImport("KERNEL32.DLL")> 
_
   
Public Shared
Sub Beep(ByVal 
freq As Integer,
ByVal dur As
Integer)
   
End Sub
The DLL 
import call made here is used to bring the Kernel32.dll library into the 
project; the Kernel32.dll contains the Beep function and it is through this 
function that we can produce our simulated musical notes through this project's 
magnificent piano keyboard emulation.  The beep function mercifully accepts only 
two arguments, the frequency and the duration.  In this application we will pass 
in the frequency associated with a specific keyboard key (which is actually a 
float so we have to crop it off to make it fly here).  I think that you will 
agree that this loss of precision in no way impairs the quality of the audio 
output.  The duration passed in to the second argument is the same of each of 
the keys, it was arbitrary and sounded about right for a quick strike on a 
keyboard key (at least it sounds right if you bought your keyboard on sale at 
the dollar store).
Now onto 
the next bit of magic; the button handlers.  This bit of code makes it possible 
to produce beautiful strains of high quality music through the keyboard:
Private
Sub Play_KeyDown(ByVal 
sender As Object,
ByVal e As 
System.Windows.Forms.KeyEventArgs) _
   
Handles btnMC.KeyDown, btnHA.KeyDown, 
btnHAs.KeyDown, btnHB.KeyDown, _
    btnHC.KeyDown, 
btnHCs.KeyDown, btnHD.KeyDown, btnHDs.KeyDown, btnHE.KeyDown, _
    btnHF.KeyDown, 
btnHFs.KeyDown, btnHG.KeyDown, btnHGs.KeyDown, btnLA.KeyDown, _
    btnLAs.KeyDown, 
btnLB.KeyDown, btnLC.KeyDown, btnLCs.KeyDown, btnLD.KeyDown, _
    btnLDs.KeyDown, 
btnLE.KeyDown, btnLF.KeyDown, btnLFs.KeyDown, btnLG.KeyDown, _
    btnLGs.KeyDown, 
btnMA.KeyDown, btnMAs.KeyDown, btnMB.KeyDown, btnMC.KeyDown, _
    btnMCs.KeyDown, 
btnMD.KeyDown, btnMDs.KeyDown, btnME.KeyDown, btnMF.KeyDown, _
    btnMFs.KeyDown, 
btnMG.KeyDown, btnMGs.KeyDown, Me.KeyDown 
 
       
Me.Focus()
 
       
Select Case 
e.KeyData.ToString()
           
Case "A"
               
Me.btnMC_Click(sender, e)
           
Case "S"
               
Me.btnMD_Click(sender, e)
           
Case "D"
               
Me.btnME_Click(sender, e)
           
Case "F"
               
Me.btnMF_Click(sender, e)
           
Case "G"
               
Me.btnMG_Click(sender, e)
           
Case "H"
               
Me.btnMA_Click(sender, e)
           
Case "J"
               
Me.btnHC_Click(sender, e)
           
Case "K"
               
Me.btnHD_Click(sender, e)
           
Case "L"
               
Me.btnHE_Click(sender, e)
           
Case "Z"
               
Me.btnHF_Click(sender, e)
           
Case "X"
               
Me.btnHG_Click(sender, e)
           
Case "C"
               
Me.btnHA_Click(sender, e)
       
End Select
 
End
Sub
Taking a look at this code you will note that it 
handles all of the key down events associated with each of the buttons.  A 
select case statement is used to figure out which keyboard button was pressed 
and that is turn is used to figure which button click event to evoke.  The click 
event handler will then call the beep function and pass to it the correct 
frequency and the canned duration (but all your user will know is that they are 
making beautiful music).
Next up is the button click event handlers;  since they 
are all pretty much the same, I will only show one in this document, the event 
handler for middle C:
Private
Sub btnMC_Click(ByVal 
sender As System.Object,
ByVal e As
System.EventArgs)
Handles btnMC.Click
   
' middle C
    Beep(261, 150)
End
Sub
As advertised, this event handler evokes the beep 
function and passes the frequency and duration arguments to that function.  I 
set the duration on all of the keys to be 150 milliseconds but you can use any 
value of your choosing.
Summary
The project demonstrates a few useful things like using 
the DLL Import function supported by the InteropServices library, but overall, 
it was just for fun.