All pastes #839258 Raw Edit

Someone

public text v1 · immutable
#839258 ·published 2007-12-30 22:56 UTC
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 );
}