rendered paste body#include <windows.h>
#include <stdio.h>
#include <mmsystem.h>
#include "resource.h"
#define NOTEON 0x90
#define NOTEOFF 0x80
#define DEFAULT_DEVICE 0
const char g_szClassName[] = "myWindowClass";
HBITMAP g_hbmKeyboard = NULL;
HBITMAP g_hbmKeyboardColour = NULL;
HBITMAP g_hbmMask = NULL;
HBITMAP g_hbmShow = NULL;
HBITMAP g_hbmTemp = NULL;
HMIDIOUT g_handle = NULL;
int g_lButtonDown = 0;
int g_heldNote = -1; /* letting -1 mean no note is playing */
HBITMAP HilightKey(int); /* returns a HBITMAP with selected key hilighted */
int id2Note(int, char *); /* returns length of string */
UINT sendMIDIEvent(HMIDIOUT, BYTE, BYTE, BYTE);
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_COLOUR:
{
DeleteObject(g_hbmShow);
g_hbmShow = HilightKey(0);
HDC hdc = GetDC(hwnd);
HDC hdcMem = CreateCompatibleDC(hdc);
BITMAP bm;
PAINTSTRUCT ps;
GetObject(g_hbmKeyboard, sizeof(BITMAP), &bm);
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, g_hbmShow);
BitBlt(hdc, 20, 20, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
DeleteObject(hdcMem);
ReleaseDC(hwnd, hdc);
}
break;
}
break;
case WM_LBUTTONUP:
{
g_lButtonDown = 0;
/* now we put the showing keyboard back to clean once we release the mouse*/
/* also we wish to draw the clean keyboard to the screen*/
HDC hdcMem, hdcMem2;
HDC hdc;
BITMAP bm;
RECT rcClient;
GetObject(g_hbmKeyboard, sizeof(BITMAP), &bm);
hdcMem = CreateCompatibleDC(0);
hdcMem2 = CreateCompatibleDC(0);
hdc = GetDC(hwnd);
HBITMAP hbmOld1 = (HBITMAP)SelectObject(hdcMem, g_hbmKeyboard);
HBITMAP hbmOld2 = (HBITMAP)SelectObject(hdcMem2, g_hbmShow);
BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
GetClientRect(hwnd, &rcClient);
FillRect(hdc, &rcClient, (HBRUSH)GetStockObject(WHITE_BRUSH));
BitBlt(hdc, 20, 20, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld1);
SelectObject(hdcMem2, hbmOld2);
DeleteObject(hdcMem);
DeleteObject(hdcMem2);
ReleaseDC(hwnd, hdc);
/* we finished replacing g_hbmShow with clean keyboard*/
sendMIDIEvent(g_handle, NOTEOFF, g_heldNote + 21, 127);
g_heldNote = -1;
break;
}
case WM_LBUTTONDOWN:
g_lButtonDown = 1;
case WM_MOUSEMOVE:
{
if(!g_lButtonDown)
break;
int x = LOWORD(lParam)-20; /*Corner of keyboard starts at 20,20.*/
int y = HIWORD(lParam)-20;
if((0 <= x)&&(x<521)&&(0<=y)&&(y<50)) /* keyboard has dimensions 521*50 */
{
char myMessage[92];
ZeroMemory(myMessage,92);
HDC BufferDC = CreateCompatibleDC(NULL);
HBITMAP hbmOld = (HBITMAP)SelectObject(BufferDC, g_hbmKeyboardColour);
COLORREF colourOfKey = GetPixel(BufferDC,x,y);
SelectObject(BufferDC, hbmOld);
DeleteDC(BufferDC);
int green = GetGValue(colourOfKey);
int red = GetRValue(colourOfKey);
int blue = GetBValue(colourOfKey);
/* display coloured key */
if(red == 255 && blue == 128 && green != g_heldNote)
{
DeleteObject(g_hbmShow);
sendMIDIEvent(g_handle, NOTEOFF, g_heldNote + 21, 127);
g_heldNote = green;
sendMIDIEvent(g_handle, NOTEON, g_heldNote + 21, 127);
g_hbmShow = HilightKey(g_heldNote);
HDC hdc = GetDC(hwnd);
HDC hdcMem = CreateCompatibleDC(hdc);
BITMAP bm;
PAINTSTRUCT ps;
RECT rcClient;
GetClientRect(hwnd, &rcClient);
FillRect(hdc, &rcClient, (HBRUSH)GetStockObject(WHITE_BRUSH));
GetObject(g_hbmKeyboard, sizeof(BITMAP), &bm);
hbmOld = (HBITMAP)SelectObject(hdcMem, g_hbmShow);
BitBlt(hdc, 20, 20, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
DeleteObject(hdcMem);
int length = id2Note(green, myMessage);
TextOut(hdc, 100, 100, myMessage, length);
ReleaseDC(hwnd, hdc);
}
/* end display coloured key */
}
}
break;
case WM_CREATE:
{
BITMAP bm;
g_hbmKeyboard = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_KEYBOARD));
g_hbmKeyboardColour = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_KBDCOLOUR));
g_hbmShow = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_KEYBOARD)); /* initially we want to show keyboard unchanged */
GetObject(g_hbmKeyboard, sizeof(BITMAP), &bm);
g_hbmMask = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL);
g_hbmTemp = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 32, NULL);
midiOutOpen(&g_handle, DEFAULT_DEVICE, 0,0, CALLBACK_WINDOW);
}
break;
case WM_PAINT:
{
BITMAP bm;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld =(HBITMAP)SelectObject(hdcMem, g_hbmShow);
GetObject(g_hbmKeyboard, sizeof(bm), &bm);
BitBlt(hdc, 20, 20, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
DeleteObject(g_hbmKeyboard); /* clean up*/
DeleteObject(g_hbmKeyboardColour);
DeleteObject(g_hbmMask);
DeleteObject(g_hbmTemp);
DeleteObject(g_hbmShow);
midiOutClose(g_handle);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAIN_MENU);
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Keyboard",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 570, 250,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
HBITMAP HilightKey(int key)
{
HDC hdcMem, hdcMem2;
HBITMAP hbmTemp = NULL;
BITMAP bm;
/*PAINTSTRUCT ps;*/
COLORREF keyColour = RGB(255, key, 128);
GetObject(g_hbmKeyboard, sizeof(BITMAP), &bm);
hbmTemp = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 32, NULL);
hdcMem = CreateCompatibleDC(0);
hdcMem2 = CreateCompatibleDC(0);
HBITMAP hbmOld1 = (HBITMAP)SelectObject(hdcMem, g_hbmKeyboardColour);
HBITMAP hbmOld2 = (HBITMAP)SelectObject(hdcMem2, g_hbmMask);
SetBkColor(hdcMem, keyColour); /* colour code for individual key */
BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); /*make mask with white key/black elsewhere*/
SelectObject(hdcMem, g_hbmTemp);
SetBkColor(hdcMem, RGB(255,0,0));
BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem2, 0, 0, SRCCOPY);
SetBkColor(hdcMem, RGB(0,0,0));
BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, g_hbmKeyboard);
SelectObject(hdcMem2, hbmTemp);
BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); /*Here we draw the new keyboard */
SelectObject(hdcMem, g_hbmMask); /*with a high-lighted key into our */
BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCAND); /*returning HBITMAP. hopefully the */
SelectObject(hdcMem, g_hbmTemp); /*memory gets freed when we delete the*/
BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCPAINT); /*HBITMAP that this function is set to*/
SelectObject(hdcMem, hbmOld1);
SelectObject(hdcMem2, hbmOld2);
DeleteObject(hdcMem);
DeleteObject(hdcMem2);
return hbmTemp;
}
int id2Note(int id, char * note)
{ int length = 0;
if((id<0) || (id>87))
return FALSE;
id += 9;
int octave = id/12;
int key = id%12;
char letter[6];
ZeroMemory(letter, 6);
switch(key)
{
case 0:
sprintf(letter, "C");
length = 3;
break;
case 1:
sprintf(letter, "C#/Db");
length = 7;
break;
case 2:
sprintf(letter, "D");
length = 3;
break;
case 3:
sprintf(letter, "D#/Eb");
length = 7;
break;
case 4:
sprintf(letter, "E");
length = 3;
break;
case 5:
sprintf(letter, "F");
length = 3;
break;
case 6:
sprintf(letter, "F#/Gb");
length = 7;
break;
case 7:
sprintf(letter, "G");
length = 3;
break;
case 8:
sprintf(letter, "G#/Ab");
length = 7;
break;
case 9:
sprintf(letter, "A");
length = 3;
break;
case 10:
sprintf(letter, "A#/Bb");
length = 7;
break;
case 11:
sprintf(letter, "B");
length = 3;
break;
default:
return FALSE;
}
sprintf(note, "%s %d", letter, octave);
return length;
}
UINT sendMIDIEvent( HMIDIOUT hMidiOut, BYTE bStatus,
BYTE bNote, BYTE bVol )
{
union {
DWORD dwData;
BYTE bData[4];
} u;
u.bData[0] = bStatus;
u.bData[1] = bNote;
u.bData[2] = bVol;
u.bData[3] = 0;
return midiOutShortMsg( hMidiOut, u.dwData );
}