mirror of
https://github.com/quantum5/MusicKeyboard.git
synced 2025-04-24 13:11:58 -04:00
Added mouse support.
This commit is contained in:
parent
f100921c57
commit
282f8bb7c8
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue