This code works well on my Windows XP with sound card.
(it is a piano window)
1. Will someone please verify it works on their XP system also?
2. How do I compile and link with gcc? (I don't know how to use the sound lib with gcc)
Thank you.
Code:// I'm using vc 7.0, command line, but gcc works too
// compile and link with this:
//cl %1.c /c
//link %1.obj user32.lib gdi32.lib winmm.lib
//---------------------------------------------------------------------------
#include <windows.h>
#include <stdio.h>
#include <mmsystem.h>
//--- constants ------------------------------------------------------------
#define IDC_BTN1 101
#define IDC_BTN2 102
//--- local -----------------------------------------------------------------
HWND hwndMain;
HWND hwndPiano;
HWND hwndWhiteKey;
HWND hwndBlackKey;
HBRUSH MW_Color;
HBRUSH PW_Color;
HBRUSH WK_Color_off;
HBRUSH WK_Color_on;
HBRUSH BK_Color_off;
HBRUSH BK_Color_on;
HWND hBtn1;
HWND hBtn2;
//first white key start 5
//white key width 15
//space between white keys 1
//white key length 80
//black key width 10
//black key length 50
//black key start: prev key start + 10
struct KEY{
char bw;
int note;
int startx;
BOOL on;
HWND hwndKey;
};
struct KEY key[49] = {
'W',36,5,FALSE,0,
'B',37,15,FALSE,0,
'W',38,21,FALSE,0,
'B',39,31,FALSE,0,
'W',40,37,FALSE,0,
'W',41,53,FALSE,0,
'B',42,63,FALSE,0,
'W',43,69,FALSE,0,
'B',44,79,FALSE,0,
'W',45,85,FALSE,0,
'B',46,95,FALSE,0,
'W',47,101,FALSE,0,
'W',48,117,FALSE,0,
'B',49,127,FALSE,0,
'W',50,133,FALSE,0,
'B',51,143,FALSE,0,
'W',52,149,FALSE,0,
'W',53,165,FALSE,0,
'B',54,175,FALSE,0,
'W',55,181,FALSE,0,
'B',56,191,FALSE,0,
'W',57,197,FALSE,0,
'B',58,207,FALSE,0,
'W',59,213,FALSE,0,
'W',60,229,FALSE,0,
'B',61,239,FALSE,0,
'W',62,245,FALSE,0,
'B',63,255,FALSE,0,
'W',64,261,FALSE,0,
'W',65,277,FALSE,0,
'B',66,287,FALSE,0,
'W',67,293,FALSE,0,
'B',68,303,FALSE,0,
'W',69,309,FALSE,0,
'B',70,319,FALSE,0,
'W',71,325,FALSE,0,
'W',72,341,FALSE,0,
'B',73,351,FALSE,0,
'W',74,357,FALSE,0,
'B',75,367,FALSE,0,
'W',76,373,FALSE,0,
'W',77,389,FALSE,0,
'B',78,399,FALSE,0,
'W',79,405,FALSE,0,
'B',80,415,FALSE,0,
'W',81,421,FALSE,0,
'B',82,431,FALSE,0,
'W',83,437,FALSE,0,
'W',84,453,FALSE,0
};
// midi
HMIDIOUT mhandle;
union {
DWORD dwData;
UCHAR bData[4];
} u;
//--- local prototypes ------------------------------------------------------------
void initMainWindow(HINSTANCE, int);
void initPianoWindow(HINSTANCE);
void initBlackKeys(HINSTANCE);
void initWhiteKeys(HINSTANCE);
void initOtherControls(HINSTANCE);
void initMidi();
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK PianoWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WhiteKeyWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK BlackKeyWndProc(HWND, UINT, WPARAM, LPARAM);
//---------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
initMainWindow(hInstance,nCmdShow);
initPianoWindow(hInstance);
initBlackKeys(hInstance); // create black keys first, so they are on top
initWhiteKeys(hInstance);
initOtherControls(hInstance);
UpdateWindow(hwndMain);
initMidi();
while(GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//---------------------------------------------------------------------------
void initMainWindow(HINSTANCE hInstance, int nCmdShow) {
WNDCLASSEX wc;
//--- register ---------------------------------------------
MW_Color = CreateSolidBrush(RGB(255, 0, 0)); // red
wc.lpszClassName = "MainClass";
wc.hInstance = hInstance;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = MW_Color;
wc.lpszMenuName = NULL;
wc.lpfnWndProc = MainWndProc;
if(!RegisterClassEx(&wc)) {
MessageBox(NULL, "Main Window Registration Failed!", "", MB_OK);
exit(0);
}
//--- create -----------------------------------------------
hwndMain = CreateWindowEx(
0,
"MainClass",
"PianoNotes",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
585, 300,
NULL, NULL, hInstance, NULL);
if(hwndMain == NULL) {
MessageBox(NULL, "Main Window Creation Failed!", "", MB_OK);
exit(0);
}
ShowWindow(hwndMain, nCmdShow);
return;
}
//---------------------------------------------------------------------------
void initPianoWindow(HINSTANCE hInstance) {
WNDCLASSEX wc;
//--- register ---------------------------------------------
PW_Color = CreateSolidBrush(RGB(115,108,244)); // blue
wc.lpszClassName = "PianoClass";
wc.hInstance = hInstance;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = PW_Color;
wc.lpszMenuName = NULL;
wc.lpfnWndProc = PianoWndProc;
if(!RegisterClassEx(&wc)) {
MessageBox(NULL, "Piano Window Registration Failed!", "", MB_OK);
exit(0);
}
//--- create -----------------------------------------------
hwndPiano = CreateWindowEx(
0,
"PianoClass",
"",
WS_CHILD,
45, 50,
475, 100,
hwndMain,
NULL, hInstance, NULL);
if(hwndPiano == NULL) {
MessageBox(NULL, "Piano Window Creation Failed!", "", MB_OK);
exit(0);
}
ShowWindow(hwndPiano, SW_SHOW);
return;
}
//---------------------------------------------------------------------------
void initBlackKeys(HINSTANCE hInstance) {
int ii;
WNDCLASSEX wc;
//--- register ---------------------------------------------
BK_Color_off = CreateSolidBrush(RGB(0,0,0)); // black
BK_Color_on = CreateSolidBrush(RGB(0,0,255));
//Step 1: Registering the Window Class
wc.lpszClassName = "BlackKeyClass";
wc.hInstance = hInstance;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = BK_Color_off;
wc.lpszMenuName = NULL;
wc.lpfnWndProc = BlackKeyWndProc;
if(!RegisterClassEx(&wc)) {
MessageBox(NULL, "Black Key Registration Failed!", "", MB_OK);
exit(0);
}
//--- create -----------------------------------------------
for (ii=0;ii<49;ii++) {
if (key[ii].bw == 'B') {
hwndBlackKey = CreateWindowEx(
0,
"BlackKeyClass",
"",
WS_CHILD,
key[ii].startx, 13,
10, 50,
hwndPiano,
NULL, hInstance, NULL);
if(hwndBlackKey == NULL) {
MessageBox(NULL, "Black Key Creation Failed!", "", MB_OK);
exit(0);
}
key[ii].hwndKey = hwndBlackKey;
ShowWindow(hwndBlackKey, SW_SHOW);
SetProp(hwndBlackKey,"note",(HANDLE)ii);
}
}
return;
}
//---------------------------------------------------------------------------
void initWhiteKeys(HINSTANCE hInstance) {
int ii;
WNDCLASSEX wc;
//--- register ---------------------------------------------
WK_Color_off = CreateSolidBrush(RGB(255,255,255)); // white
WK_Color_on = CreateSolidBrush(RGB(184,207,220));
//Step 1: Registering the Window Class
wc.lpszClassName = "WhiteKeyClass";
wc.hInstance = hInstance;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = WK_Color_off;
wc.lpszMenuName = NULL;
wc.lpfnWndProc = WhiteKeyWndProc;
if(!RegisterClassEx(&wc)) {
MessageBox(NULL, "White Key Registration Failed!", "", MB_OK);
exit(0);
}
//--- create -----------------------------------------------
for (ii=0;ii<49;ii++) {
if (key[ii].bw == 'W') {
hwndWhiteKey = CreateWindowEx(
0,
"WhiteKeyClass",
"",
WS_CHILD | WS_CLIPSIBLINGS,
key[ii].startx, 13,
15, 80,
hwndPiano,
NULL, hInstance, NULL);
if(hwndWhiteKey == NULL) {
MessageBox(NULL, "White Key Creation Failed!", "", MB_OK);
exit(0);
}
key[ii].hwndKey = hwndWhiteKey;
ShowWindow(hwndWhiteKey, SW_SHOW);
SetProp(hwndWhiteKey,"note",(HANDLE)ii);
}
}
return;
}
//---------------------------------------------------------------------------
void initOtherControls(HINSTANCE hInstance) {
hBtn1 = CreateWindow("BUTTON", "All Off",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
400, 175, 66, 32,
hwndMain,
(HMENU)IDC_BTN1,
hInstance, NULL );
hBtn2 = CreateWindow("BUTTON", "Sustain",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
300, 175, 73, 15,
hwndMain,
(HMENU)IDC_BTN2,
hInstance, NULL );
return;
}
//---------------------------------------------------------------------------
void initMidi()
{
/* Open whichever MIDI Out device is specified in Control Panel's "Multimedia"*/
midiOutOpen(&mhandle, (UINT)-1, 0, 0, CALLBACK_NULL);
/* Set the voice */
u.bData[0] = 0xC0;
u.bData[1] = 60; /* 60 = French Horm */
midiOutShortMsg(mhandle, u.bData[0]);
midiOutShortMsg(mhandle, u.bData[1]);
return;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
int ii;
BOOL bHold;
switch(msg)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
SetBkColor(hdc, RGB(255, 0, 0));
SetTextColor(hdc, RGB(0, 0, 0));
TextOut(hdc, 3, 10, "PianoNotes", 10);
EndPaint(hwnd, &ps);
break;
case WM_COMMAND :
switch( LOWORD( wParam ) )
{
case IDC_BTN1:
//MessageBox(hwnd,"button","", MB_OK);
for (ii=0;ii<49;ii++) {
if (key[ii].on) {
u.bData[0] = 0x80; /* MIDI status byte */
u.bData[1] = key[ii].note; /* first MIDI data byte - the note */
midiOutShortMsg(mhandle, u.dwData);
key[ii].on = FALSE;
InvalidateRect(key[ii].hwndKey, NULL, TRUE );
}
}
break;
}
break;
case WM_LBUTTONDOWN:
//MessageBox(hwnd,"Main WM_LBUTTONDOWN","", MB_OK);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK PianoWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_LBUTTONDOWN:
//MessageBox(hwnd,"Piano WM_LBUTTONDOWN","", MB_OK);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK WhiteKeyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
int ii;
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
switch(msg)
{
case WM_PAINT:
for (ii=0;ii<49;ii++) {
if (key[ii].bw == 'W') {
hwndWhiteKey = key[ii].hwndKey;
hdc = BeginPaint(hwndWhiteKey, &ps);
GetClientRect(hwndWhiteKey, &rect);
if (key[ii].on)
FillRect(ps.hdc, &rect, WK_Color_on);
else
FillRect(ps.hdc, &rect, WK_Color_off);
EndPaint(hwndWhiteKey, &ps);
}
}
break;
case WM_LBUTTONDOWN:
//MessageBox(hwnd,"White Key WM_LBUTTONDOWN","", MB_OK);
ii = (int) GetProp(hwnd,"note");
if (key[ii].on) {
u.bData[0] = 0x80; /* MIDI note off */
u.bData[1] = key[ii].note; /* first MIDI data byte */ /* 48 = C */
midiOutShortMsg(mhandle, u.dwData);
key[ii].on = FALSE;
}else{
u.bData[0] = 0x90; /* MIDI note on */
u.bData[1] = key[ii].note; /* first MIDI data byte - the note*/
u.bData[2] = 75; /* second MIDI data byte */ /* volumn 0-127 */
u.bData[3] = 0;
midiOutShortMsg(mhandle, u.dwData);
key[ii].on = TRUE;
}
InvalidateRect(key[ii].hwndKey, NULL, TRUE );
break;
case WM_LBUTTONUP:
//MessageBox(hwnd,"White Key WM_LBUTTONUP","", MB_OK);
if (IsDlgButtonChecked(hwndMain, IDC_BTN2))
{ break; }
ii = (int) GetProp(hwnd,"note");
if (key[ii].on) {
u.bData[0] = 0x80; /* MIDI note off */
u.bData[1] = key[ii].note; /* first MIDI data byte - the note*/
midiOutShortMsg(mhandle, u.dwData);
key[ii].on = FALSE;
InvalidateRect(key[ii].hwndKey, NULL, TRUE );
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK BlackKeyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
int ii;
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
switch(msg)
{
case WM_PAINT:
for (ii=0;ii<49;ii++) {
if (key[ii].bw == 'B') {
hwndBlackKey = key[ii].hwndKey;
hdc = BeginPaint(hwndBlackKey, &ps);
GetClientRect(hwndBlackKey, &rect);
if (key[ii].on)
FillRect(ps.hdc, &rect, BK_Color_on);
else
FillRect(ps.hdc, &rect, BK_Color_off);
EndPaint(hwndBlackKey, &ps);
}
}
break;
case WM_LBUTTONDOWN:
//MessageBox(hwnd,"Black Key WM_LBUTTONDOWN","", MB_OK);
ii = (int) GetProp(hwnd,"note");
if (key[ii].on) {
u.bData[0] = 0x80; /* MIDI note off */
u.bData[1] = key[ii].note; /* first MIDI data byte - the note*/
midiOutShortMsg(mhandle, u.dwData);
key[ii].on = FALSE;
}else{
u.bData[0] = 0x90; /* MIDI note on */
u.bData[1] = key[ii].note; /* first MIDI data byte - the note */
u.bData[2] = 75; /* second MIDI data byte */ /* volumn 0-127 */
u.bData[3] = 0;
midiOutShortMsg(mhandle, u.dwData);
key[ii].on = TRUE;
}
InvalidateRect(key[ii].hwndKey, NULL, TRUE );
break;
case WM_LBUTTONUP:
//MessageBox(hwnd,"Black Key WM_LBUTTONUP","", MB_OK);
if (IsDlgButtonChecked(hwndMain, IDC_BTN2))
{ break; }
ii = (int) GetProp(hwnd,"note");
if (key[ii].on) {
u.bData[0] = 0x80; /* MIDI note off*/
u.bData[1] = key[ii].note; /* first MIDI data byte - the note */
midiOutShortMsg(mhandle, u.dwData);
key[ii].on = FALSE;
InvalidateRect(key[ii].hwndKey, NULL, TRUE );
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}