/************************************************************* * Author : Haipeng * Date : 2010/4/10 * Last Compile : 2010/5/2 * Description : Piano GUI *************************************************************/ #include <windows.h> #include <ctype.h> #include "resource.h" typedef union _midi { DWORD dwData; BYTE bData[4]; } MIDI; BOOL keypressed=FALSE; BOOL blongsound=FALSE; unsigned long result,device; HMIDIOUT handle; unsigned char key; MIDI midi; struct _keys { BOOL bPressed; DWORD dwData; int time; }; struct _keys keystate[21]; void InitKeyState(void); void CALLBACK CheckTimer(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime); char about_message[]="Author : Haipeng/n"/ "Last Compiled : "__DATE__; /* Declare Windows procedure */ LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); /* Make the class name into a global variable */ char szClassName[ ] = "Piano"; HINSTANCE hInst; int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) { HWND hwnd; /* This is the handle for our window */ MSG messages; /* Here messages to the application are saved */ WNDCLASSEX wincl; /* Data structure for the windowclass */ /* The Window structure */ hInst=hThisInstance; wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ wincl.style = CS_DBLCLKS; /* Catch double-clicks */ wincl.cbSize = sizeof (WNDCLASSEX); /* Use default icon and mouse-pointer */ wincl.hIcon = LoadIcon (hThisInstance, MAKEINTRESOURCE(PIANOICON)); wincl.hIconSm = LoadIcon (hThisInstance, MAKEINTRESOURCE(PIANOICON)); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; /* No menu */ wincl.cbClsExtra = 0; /* No extra bytes after the window class */ wincl.cbWndExtra = 0; /* structure or the window instance */ /* Use Windows's default colour as the background of the window */ wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; /* Register the window class, and if it fails quit the program */ if (!RegisterClassEx (&wincl)) return 0; /* The class is registered, let's create the program*/ hwnd = CreateWindowEx ( 0, /* Extended possibilites for variation */ szClassName, /* Classname */ szClassName, /* Title Text */ WS_BORDER|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, /* default window */ CW_USEDEFAULT, /* Windows decides the position */ CW_USEDEFAULT, /* where the window ends up on the screen */ 595, /* The programs width */ 340, /* and height in pixels */ HWND_DESKTOP, /* The window is a child-window to desktop */ LoadMenu(hThisInstance,MAKEINTRESOURCE(MYMENU)), /* No menu */ hThisInstance, /* Program Instance handler */ NULL /* No Window Creation data */ ); /* Make the window visible on the screen */ midiOutOpen(&handle,0,0,0,CALLBACK_NULL); midi.bData[1]=6; midi.bData[0]=0xc0; midi.bData[3]=0; midi.bData[3]=0; midiOutShortMsg(handle,midi.dwData); midiOutSetVolume(handle,0xffffffff); ShowWindow (hwnd, nCmdShow); InitKeyState(); SetTimer(hwnd,6000,100,CheckTimer); /* Run the message loop. It will run until GetMessage() returns 0 */ while (GetMessage (&messages, NULL, 0, 0)) { /* Translate virtual-key messages into character messages */ TranslateMessage(&messages); /* Send message to WindowProcedure */ DispatchMessage(&messages); } /* The program return-value is 0 - The value that PostQuitMessage() gave */ return messages.wParam; } /* This function is called by the Windows function DispatchMessage() */ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hDC,memDC; PAINTSTRUCT pps; HBITMAP bmp; switch (message) /* handle the messages */ { case WM_DESTROY: DeleteDC(memDC); DeleteObject(bmp); PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; case WM_CREATE: // hDC=GetDC(hwnd); // bmp=LoadBitmap(hInst,MAKEINTRESOURCE(PIANO)); // memDC=CreateCompatibleDC(hDC); // SelectObject(memDC,bmp); break; case WM_PAINT: hDC=GetDC(hwnd); bmp=LoadBitmap(hInst,MAKEINTRESOURCE(PIANO)); memDC=CreateCompatibleDC(hDC); SelectObject(memDC,bmp); BeginPaint(hwnd,&pps); BitBlt(hDC,0,0,605,300,memDC,0,0,SRCCOPY); EndPaint(hwnd,&pps); break; case WM_KEYDOWN: switch(tolower(wParam)) { case 'a': if(!keystate[0].bPressed) { keystate[0].time=0; midiOutShortMsg(handle, 0x00603C90); keystate[0].bPressed=TRUE; } break; case 's': if(!keystate[1].bPressed) { keystate[1].time=0; midiOutShortMsg(handle, 0x00603E90); keystate[1].bPressed=TRUE; } break; case 'd': if(!keystate[2].bPressed) { keystate[2].time=0; midiOutShortMsg(handle, 0x00604090); keystate[2].bPressed=TRUE; } break; case 'f': if(!keystate[3].bPressed) { keystate[3].time=0; midiOutShortMsg(handle, 0x00604190); keystate[3].bPressed=TRUE; } break; case 'j': if(!keystate[4].bPressed) { keystate[4].time=0; midiOutShortMsg(handle, 0x00604390); keystate[4].bPressed=TRUE; } break; case 'k': if(!keystate[5].bPressed) { keystate[5].time=0; midiOutShortMsg(handle, 0x00604590); keystate[5].bPressed=TRUE; } break; case 'l': if(!keystate[6].bPressed) { keystate[6].time=0; midiOutShortMsg(handle, 0x00604790); keystate[6].bPressed=TRUE; } break; case 'z': if(!keystate[7].bPressed) { keystate[7].time=0; midiOutShortMsg(handle, 0x00603090); keystate[7].bPressed=TRUE; } break; case 'x': if(!keystate[8].bPressed) { keystate[8].time=0; midiOutShortMsg(handle, 0x00603290); keystate[8].bPressed=TRUE; } break; case 'c': if(!keystate[9].bPressed) { keystate[9].time=0; midiOutShortMsg(handle, 0x00603490); keystate[9].bPressed=TRUE; } break; case 'v': if(!keystate[10].bPressed) { keystate[10].time=0; midiOutShortMsg(handle, 0x00603590); keystate[10].bPressed=TRUE; } break; case 'm': if(!keystate[11].bPressed) { keystate[11].time=0; midiOutShortMsg(handle, 0x00603790); keystate[11].bPressed=TRUE; } break; case 188: if(!keystate[12].bPressed) { keystate[12].time=0; midiOutShortMsg(handle, 0x00603990); keystate[12].bPressed=TRUE; } break; case 190: if(!keystate[13].bPressed) { keystate[13].time=0; midiOutShortMsg(handle, 0x00603b90); keystate[13].bPressed=TRUE; } break; case 'q': if(!keystate[14].bPressed) { keystate[14].time=0; midiOutShortMsg(handle, 0x00604890); keystate[14].bPressed=TRUE; } break; case 'w': if(!keystate[15].bPressed) { keystate[15].time=0; midiOutShortMsg(handle, 0x00604a90); keystate[15].bPressed=TRUE; } break; case 'e': if(!keystate[16].bPressed) { keystate[16].time=0; midiOutShortMsg(handle, 0x00604c90); keystate[16].bPressed=TRUE; } break; case 'r': if(!keystate[17].bPressed) { keystate[17].time=0; midiOutShortMsg(handle, 0x00604d90); keystate[17].bPressed=TRUE; } break; case 'u': if(!keystate[18].bPressed) { keystate[18].time=0; midiOutShortMsg(handle, 0x00604f90); keystate[18].bPressed=TRUE; } break; case 'i': if(!keystate[19].bPressed) { keystate[19].time=0; midiOutShortMsg(handle, 0x00605190); keystate[19].bPressed=TRUE; } break; case 'o': if(!keystate[20].bPressed) { keystate[20].time=0; midiOutShortMsg(handle, 0x00605390); keystate[20].bPressed=TRUE; } break; default: break; } break; case WM_KEYUP: switch(tolower(wParam)) { case 'a': keystate[0].bPressed=FALSE; break; case 's': keystate[1].bPressed=FALSE; break; case 'd': keystate[2].bPressed=FALSE; break; case 'f': keystate[3].bPressed=FALSE; break; case 'j': keystate[4].bPressed=FALSE; break; case 'k': keystate[5].bPressed=FALSE; break; case 'l': keystate[6].bPressed=FALSE; break; case 'z': keystate[7].bPressed=FALSE; break; case 'x': keystate[8].bPressed=FALSE; break; case 'c': keystate[9].bPressed=FALSE; break; case 'v': keystate[10].bPressed=FALSE; break; case 'm': keystate[11].bPressed=FALSE; break; case 188: keystate[12].bPressed=FALSE; break; case 190: keystate[13].bPressed=FALSE; break; case 'q': keystate[14].bPressed=FALSE; break; case 'w': keystate[15].bPressed=FALSE; break; case 'e': keystate[16].bPressed=FALSE; break; case 'r': keystate[17].bPressed=FALSE; break; case 'u': keystate[18].bPressed=FALSE; break; case 'i': keystate[19].bPressed=FALSE; break; case 'o': keystate[20].bPressed=FALSE; break; default: break; } break; case WM_COMMAND: if(lParam==0&&HIWORD(wParam)==0) { switch(LOWORD(wParam)) { case 101: PostQuitMessage(0); break; case 100: break; case MPIANO: blongsound=FALSE; midi.bData[1]=6; midiOutShortMsg(handle,midi.dwData); break; case MTINKLE: blongsound=FALSE; midi.bData[1]=112; midiOutShortMsg(handle,midi.dwData); break; case MBIRDS: blongsound=FALSE; midi.bData[1]=123; midiOutShortMsg(handle,midi.dwData); break; case MPICCOLO: blongsound=TRUE; midi.bData[1]=72; midiOutShortMsg(handle,midi.dwData); break; case MGUITAR_NYLON: blongsound=FALSE; midi.bData[1]=24; midiOutShortMsg(handle,midi.dwData); break; case MGUITAR_STEEL: blongsound=FALSE; midi.bData[1]=25; midiOutShortMsg(handle,midi.dwData); break; case MGUITAR_JAZZ: blongsound=FALSE; midi.bData[1]=26; midiOutShortMsg(handle,midi.dwData); break; case MGUITAR_CLEAN: blongsound=FALSE; midi.bData[1]=27; midiOutShortMsg(handle,midi.dwData); break; case MGUITAR_MUTED: blongsound=FALSE; midi.bData[1]=28; midiOutShortMsg(handle,midi.dwData); break; case MGUITAR_HARMONICS: blongsound=FALSE; midi.bData[1]=31; midiOutShortMsg(handle,midi.dwData); break; case MBASS: blongsound=FALSE; midi.bData[1]=32; midiOutShortMsg(handle,midi.dwData); break; case MVIOLIN: blongsound=TRUE; midi.bData[1]=40; midiOutShortMsg(handle,midi.dwData); break; case MVIOLA: blongsound=TRUE; midi.bData[1]=41; midiOutShortMsg(handle,midi.dwData); break; case MCELLO: blongsound=TRUE; midi.bData[1]=42; midiOutShortMsg(handle,midi.dwData); break; case MCONTRABASS: blongsound=TRUE; midi.bData[1]=43; midiOutShortMsg(handle,midi.dwData); break; case MTREMOLO_STRINGS: blongsound=TRUE; midi.bData[1]=44; midiOutShortMsg(handle,midi.dwData); break; case MPIZZICATO_STRINGS: blongsound=FALSE; midi.bData[1]=45; midiOutShortMsg(handle,midi.dwData); break; case MORCHESTRAL_HARP: blongsound=FALSE; midi.bData[1]=46; midiOutShortMsg(handle,midi.dwData); break; case MTIMPANI: blongsound=FALSE; midi.bData[1]=47; midiOutShortMsg(handle,midi.dwData); break; case MHARMONICA: blongsound=TRUE; midi.bData[1]=22; midiOutShortMsg(handle,midi.dwData); break; case MTRUMPET: blongsound=TRUE; midi.bData[1]=56; midiOutShortMsg(handle,midi.dwData); break; case MCLARINET: blongsound=TRUE; midi.bData[1]=71; midiOutShortMsg(handle,midi.dwData); break; case MRAIN: blongsound=FALSE; midi.bData[1]=97; midiOutShortMsg(handle,midi.dwData); break; case MWOOBLOCK: blongsound=FALSE; midi.bData[1]=115; midiOutShortMsg(handle,midi.dwData); break; case 301: break; case 302: MessageBox(hwnd,about_message,"About",MB_OK); break; } } break; default: /* for messages that we don't deal with */ return DefWindowProc (hwnd, message, wParam, lParam); } return 0; } void CALLBACK CheckTimer(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime) { int i; if(blongsound) { for(i=0; i<21; i++) { if(!keystate[i].bPressed) { keystate[i].time++; if(keystate[i].time>1) { keystate[i].time=0; midiOutShortMsg(handle, keystate[i].dwData); } } } } } void InitKeyState(void) { keystate[0].dwData=0x00603C80; keystate[1].dwData=0x00603E80; keystate[2].dwData=0x00604080; keystate[3].dwData=0x00604180; keystate[4].dwData=0x00604380; keystate[5].dwData=0x00604580; keystate[6].dwData=0x00604780; keystate[7].dwData=0x00603080; keystate[8].dwData=0x00603280; keystate[9].dwData=0x00603480; keystate[10].dwData=0x00603580; keystate[11].dwData=0x00603780; keystate[12].dwData=0x00603980; keystate[13].dwData=0x00603b80; keystate[14].dwData=0x00604880; keystate[15].dwData=0x00604a80; keystate[16].dwData=0x00604c80; keystate[17].dwData=0x00604d80; keystate[18].dwData=0x00604f80; keystate[19].dwData=0x00605180; keystate[20].dwData=0x00605380; } 其实有很多代码没必要写的那么复杂,比如是否是系统判断的连续键,检查其消息参数就可以了,没必要出阿里WM_KEYUP消息。 还是有待改进,但最近是没时间了。