Initial Commit.

Signed-off-by: Xiaomao Chen <xiaomao5@live.com>
This commit is contained in:
Quantum 2013-06-02 22:14:25 -04:00
commit be89fa7bf6
12 changed files with 814 additions and 0 deletions

8
.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
*.obj
*.exe
*.res
/build
/dist
/test
/old
/*.pdb

55
Makefile Normal file
View file

@ -0,0 +1,55 @@
SRCDIR=src
INCDIR=include
CXX=cl /nologo
LD=link /nologo
CXXFLAGS=/c /O1 /I$(INCDIR) /W4 /Zi /DWIN32_LEAN_AND_MEAN /DWINVER=0x0501 /D_WIN32_WINNT=0x0501 /DUNICODE /D_UNICODE
LDFLAGS=/subsystem:windows /debug /manifest /incremental:no /opt:REF
LDFLAGS=$(LDFLAGS) "/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"
RC=rc /nologo
RCFLAGS=/i$(INCDIR)
LIBS=
!IFDEF DEBUG
BUILD=Debug
CXXFLAGS=$(CXXFLAGS) /DDEBUG
LDFLAGS=$(LDFLAGS)
!ELSE
BUILD=Release
LDFLAGS=$(LDFLAGS)
!ENDIF
OUTDIR=build\$(BUILD)
DISTDIR=dist\$(BUILD)
FILES=$(OUTDIR)\Keyboard.obj \
$(OUTDIR)\MainWindow.obj \
$(OUTDIR)\Window.obj \
$(OUTDIR)\keyboard.res
all: initdir $(DISTDIR)\Keyboard.exe
initdir:
if not exist build md build
if not exist $(OUTDIR) md $(OUTDIR)
if not exist build md dist
if not exist $(DISTDIR) md $(DISTDIR)
$(INCDIR)\MainWindow.hpp: $(INCDIR)\Window.hpp
$(SRCDIR)\MainWindow.cpp: $(INCDIR)\MainWindow.hpp
$(SRCDIR)\Keyboard.cpp: $(INCDIR)\MainWindow.hpp
$(SRCDIR)\Window.cpp: $(INCDIR)\Window.hpp
keyboard.rc: keyboard.ico keymap.bmp
$(OUTDIR)\keyboard.res: keyboard.rc
$(RC) $(RCFLAGS) /fo$@ $**
{$(SRCDIR)}.cpp{$(OUTDIR)}.obj::
$(CXX) $(CXXFLAGS) /Fo$(OUTDIR)\ /Fd$(OUTDIR)\ $<
{$(SRCDIR)}.c{$(OUTDIR)}.obj::
$(CXX) $(CXXFLAGS) /Fo$(OUTDIR)\ /Fd$(OUTDIR)\ $<
$(DISTDIR)\Keyboard.exe: $(FILES)
$(LD) /out:$@ $(LDFLAGS) $** $(LIBS)
mt.exe -nologo -manifest $@.manifest -outputresource:$@;1 && del $@.manifest || set ERRORLEVEL=0

42
include/MainWindow.hpp Normal file
View file

@ -0,0 +1,42 @@
#pragma once
#ifndef id68C60171_0140_4DE1_B7255EFF557A74F9
#define id68C60171_0140_4DE1_B7255EFF557A74F9
#include <Window.hpp>
#include <mmsystem.h>
#include <commctrl.h>
#include <shellapi.h>
class MainWindow : public Window {
public:
virtual LPCTSTR ClassName() { return TEXT("MusicKeyboardMain"); }
static MainWindow *Create(LPCTSTR szTitle);
protected:
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnCreate();
LRESULT OnDestroy();
bool Play(WPARAM wCode, LPARAM lParam, bool down);
void OnPaint();
void PaintContent(PAINTSTRUCT *pps);
BOOL WinRegisterClass(WNDCLASS *pwc);
WORD GetQWERTYKeyCode(WORD wKeyCode);
WORD GetRealKeyCode(WORD wQWERTYCode);
virtual HICON GetIcon();
HWND m_volumeLabel, m_volumeBar;
HWND m_forceLabel, m_forceBar;
HWND m_instruLabel, m_instruSelect;
int m_instrument, m_volume, m_force;
HMIDIOUT m_midi;
bool isQWERTY;
HKL hklQWERTY;
private:
HFONT hFont;
HBRUSH hBrush;
HBITMAP hKeyboardLayout;
HDC hdcKeyboard;
};
#endif

65
include/Window.hpp Normal file
View file

@ -0,0 +1,65 @@
#pragma once
#ifndef idC3714409_EABC_45DE_B5338EC60149AE87
#define idC3714409_EABC_45DE_B5338EC60149AE87
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
inline void MakeRect(RECT &rect, int x, int y, int cx, int cy)
{
rect.left = x;
rect.top = y;
rect.right = x + cx;
rect.bottom = y + cy;
}
inline void MakeRectRight(RECT &rect, int x, int y, int cx, int cy)
{
MakeRect(rect, x - cx, y, cx, cy);
}
inline void MakeRectBottom(RECT &rect, int x, int y, int cx, int cy)
{
MakeRect(rect, x, y - cy, cx, cy);
}
inline void MakeRectBottomRight(RECT &rect, int x, int y, int cx, int cy)
{
MakeRect(rect, x - cx, y - cy, cx, cy);
}
class Window {
public:
HWND GetHWND() { return m_hwnd; }
static HINSTANCE GetInstance() {
static HINSTANCE instance = (HINSTANCE) GetModuleHandle(NULL);
return instance; // Doesn't change
}
protected:
virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual void PaintContent(PAINTSTRUCT *pps) { UNREFERENCED_PARAMETER(pps); }
virtual LPCTSTR ClassName() = 0;
virtual HICON GetIcon() { return NULL; }
virtual BOOL WinRegisterClass(WNDCLASS *pwc) {
return RegisterClass(pwc);
}
virtual ~Window();
HWND WinCreateWindow(DWORD dwExStyle, LPCTSTR pszName,
DWORD dwStyle, int x, int y, int cx,
int cy, HWND hwndParent, HMENU hmenu);
private:
virtual void Register();
void OnPaint();
void OnPrintClient(HDC hdc);
static LRESULT CALLBACK
s_WndProc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam);
protected:
HWND m_hwnd;
};
#endif // header

2
include/resource.h Normal file
View file

@ -0,0 +1,2 @@
#define RID_ICON 1
#define RID_KEYBOARD 2

BIN
keyboard.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
keyboard.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

137
keyboard.rc Normal file
View file

@ -0,0 +1,137 @@
#include <resource.h>
#include <winnls.h>
RID_ICON ICON keyboard.ico
RID_KEYBOARD BITMAP keymap.bmp
STRINGTABLE LANGUAGE 0x09, 0x01 // en-US
BEGIN
0xAE00, "Acoustic Grand Piano"
0xAE01, "Bright Acoustic Piano"
0xAE02, "Electric Grand Piano"
0xAE03, "Honky-tonk Piano"
0xAE04, "Rhodes Piano"
0xAE05, "Chorused Piano"
0xAE06, "Harpsichord"
0xAE07, "Clavichord"
0xAE08, "Celesta"
0xAE09, "Glockenspiel"
0xAE0A, "Music box"
0xAE0B, "Vibraphone"
0xAE0C, "Marimba"
0xAE0D, "Xylophone"
0xAE0E, "Tubular Bells"
0xAE0F, "Dulcimer"
0xAE10, "Hammond Organ"
0xAE11, "Percussive Organ"
0xAE12, "Rock Organ"
0xAE13, "Church Organ"
0xAE14, "Reed Organ"
0xAE15, "Accordian"
0xAE16, "Harmonica"
0xAE17, "Tango Accordian"
0xAE18, "Acoustic Guitar (nylon)"
0xAE19, "Acoustic Guitar (steel)"
0xAE1A, "Electric Guitar (jazz)"
0xAE1B, "Electric Guitar (clean)"
0xAE1C, "Electric Guitar (muted)"
0xAE1D, "Overdriven Guitar"
0xAE1E, "Distortion Guitar"
0xAE1F, "Guitar Harmonics"
0xAE20, "Acoustic Bass"
0xAE21, "Electric Bass(finger)"
0xAE22, "Electric Bass (pick)"
0xAE23, "Fretless Bass"
0xAE24, "Slap Bass 1"
0xAE25, "Slap Bass 2"
0xAE26, "Synth Bass 1"
0xAE27, "Synth Bass 2"
0xAE28, "Violin"
0xAE29, "Viola"
0xAE2A, "Cello"
0xAE2B, "Contrabass"
0xAE2C, "Tremolo Strings"
0xAE2D, "Pizzicato Strings"
0xAE2E, "Orchestral Harp"
0xAE2F, "Timpani"
0xAE30, "String Ensemble 1"
0xAE31, "String Ensemble 2"
0xAE32, "Synth Strings 1"
0xAE33, "Synth Strings 2"
0xAE34, "Choir Aahs"
0xAE35, "Voice Oohs"
0xAE36, "Synth Voice"
0xAE37, "Orchestra Hit"
0xAE38, "Trumpet"
0xAE39, "Trombone"
0xAE3A, "Tuba"
0xAE3B, "Muted Trumpet"
0xAE3C, "French Horn"
0xAE3D, "Brass Section"
0xAE3E, "Synth Brass 1"
0xAE3F, "Synth Brass 2"
0xAE40, "Soprano Sax"
0xAE41, "Alto Sax"
0xAE42, "Tenor Sax"
0xAE43, "Baritone Sax"
0xAE44, "Oboe"
0xAE45, "English Horn"
0xAE46, "Bassoon"
0xAE47, "Clarinet"
0xAE48, "Piccolo"
0xAE49, "Flute"
0xAE4A, "Recorder"
0xAE4B, "Pan Flute"
0xAE4C, "Bottle Blow"
0xAE4D, "Shakuhachi"
0xAE4E, "Whistle"
0xAE4F, "Ocarina"
0xAE50, "Lead 1 (square)"
0xAE51, "Lead 2 (sawtooth)"
0xAE52, "Lead 3 (caliope lead)"
0xAE53, "Lead 4 (chiff lead)"
0xAE54, "Lead 5 (charang)"
0xAE55, "Lead 6 (voice)"
0xAE56, "Lead 7 (fifths)"
0xAE57, "87 Lead 8 (bass+lead) "
0xAE58, "Pad 1 (new age)"
0xAE59, "Pad 2 (warm)"
0xAE5A, "Pad 3 (polysynth)"
0xAE5B, "Pad 4 (choir)"
0xAE5C, "Pad 5 (bowed)"
0xAE5D, "Pad 6 (metallic)"
0xAE5E, "Pad 7 (halo)"
0xAE5F, "Pad 8 (sweep)"
0xAE60, "FX 1 (rain)"
0xAE61, "FX 2 (soundtrack)"
0xAE62, "FX 3 (crystal)"
0xAE63, "FX 4 (atmosphere)"
0xAE64, "FX 5 (brightness)"
0xAE65, "FX 6 (goblins)"
0xAE66, "FX 7 (echoes)"
0xAE67, "FX 8 (sci-fi)"
0xAE68, "Sitar"
0xAE69, "Banjo"
0xAE6A, "Shamisen"
0xAE6B, "Koto"
0xAE6C, "Kalimba"
0xAE6D, "Bagpipe"
0xAE6E, "Fiddle"
0xAE6F, "Shanai"
0xAE70, "Tinkle Bell"
0xAE71, "Agogo"
0xAE72, "Steel Drums"
0xAE73, "Woodblock"
0xAE74, "Taiko Drum"
0xAE75, "Melodic Tom"
0xAE76, "Synth Drum"
0xAE77, "Reverse Cymbal"
0xAE78, "Guitar Fret Noise"
0xAE79, "Breath Noise"
0xAE7A, "Seashore"
0xAE7B, "Bird Tweet"
0xAE7C, "Telephone Ring"
0xAE7D, "Helicopter"
0xAE7E, "Applause"
0xAE7F, "Gunshot"
END

BIN
keymap.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

22
src/Keyboard.cpp Normal file
View file

@ -0,0 +1,22 @@
#include <MainWindow.hpp>
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) {
UNREFERENCED_PARAMETER(hInstance);
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
InitCommonControls();
MainWindow *win = MainWindow::Create(L"Music Keyboard");
if (win) {
ShowWindow(win->GetHWND(), nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}

395
src/MainWindow.cpp Normal file
View file

@ -0,0 +1,395 @@
#include <MainWindow.hpp>
#include <resource.h>
#include <commctrl.h>
#include <windowsx.h>
#define LEFT(x, y, cx, cy) x, y, cx, cy
#define RIGHT(x, y, cx, cy) (x - cx), y, cx, cy
#define BOTTOM(x, y, cx, cy) x, (y - cy), cx, cy
#define BOTTOMRIGHT(x, y, cx, cy) (x - cx), (y - cy), cx, cy
#define KEYBOARD_IMAGE 0xAA00
#define KEYBOARD_VOLUME 0xAA01
#define KEYBOARD_FORCE 0xAA02
#define KEYBOARD_INSTRUMENT 0xAA03
#define MIDI_MESSAGE(handle, code, arg1, arg2) \
midiOutShortMsg(handle, ((arg2 & 0x7F) << 16) |\
((arg1 & 0x7F) << 8) | (code & 0xFF))
#pragma comment(lib, "winmm.lib")
DWORD rgbWindowBackground;
static char keymap[256];
BOOL MainWindow::WinRegisterClass(WNDCLASS *pwc)
{
pwc->style = CS_HREDRAW | CS_VREDRAW;
return __super::WinRegisterClass(pwc);
}
BOOL EnableCloseButton(const HWND hwnd, const BOOL bState)
{
HMENU hMenu;
UINT dwExtra;
if (hwnd == NULL)
return FALSE;
if ((hMenu = GetSystemMenu(hwnd, FALSE)) == NULL)
return FALSE;
dwExtra = bState ? MF_ENABLED : (MF_DISABLED | MF_GRAYED);
return EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | dwExtra) != -1;
}
LRESULT MainWindow::OnCreate()
{
NONCLIENTMETRICS ncmMetrics = { sizeof(NONCLIENTMETRICS) };
RECT client;
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncmMetrics, 0);
GetClientRect(m_hwnd, &client);
hFont = CreateFontIndirect(&ncmMetrics.lfMessageFont);
rgbWindowBackground = GetSysColor(COLOR_WINDOW);
hBrush = GetSysColorBrush(COLOR_WINDOW);
hKeyboardLayout = (HBITMAP) LoadImage(GetInstance(), MAKEINTRESOURCE(RID_KEYBOARD),
IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT);
hdcKeyboard = CreateCompatibleDC(GetDC(m_hwnd));
SelectBitmap(hdcKeyboard, hKeyboardLayout);
// Children
m_volumeLabel = CreateWindow(WC_STATIC, L"Volume:",
WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 0, 0, 0, 0,
m_hwnd, NULL, GetInstance(), NULL);
m_forceLabel = CreateWindow(WC_STATIC, L"Force:",
WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 0, 0, 0, 0,
m_hwnd, NULL, GetInstance(), NULL);
m_instruLabel = CreateWindow(WC_STATIC, L"Instrument:",
WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 0, 0, 0, 0,
m_hwnd, NULL, GetInstance(), NULL);
m_volumeBar = CreateWindow(TRACKBAR_CLASS, NULL,
WS_CHILD | WS_VISIBLE | TBS_NOTICKS, 0, 0, 0, 0,
m_hwnd, (HMENU) KEYBOARD_VOLUME, GetInstance(), NULL);
m_forceBar = CreateWindow(TRACKBAR_CLASS, NULL,
WS_CHILD | WS_VISIBLE | TBS_NOTICKS, 0, 0, 0, 0,
m_hwnd, (HMENU) KEYBOARD_FORCE, GetInstance(), NULL);
m_instruSelect = CreateWindow(WC_COMBOBOX, NULL, WS_CHILD | WS_VISIBLE |
CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL, 0, 0, 0, 0,
m_hwnd, (HMENU) KEYBOARD_INSTRUMENT, GetInstance(), NULL);
SendMessage(m_volumeBar, TBM_SETRANGEMIN, FALSE, 0x0000);
SendMessage(m_volumeBar, TBM_SETRANGEMAX, FALSE, 0xFFFF);
SendMessage(m_forceBar, TBM_SETRANGE, FALSE, 127 << 16);
SendMessage(m_volumeBar, TBM_SETPOS, FALSE, 0xFFFF);
SendMessage(m_forceBar, TBM_SETPOS, FALSE, 64);
m_force = 64;
m_volume = 0xFFFF;
WCHAR buf[MAX_PATH];
int piano;
SendMessage(m_instruSelect, CB_INITSTORAGE, 128, 4096);
for (int i = 0; i < 128; ++i) {
int id;
LoadString(GetInstance(), 0xAE00 | i, buf, MAX_PATH);
id = SendMessage(m_instruSelect, CB_ADDSTRING, 0, (LPARAM) buf);
SendMessage(m_instruSelect, CB_SETITEMDATA, id, i);
}
LoadString(GetInstance(), 0xAE00, buf, MAX_PATH);
piano = SendMessage(m_instruSelect, CB_FINDSTRING, 0, (LPARAM) buf);
SendMessage(m_instruSelect, CB_SETCURSEL, piano, 0);
#define SETFONT(hwnd) PostMessage(hwnd, WM_SETFONT, (WPARAM) hFont, (LPARAM) TRUE)
SETFONT(m_volumeLabel);
SETFONT(m_volumeBar);
SETFONT(m_forceLabel);
SETFONT(m_forceBar);
SETFONT(m_instruLabel);
SETFONT(m_instruSelect);
#undef SETFONT
if (midiOutOpen(&m_midi, 0, NULL, NULL, CALLBACK_NULL) != MMSYSERR_NOERROR)
MessageBox(m_hwnd, L"Failed to open MIDI device!", L"Fatal Error", MB_ICONERROR);
keymap[VK_OEM_3] = 54; // `~ key
keymap['Q'] = 55;
keymap[VK_TAB] = 55;
keymap['A'] = 57;
keymap['Z'] = 57;
keymap['W'] = 56;
keymap['E'] = 58;
keymap['S'] = 59;
keymap['X'] = 59;
keymap['D'] = 60;
keymap['C'] = 60;
keymap['R'] = 61;
keymap['F'] = 62;
keymap['V'] = 62;
keymap['T'] = 63;
keymap['G'] = 64;
keymap['B'] = 64;
keymap['H'] = 65;
keymap['N'] = 65;
keymap['U'] = 66;
keymap['J'] = 67;
keymap['M'] = 67;
keymap['I'] = 68;
keymap['K'] = 69;
keymap[VK_OEM_COMMA] = 69;
keymap['O'] = 70;
keymap['L'] = 71;
keymap[VK_OEM_PERIOD] = 71;
keymap[VK_OEM_1] = 72; // ;:
keymap[VK_OEM_2] = 72; // /?
keymap[VK_OEM_7] = 74; // '"
keymap[VK_OEM_4] = 73; // [
keymap[VK_OEM_6] = 75; // ]
keymap[VK_RETURN] = 76;
keymap[VK_OEM_5] = 77; // \|
keymap[VK_BACK] = 77;
keymap[0x31] = 57;
keymap[0x32] = 59;
keymap[0x33] = 60;
keymap[0x34] = 62;
keymap[0x35] = 64;
keymap[0x36] = 65;
keymap[0x37] = 67;
keymap[0x38] = 69;
keymap[0x39] = 71;
keymap[0x30] = 72;
keymap[VK_OEM_MINUS] = 74;
keymap[VK_OEM_PLUS] = 76;
PostMessage(m_hwnd, WM_INPUTLANGCHANGE, 0, 0);
SetTimer(m_hwnd, 0xDE00, 1000, NULL);
return 0;
}
LRESULT MainWindow::OnDestroy()
{
DestroyWindow(m_volumeLabel);
DestroyWindow(m_volumeBar);
DestroyWindow(m_forceLabel);
DestroyWindow(m_forceBar);
DestroyWindow(m_instruLabel);
DestroyWindow(m_instruSelect);
midiOutClose(m_midi);
return 0;
}
HICON MainWindow::GetIcon()
{
return LoadIcon(GetInstance(), MAKEINTRESOURCE(RID_ICON));
}
void MainWindow::PaintContent(PAINTSTRUCT *pps)
{
BITMAP bm;
int cx, cy, tx, ty, x, y;
double ratio;
RECT client;
GetClientRect(m_hwnd, &client);
GetObject(hKeyboardLayout, sizeof(BITMAP), &bm);
cx = client.right - 24, cy = client.bottom - 117;
ratio = ((double) bm.bmWidth) / ((double) bm.bmHeight);
if (cx / ratio > cy)
tx = (int) (cy * ratio), ty = (int) cy;
else
tx = (int) cx, ty = (int) (cx / ratio);
x = 12 + (cx - tx) / 2;
y = 12 + (cy - ty) / 2;
StretchBlt(pps->hdc, x, y, tx, ty, hdcKeyboard, 0, 0, bm.bmWidth, bm.bmHeight, SRCAND);
}
void MainWindow::OnPaint()
{
PAINTSTRUCT ps;
BeginPaint(m_hwnd, &ps);
PaintContent(&ps);
EndPaint(m_hwnd, &ps);
}
WORD MainWindow::GetQWERTYKeyCode(WORD wKeyCode)
{
if (isQWERTY)
return wKeyCode;
UINT uiScan = MapVirtualKey(wKeyCode, MAPVK_VK_TO_VSC);
if (!uiScan)
return wKeyCode;
UINT uiQWERTY = MapVirtualKeyEx(uiScan, MAPVK_VSC_TO_VK, hklQWERTY);
if (uiScan)
return (WORD) uiQWERTY;
else
return wKeyCode;
}
WORD MainWindow::GetRealKeyCode(WORD wQWERTYCode)
{
if (isQWERTY)
return wQWERTYCode;
UINT uiScan = MapVirtualKeyEx(wQWERTYCode, MAPVK_VK_TO_VSC, hklQWERTY);
if (!uiScan)
return wQWERTYCode;
UINT uiKeyCode = MapVirtualKey(uiScan, MAPVK_VSC_TO_VK);
if (uiScan)
return (WORD) uiKeyCode;
else
return wQWERTYCode;
}
int GetMIDINote(WPARAM wCode)
{
int state = 0;
int note;
if (GetKeyState(VK_CONTROL) < 0)
state |= 0x001;
if (GetKeyState(VK_SHIFT) < 0)
state |= 0x010;
if (GetKeyState(VK_MENU) < 0)
state |= 0x100;
note = keymap[wCode];
switch (state) {
case 0x001:
note -= 24;
break;
case 0x010:
note += 24;
break;
case 0x100:
note += 48;
break;
}
return note;
}
bool MainWindow::Play(WPARAM wCode, LPARAM lParam, bool down)
{
int note;
wCode = GetQWERTYKeyCode((WORD) wCode);
if (wCode > 255 || !keymap[wCode] || (down && (lParam & 0x40000000)))
return false;
note = GetMIDINote(wCode);
if (down) {
int num = note;
while (num > 24)
num -= 24;
while (num < 0x7F) {
if (num != note)
MIDI_MESSAGE(m_midi, 0x90, num, 0);
num += 24;
}
}
if (down)
MIDI_MESSAGE(m_midi, 0x90, note, m_force);
else
MIDI_MESSAGE(m_midi, 0x90, note, 0);
return true;
}
LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_CREATE:
return OnCreate();
case WM_DESTROY:
return OnDestroy();
case WM_NCDESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
OnPaint();
return 0;
case WM_SIZE: {
RECT client;
HDWP hdwp;
GetClientRect(m_hwnd, &client);
#define REPOS(hwnd, k) hdwp = DeferWindowPos(hdwp, hwnd, 0, k, SWP_NOACTIVATE|SWP_NOZORDER)
hdwp = BeginDeferWindowPos(14);
REPOS(m_volumeLabel, BOTTOM(12, client.bottom - 12, 70, 25));
REPOS(m_volumeBar, BOTTOM(82, client.bottom - 12, client.right - 94, 25));
REPOS(m_forceLabel, BOTTOM(12, client.bottom - 42, 70, 25));
REPOS(m_forceBar, BOTTOM(82, client.bottom - 42, client.right - 94, 25));
REPOS(m_instruLabel, BOTTOM(12, client.bottom - 72, 70, 25));
REPOS(m_instruSelect, BOTTOM(82, client.bottom - 72, client.right - 94, 25));
EndDeferWindowPos(hdwp);
#undef REPOS
return 0;
}
case WM_COMMAND:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
switch (LOWORD(wParam)) {
case KEYBOARD_INSTRUMENT:
m_instrument = SendMessage((HWND) lParam, CB_GETITEMDATA,
SendMessage((HWND) lParam, CB_GETCURSEL, 0, 0), 0);
MIDI_MESSAGE(m_midi, 0xC0, m_instrument, 0);
}
}
break;
case WM_HSCROLL:
switch (LOWORD(wParam)) {
case TB_THUMBPOSITION:
if (lParam == (LPARAM) m_volumeBar) {
m_volume = HIWORD(wParam);
midiOutSetVolume(m_midi, m_volume);
} else if (lParam == (LPARAM) m_forceBar)
m_force = HIWORD(wParam);
break;
}
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (Play(wParam, lParam, true))
return 0;
break;
case WM_KEYUP:
case WM_SYSKEYUP:
if (Play(wParam, lParam, false))
return 0;
break;
case WM_LBUTTONDOWN:
SetFocus(m_hwnd);
return 0;
case WM_MOUSEWHEEL:
if (GetFocus() != m_forceBar)
SendMessage(m_forceBar, WM_MOUSEWHEEL,
-GET_WHEEL_DELTA_WPARAM(wParam) * 2 << 16 |
GET_KEYSTATE_WPARAM(wParam), lParam);
case WM_INPUTLANGCHANGE: {
TCHAR buf[KL_NAMELENGTH];
GetKeyboardLayoutName(buf);
isQWERTY = lstrcmpi(buf, L"00000409") == 0;
if (!isQWERTY && !hklQWERTY)
hklQWERTY = LoadKeyboardLayout(L"00000409", KLF_NOTELLSHELL);
}
case WM_CHAR:
case WM_DEADCHAR:
case WM_SYSCHAR:
case WM_SYSDEADCHAR:
return 0;
case WM_ENTERSIZEMOVE:
SetWindowLongPtr(m_hwnd, GWL_EXSTYLE, GetWindowLongPtr(m_hwnd, GWL_EXSTYLE) | WS_EX_COMPOSITED);
return 0;
case WM_EXITSIZEMOVE:
SetWindowLongPtr(m_hwnd, GWL_EXSTYLE, GetWindowLongPtr(m_hwnd, GWL_EXSTYLE) & ~WS_EX_COMPOSITED);
return 0;
}
return __super::HandleMessage(uMsg, wParam, lParam);
}
MainWindow *MainWindow::Create(LPCTSTR szTitle)
{
MainWindow *self = new MainWindow();
RECT client = {0, 0, 622, 286};
AdjustWindowRect(&client, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, FALSE);
if (self &&
self->WinCreateWindow(0,
szTitle, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT, client.right - client.left,
client.bottom - client.top, NULL, NULL)) {
return self;
}
delete self;
return NULL;
}

88
src/Window.cpp Normal file
View file

@ -0,0 +1,88 @@
#include <window.hpp>
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
HWND Window::WinCreateWindow(DWORD dwExStyle, LPCTSTR pszName,
DWORD dwStyle, int x, int y, int cx,
int cy, HWND hwndParent, HMENU hmenu)
{
Register();
return CreateWindowEx(dwExStyle, ClassName(), pszName, dwStyle,
x, y, cx, cy, hwndParent, hmenu, GetInstance(),
this);
}
Window::~Window() {}
void Window::Register()
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = Window::s_WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetInstance();
wc.hIcon = GetIcon();
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = CreateSolidBrush(RGB(0xF0, 0xF0, 0xF0));
wc.lpszMenuName = NULL;
wc.lpszClassName = ClassName();
WinRegisterClass(&wc);
}
LRESULT CALLBACK
Window::s_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
Window *self;
if (uMsg == WM_NCCREATE) {
LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam;
self = (Window *)(lpcs->lpCreateParams);
self->m_hwnd = hwnd;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM) self);
} else {
self = (Window *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
if (self) {
return self->HandleMessage(uMsg, wParam, lParam);
} else {
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
LRESULT Window::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_NCDESTROY: {
LRESULT lres;
lres = DefWindowProc(m_hwnd, uMsg, wParam, lParam);
SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
delete this;
return lres;
}
case WM_PAINT:
OnPaint();
return 0;
case WM_PRINTCLIENT:
OnPrintClient(reinterpret_cast<HDC>(wParam));
return 0;
}
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
void Window::OnPaint()
{
PAINTSTRUCT ps;
BeginPaint(m_hwnd, &ps);
PaintContent(&ps);
EndPaint(m_hwnd, &ps);
}
void Window::OnPrintClient(HDC hdc)
{
PAINTSTRUCT ps;
ps.hdc = hdc;
GetClientRect(m_hwnd, &ps.rcPaint);
PaintContent(&ps);
}