mirror of
https://github.com/quantum5/MusicKeyboard.git
synced 2025-04-24 13:11:58 -04:00
Initial Commit.
Signed-off-by: Xiaomao Chen <xiaomao5@live.com>
This commit is contained in:
commit
be89fa7bf6
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
*.obj
|
||||
*.exe
|
||||
*.res
|
||||
/build
|
||||
/dist
|
||||
/test
|
||||
/old
|
||||
/*.pdb
|
55
Makefile
Normal file
55
Makefile
Normal 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
42
include/MainWindow.hpp
Normal 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
65
include/Window.hpp
Normal 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
2
include/resource.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define RID_ICON 1
|
||||
#define RID_KEYBOARD 2
|
BIN
keyboard.bmp
Normal file
BIN
keyboard.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
BIN
keyboard.ico
Normal file
BIN
keyboard.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
137
keyboard.rc
Normal file
137
keyboard.rc
Normal 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
BIN
keymap.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
22
src/Keyboard.cpp
Normal file
22
src/Keyboard.cpp
Normal 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
395
src/MainWindow.cpp
Normal 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
88
src/Window.cpp
Normal 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);
|
||||
}
|
Loading…
Reference in a new issue