Added mouse support.

This commit is contained in:
Quantum 2013-09-09 18:14:14 -04:00
parent f100921c57
commit 282f8bb7c8
4 changed files with 126 additions and 4 deletions

View file

@ -13,6 +13,7 @@ class MainWindow : public Window {
public:
virtual LPCTSTR ClassName() { return TEXT("MusicKeyboardMain"); }
static MainWindow *Create(LPCTSTR szTitle);
void PlayNote(int note, bool down);
protected:
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnCreate();

View file

@ -16,6 +16,8 @@
#define MPCM_SETKEYTEXT (WM_USER + 5)
#define MPCM_GETBACKGROUND (WM_USER + 6)
#define MPCM_SETBACKGROUND (WM_USER + 7)
#define MMWM_TURNNOTE (WM_APP + 0)
#define MMWM_NOTEID (WM_APP + 1)
class PianoControl : public Window {
public:
@ -48,12 +50,14 @@ protected:
BOOL WinRegisterClass(WNDCLASS *pwc);
virtual int keyIDToInternal(int id, bool &black);
virtual int internalToKeyID(int id, bool black);
virtual bool haveBlackToLeft(int id);
virtual bool haveBlackToRight(int id);
int haveBlack(int id) {
return (haveBlackToLeft(id) ? 2 : 0) | (haveBlackToRight(id) ? 1 : 0);
}
virtual void UpdateKey(int key, bool black);
virtual int hitTest(int x, int y, bool &black);
bool *blackStatus;
bool *whiteStatus;
@ -68,6 +72,9 @@ protected:
HBITMAP hMemBitmap;
HBRUSH hBackground;
int bmx, bmy;
bool mouseDown;
int lastNote, lastKey;
};
#endif

View file

@ -264,6 +264,13 @@ bool MainWindow::Play(WPARAM wParam, LPARAM lParam, bool down)
return false;
note = GetMIDINote(wCode);
PlayNote(note, down);
piano->SetKeyStatus((note - 6) % 24, down);
return true;
}
void MainWindow::PlayNote(int note, bool down)
{
if (down) {
int num = note % 24;
while (num < 0x7F) {
@ -276,8 +283,6 @@ bool MainWindow::Play(WPARAM wParam, LPARAM lParam, bool down)
MIDI_MESSAGE(m_midi, 0x90, note, m_force);
else
MIDI_MESSAGE(m_midi, 0x90, note, 0);
piano->SetKeyStatus((note - 6) % 24, down);
return true;
}
LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
@ -392,6 +397,32 @@ LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_EXITSIZEMOVE:
SetWindowLongPtr(m_hwnd, GWL_EXSTYLE, GetWindowLongPtr(m_hwnd, GWL_EXSTYLE) & ~WS_EX_COMPOSITED);
return 0;
case MMWM_NOTEID: {
int state = 0;
if (GetKeyState(VK_CONTROL) < 0)
state |= 0x001;
if (GetKeyState(VK_SHIFT) < 0)
state |= 0x010;
if (GetKeyState(VK_MENU) < 0)
state |= 0x100;
int note = wParam + 54;
switch (state) {
case 0x001:
note -= 24;
break;
case 0x010:
note += 24;
break;
case 0x100:
note += 48;
break;
}
return note;
}
case MMWM_TURNNOTE:
PlayNote((int) wParam, lParam != 0);
return 0;
}
return Window::HandleMessage(uMsg, wParam, lParam);
}

View file

@ -1,4 +1,5 @@
#include <PianoControl.hpp>
#include <MainWindow.hpp>
#include <windowsx.h>
#include <stdio.h>
@ -30,6 +31,8 @@ LRESULT PianoControl::OnCreate()
blackStatus = whiteStatus = NULL;
blackText = whiteText = NULL;
mouseDown = false;
lastNote = lastKey = 0;
SetOctaves(2);
return 0;
@ -171,6 +174,16 @@ int PianoControl::keyIDToInternal(int id, bool &black) {
return id / 12 * 7 + ret;
}
static int internalToKeyIDMap[7] = {1, 3, 5, 6, 8, 10, 11};
int PianoControl::internalToKeyID(int id, bool black)
{
id = id / 7 * 12 + internalToKeyIDMap[id % 7];
if (black)
--id;
return id;
}
bool PianoControl::haveBlackToLeft(int i) {
switch (i % 7) {
case 0: // G
@ -206,6 +219,43 @@ bool PianoControl::haveBlackToRight(int i) {
return false; // not reached
}
int PianoControl::hitTest(int x, int y, bool &black)
{
RECT client;
int width, height;
int wwidth, bwidth, bheight, hbwidth;
GetClientRect(m_hwnd, &client);
width = client.right - client.left;
height = client.bottom - client.top;
wwidth = width / 7 / octaves; // Displaying 14 buttons.
bwidth = width / 12 / octaves; // smaller
bheight = height / 2;
bheight = height / 2;
hbwidth = bwidth / 2;
int key = x / wwidth;
int dx = x % wwidth;
if (y < bheight && (dx < hbwidth || dx > (wwidth - hbwidth))) {
int temp = key;
if (dx >= hbwidth)
++temp;
switch (temp % 7) {
case 0:
case 1:
case 2:
case 4:
case 5:
black = true;
return temp;
}
}
black = false;
return key;
}
void PianoControl::PaintContent(PAINTSTRUCT *pps)
{
RECT client, rect;
@ -459,8 +509,41 @@ LRESULT PianoControl::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_SIZE:
InvalidateRect(m_hwnd, NULL, TRUE);
return 0;
case WM_LBUTTONDOWN:
SetFocus(hwParent);
case WM_LBUTTONDOWN: {
/*if (mouseDown)
return 0;*/
bool black;
int internal = hitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), black);
int key = internalToKeyID(internal, black);
int external = SendMessage(hwParent, MMWM_NOTEID, key, 0);
SendMessage(hwParent, MMWM_TURNNOTE, external, 1);
SetKeyStatus(key, true);
lastNote = external;
lastKey = key;
mouseDown = true;
return 0;
}
case WM_LBUTTONUP: {
SendMessage(hwParent, MMWM_TURNNOTE, lastNote, 0);
SetKeyStatus(lastKey, false);
mouseDown = false;
return 0;
}
case WM_MOUSEMOVE:
if (mouseDown) {
bool black;
int internal = hitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), black);
int key = internalToKeyID(internal, black);
int external = SendMessage(hwParent, MMWM_NOTEID, key, 0);
if (lastNote != external) {
SendMessage(hwParent, MMWM_TURNNOTE, lastNote, 0);
SetKeyStatus(lastKey, false);
SendMessage(hwParent, MMWM_TURNNOTE, external, 1);
SetKeyStatus(key, true);
lastNote = external;
lastKey = key;
}
}
return 0;
case WM_KEYDOWN:
case WM_SYSKEYDOWN: