#pragma comment(lib, "winmm")
#include <Windows.h>
#include <windowsx.h>
#include <CommCtrl.h>
#include <wchar.h>
#include "resource.h"
#define MAKESMSG(st,ch,d1,d2) (st)<<4|(ch)|(d1)<<8|(d2)<<16
// GM Standard Drum Map
LPCTSTR percussion[] = {
L"Bass Drum 2",
L"Bass Drum 1",
L"Side Stick",
L"Snare Drum 1",
L"Hand Clap",
L"Snare Drum 2",
L"Low Tom 2",
L"Closed Hi-hat",
L"Low Tom 1",
L"Pedal Hi-hat",
L"Mid Tom 2",
L"Open Hi-hat",
L"Mid Tom 1",
L"High Tom 2",
L"Crash Cymbal 1",
L"High Tom 1",
L"Ride Cymbal 1",
L"Chinese Cymbal",
L"Ride Bell",
L"Tambourine",
L"Splash Cymbal",
L"Cowbell",
L"Crash Cymbal 2",
L"Vibra Slap",
L"Ride Cymbal 2",
L"High Bongo",
L"Low Bongo",
L"Mute High Conga",
L"Open High Conga",
L"Low Conga",
L"High Timbale",
L"Low Timbale",
L"High Agogo",
L"Low Agogo",
L"Cabasa",
L"Maracas",
L"Short Whistle",
L"Long Whistle",
L"Short Guiro",
L"Long Guiro",
L"Claves",
L"High Wood Block",
L"Low Wood Block",
L"Mute Cuica",
L"Open Cuica",
L"Mute Triangle",
L"Open Triangle",
};
const int scale[] = { 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 };
// 外部変数
HINSTANCE hInst;
HMIDIOUT hmo;
HBRUSH brush[3];
int pushid = 0;
// 関数プロトタイプ宣言
void Trace(LPCTSTR format, ...);
INT_PTR CALLBACK DlgMain(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnInitDialog(HWND hDlg, LPARAM lParam);
void OnDestroy(HWND hDlg);
void OnLButtonDown(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnLButtonUp(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR OnCtlColorStatic(WPARAM wParam, LPARAM lParam);
//==============================================================================
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
hInst = hInstance;
midiOutOpen(&hmo, MIDI_MAPPER, NULL, 0, CALLBACK_NULL);
DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DlgMain);
midiOutReset(hmo);
midiOutClose(hmo);
return 0;
}
void Trace(LPCTSTR format, ...)
{
va_list arg_ptr;
va_start(arg_ptr, format);
TCHAR buffer[256];
int size = _vsnwprintf_s(buffer, _TRUNCATE, format, arg_ptr);
va_end(arg_ptr);
OutputDebugString(buffer);
if (size < 0) {
OutputDebugString(L"...\n");
}
}
//------------------------------------------------------------------------------
INT_PTR CALLBACK DlgMain(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
INT_PTR res = TRUE; // メッセージを処理した
switch (uMsg) {
case WM_CTLCOLORSTATIC:
return OnCtlColorStatic(wParam, lParam);
case WM_LBUTTONDOWN:
OnLButtonDown(hDlg, uMsg, wParam, lParam);
break;
case WM_LBUTTONUP:
OnLButtonUp(hDlg, uMsg, wParam, lParam);
break;
case WM_INITDIALOG:
OnInitDialog(hDlg, lParam);
break;
case WM_CLOSE:
EndDialog(hDlg, 0);
break;
case WM_DESTROY:
OnDestroy(hDlg);
break;
default:
res = FALSE; // メッセージを処理しなかった
}
return res;
}
void OnInitDialog(HWND hDlg, LPARAM lParam)
{
RECT rw, rc;
GetWindowRect(hDlg, &rw);
GetClientRect(hDlg, &rc);
int cx = (rw.right - rw.left) - rc.right + 675;
int cy = (rw.bottom - rw.top) - rc.bottom + 375;
SetWindowPos(hDlg, HWND_TOP, 200, 200, cx, cy, 0);
for (int n = 0; n < 47; n++) {
int x = 10 + 165 * (n / 12);
int y = 10 + 30 * (n % 12);
int id = 35 + n;
HWND hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_STATIC, NULL,
WS_CHILD | WS_VISIBLE,
x, y, 160, 25, hDlg, HMENU(id), hInst, NULL);
TCHAR buf[32];
swprintf_s(buf, L"%d:%s", id, percussion[n]);
SetDlgItemText(hDlg, id, buf);
}
brush[0] = GetStockBrush(WHITE_BRUSH);
brush[1] = GetStockBrush(LTGRAY_BRUSH);
brush[2] = CreateSolidBrush(RGB(0xff, 0xff, 0x00));
}
void OnDestroy(HWND hDlg)
{
for (int n = 0; n < _countof(brush); n++) {
DeleteObject(brush[n]);
}
}
void OnLButtonDown(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
SetCapture(hDlg);
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
HWND hChild = ChildWindowFromPoint(hDlg, pt);
LONG id = GetWindowLong(hChild, GWL_ID);
Trace(L"OnLButtonDown(%d)\n", id);
if (id) {
pushid = id;
InvalidateRect(hChild, NULL, FALSE);
midiOutShortMsg(hmo, MAKESMSG(0x9, 10 - 1, pushid, 127)); // note on
}
}
void OnLButtonUp(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
ReleaseCapture();
Trace(L"OnLButtonUp(%d)\n", pushid);
if (pushid) {
midiOutShortMsg(hmo, MAKESMSG(0x8, 10 - 1, pushid, 0)); // note off
HWND hChild = GetDlgItem(hDlg, pushid);
InvalidateRect(hChild, NULL, FALSE);
pushid = 0;
}
}
INT_PTR OnCtlColorStatic(WPARAM wParam, LPARAM lParam)
{
LONG id = GetWindowLong(HWND(lParam), GWL_ID);
// Trace(L"OnCtlColorStatic(%d)\n", id);
if (id) {
HDC hdc = HDC(wParam);
SetBkMode(hdc, TRANSPARENT);
return INT_PTR(brush[(id == pushid) ? 2 : scale[id % 12]]);
}
return FALSE;
}