/* Simple.c -- Displays a window on the screen and plays a MIDI note while executing. Uses these basic Win API low-level MIDI functions: midiOutGetNumDevs() -- get the number of MIDI output devices in the system midiOutGetDevCaps() -- get thecapabilities of a selected MIDI output device midiOutOpen() -- open a selected MIDI output device midiOutShortMsg() -- send a channel voice message midiOutClose() -- close selected MIDI output device */ #include #include #include #include #define NOTEON 0x90 #define NOTEOFF 0x80 char szWinName[] = "MyWin"; /* name of window class */ HINSTANCE hInst; LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK TestProc(HWND, UINT, WPARAM, LPARAM); UINT FAR PASCAL sendMIDIEvent( HMIDIOUT, BYTE, BYTE, BYTE ); int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode) { HWND hwnd; MSG msg; WNDCLASS wcl; /* Define a window class. */ wcl.hInstance = hThisInst; /* handle to this instance */ wcl.lpszClassName = szWinName; /* window class name */ wcl.lpfnWndProc = WindowFunc; /* window function */ wcl.style = 0; /* default style */ wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION); /* icon style */ wcl.hCursor = LoadCursor(NULL, IDC_ARROW); /* cursor style */ /* specify name of menu resource */ wcl.lpszMenuName = "MYMENU"; /* main menu */ wcl.cbClsExtra = 0; /* none needed */ wcl.cbWndExtra = 0; /* information needed */ /* Make the window white. */ wcl.hbrBackground = GetStockObject(WHITE_BRUSH); /* Register the window class. */ if(!RegisterClass (&wcl)) return 0; /* Now that a window class has beer registered, a window can he created. */ hwnd = CreateWindow( szWinName, /* name of window class */ "Using a List Box", /* title */ WS_OVERLAPPEDWINDOW, /* window style - normal */ CW_USEDEFAULT, /* X coordinate - let Windows decide */ CW_USEDEFAULT, /* y coordinate - let Windows decide */ CW_USEDEFAULT, /* width - let Windows decide */ CW_USEDEFAULT, /* height - let Windows decide */ NULL, /* no parent window */ NULL, /* use menu registered with this class */ hThisInst, /* handle of this instance of the program */ NULL); /* no additional arguments */ hInst = hThisInst; /* save the current instance handle */ /* Display the window. */ ShowWindow(hwnd, nWinMode); UpdateWindow(hwnd); /* Create the message loop. */ // Start the message loop. while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); // allow use of keyboard DispatchMessage(&msg); // return control to Windows } return msg.wParam; } // This function is called by Windows 95 and is passed messages from the message queue. // It will set up the default device and handle menu selections LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HMIDIOUT hMidiOut; static UINT numDevs, curDevice; // curDevice will be initialized to 0 static MIDIOUTCAPS devCaps; static LPMIDIOUTCAPS lpCaps = &devCaps; int iResult; switch(message) { case WM_CREATE: // Open the first midi device in the device list numDevs = midiOutGetNumDevs(); // Get the number of devices midiOutGetDevCaps(curDevice, lpCaps, sizeof(MIDIOUTCAPS)); // Get device capabilities for first device (curDevice == 0) iResult = midiOutOpen(&hMidiOut, curDevice, /*(DWORD) hwnd*/(DWORD) NULL, (DWORD) NULL, /*CALLBACK_WINDOW*/ (DWORD) NULL); // Open first device if(iResult != MMSYSERR_NOERROR) MessageBox(hwnd, "Midi Device Could Not Be Opened", "Device Error", MB_OK); sendMIDIEvent(hMidiOut, NOTEON, 60, 100); // Turn on middle C break; case WM_COMMAND: break; case WM_PAINT: { char str[5]; HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(hwnd, &ps); wsprintf(str, "%d ", numDevs); // Print the number of midi devices TextOut(hdc, 5, 5, str, strlen(str)); EndPaint(hdc, &ps); } break; case WM_DESTROY: /* terminate the program */ sendMIDIEvent(hMidiOut, NOTEOFF, 60, 100); /* On exit turn off the note */ midiOutClose(hMidiOut); PostQuitMessage(0); break; default: /* Let Windows 95 process any messages not specified in the preceding switch statement. */ return DefWindowProc(hwnd, message, wParam, lParam); } return 0; } /* Straight out of Microsoft MM SDK doc */ /* Takes three bytes (a status byte and two data bytes) as input and converts to the four-byte type required by midiOutShortMsg() */ UINT FAR PASCAL sendMIDIEvent( HMIDIOUT hMidiOut, BYTE bStatus, BYTE bData1, BYTE bData2 ) { union { DWORD dwData; BYTE bData[4]; } u; u.bData[0] = bStatus; u.bData[1] = bData1; u.bData[2] = bData2; u.bData[3] = 0; return midiOutShortMsg( hMidiOut, u.dwData ); }