mirror of
https://github.com/quantum5/MusicKeyboard.git
synced 2025-04-24 13:11:58 -04:00
Working touch support.
This commit is contained in:
parent
0f297cfae3
commit
c8a835e83f
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@ INCDIR=include
|
||||||
|
|
||||||
CXX=cl /nologo
|
CXX=cl /nologo
|
||||||
LD=link /nologo
|
LD=link /nologo
|
||||||
CXXFLAGS=/c /O1 /I$(INCDIR) /W4 /Zi /DWIN32_LEAN_AND_MEAN /DWINVER=0x0501 /D_WIN32_WINNT=0x0501 /DUNICODE /D_UNICODE
|
CXXFLAGS=/c /O1 /I$(INCDIR) /W4 /Zi /DWIN32_LEAN_AND_MEAN /DWINVER=0x0601 /D_WIN32_WINNT=0x0601 /DUNICODE /D_UNICODE
|
||||||
LDFLAGS=/subsystem:windows /debug /incremental:no /opt:REF
|
LDFLAGS=/subsystem:windows /debug /incremental:no /opt:REF
|
||||||
RC=rc /nologo
|
RC=rc /nologo
|
||||||
RCFLAGS=/i$(INCDIR)
|
RCFLAGS=/i$(INCDIR)
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
|
||||||
|
typedef BOOL (WINAPI *T_GetTouchInputInfo)(HTOUCHINPUT hTouchInput, UINT cInputs, PTOUCHINPUT pInputs, int cbSize);
|
||||||
|
typedef BOOL (WINAPI *T_CloseTouchInputHandle)(HTOUCHINPUT hTouchInput);
|
||||||
|
typedef BOOL (WINAPI *T_RegisterTouchWindow)(HWND hWnd, ULONG ulFlags);
|
||||||
|
|
||||||
#define MPCM_GETKEYSTATUS (WM_USER + 0)
|
#define MPCM_GETKEYSTATUS (WM_USER + 0)
|
||||||
#define MPCM_SETKEYSTATUS (WM_USER + 1)
|
#define MPCM_SETKEYSTATUS (WM_USER + 1)
|
||||||
#define MPCM_GETOCTAVES (WM_USER + 2)
|
#define MPCM_GETOCTAVES (WM_USER + 2)
|
||||||
|
@ -19,6 +23,15 @@
|
||||||
#define MMWM_TURNNOTE (WM_APP + 0)
|
#define MMWM_TURNNOTE (WM_APP + 0)
|
||||||
#define MMWM_NOTEID (WM_APP + 1)
|
#define MMWM_NOTEID (WM_APP + 1)
|
||||||
|
|
||||||
|
#define MAXPOINTS 20
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool down;
|
||||||
|
POINTL point;
|
||||||
|
int lastNote;
|
||||||
|
int lastKey;
|
||||||
|
} PianoTouchPoint;
|
||||||
|
|
||||||
class PianoControl : public Window {
|
class PianoControl : public Window {
|
||||||
public:
|
public:
|
||||||
virtual LPCTSTR ClassName() { return TEXT("KeyboardControl"); }
|
virtual LPCTSTR ClassName() { return TEXT("KeyboardControl"); }
|
||||||
|
@ -26,13 +39,13 @@ public:
|
||||||
DWORD dwStyle = 0,
|
DWORD dwStyle = 0,
|
||||||
int x = CW_USEDEFAULT, int y = CW_USEDEFAULT,
|
int x = CW_USEDEFAULT, int y = CW_USEDEFAULT,
|
||||||
int cx = CW_USEDEFAULT, int cy = CW_USEDEFAULT);
|
int cx = CW_USEDEFAULT, int cy = CW_USEDEFAULT);
|
||||||
|
|
||||||
virtual void SetOctaves(int octaves);
|
virtual void SetOctaves(int octaves);
|
||||||
virtual int GetOctaves() { return octaves; }
|
virtual int GetOctaves() { return octaves; }
|
||||||
|
|
||||||
virtual void SetKeyStatus(int key, bool down);
|
virtual void SetKeyStatus(int key, bool down);
|
||||||
virtual bool GetKeyStatus(int key);
|
virtual bool GetKeyStatus(int key);
|
||||||
|
|
||||||
virtual void SetKeyText(int key, LPCWSTR text);
|
virtual void SetKeyText(int key, LPCWSTR text);
|
||||||
virtual LPCWSTR GetKeyText(int key);
|
virtual LPCWSTR GetKeyText(int key);
|
||||||
|
|
||||||
|
@ -41,7 +54,7 @@ public:
|
||||||
|
|
||||||
virtual void SetBackground(HBRUSH background) { hBackground = background; }
|
virtual void SetBackground(HBRUSH background) { hBackground = background; }
|
||||||
virtual HBRUSH GetBackground() { return hBackground; }
|
virtual HBRUSH GetBackground() { return hBackground; }
|
||||||
|
|
||||||
HFONT GetFont() { return hFont; }
|
HFONT GetFont() { return hFont; }
|
||||||
void SetFont(HFONT font) { hFont = font; }
|
void SetFont(HFONT font) { hFont = font; }
|
||||||
protected:
|
protected:
|
||||||
|
@ -51,7 +64,15 @@ protected:
|
||||||
void OnPaint();
|
void OnPaint();
|
||||||
virtual void PaintContent(PAINTSTRUCT *pps);
|
virtual void PaintContent(PAINTSTRUCT *pps);
|
||||||
BOOL WinRegisterClass(WNDCLASS *pwc);
|
BOOL WinRegisterClass(WNDCLASS *pwc);
|
||||||
|
|
||||||
|
void OnTouchPoint(UINT id, int x, int y);
|
||||||
|
int GetTouchPointID(DWORD dwID);
|
||||||
|
PianoTouchPoint touchPoint[MAXPOINTS];
|
||||||
|
DWORD touchPointID[MAXPOINTS];
|
||||||
|
bool hasTouch;
|
||||||
|
T_GetTouchInputInfo F_GetTouchInputInfo;
|
||||||
|
T_CloseTouchInputHandle F_CloseTouchInputHandle;
|
||||||
|
|
||||||
virtual int keyIDToInternal(int id, bool &black);
|
virtual int keyIDToInternal(int id, bool &black);
|
||||||
virtual int internalToKeyID(int id, bool black);
|
virtual int internalToKeyID(int id, bool black);
|
||||||
virtual bool haveBlackToLeft(int id);
|
virtual bool haveBlackToLeft(int id);
|
||||||
|
@ -61,21 +82,21 @@ protected:
|
||||||
}
|
}
|
||||||
virtual void UpdateKey(int key, bool black);
|
virtual void UpdateKey(int key, bool black);
|
||||||
virtual int hitTest(int x, int y, bool &black);
|
virtual int hitTest(int x, int y, bool &black);
|
||||||
|
|
||||||
bool *blackStatus;
|
bool *blackStatus;
|
||||||
bool *whiteStatus;
|
bool *whiteStatus;
|
||||||
LPCWSTR *blackText;
|
LPCWSTR *blackText;
|
||||||
LPCWSTR *whiteText;
|
LPCWSTR *whiteText;
|
||||||
|
|
||||||
int octaves;
|
int octaves;
|
||||||
HFONT hFont;
|
HFONT hFont;
|
||||||
HWND hwParent;
|
HWND hwParent;
|
||||||
|
|
||||||
HDC hMemDC;
|
HDC hMemDC;
|
||||||
HBITMAP hMemBitmap;
|
HBITMAP hMemBitmap;
|
||||||
HBRUSH hBackground;
|
HBRUSH hBackground;
|
||||||
int bmx, bmy;
|
int bmx, bmy;
|
||||||
|
|
||||||
bool mouseDown;
|
bool mouseDown;
|
||||||
int lastNote, lastKey;
|
int lastNote, lastKey;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,11 +4,16 @@
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <tpcshrd.h>
|
||||||
|
|
||||||
#ifndef max
|
#ifndef max
|
||||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MOUSEEVENTF_FROMTOUCH 0xFF515700
|
||||||
|
|
||||||
BOOL PianoControl::WinRegisterClass(WNDCLASS *pwc)
|
BOOL PianoControl::WinRegisterClass(WNDCLASS *pwc)
|
||||||
{
|
{
|
||||||
return Window::WinRegisterClass(pwc);
|
return Window::WinRegisterClass(pwc);
|
||||||
|
@ -24,16 +29,48 @@ LRESULT PianoControl::OnCreate()
|
||||||
|
|
||||||
hFont = CreateFontIndirect(&ncmMetrics.lfMessageFont);
|
hFont = CreateFontIndirect(&ncmMetrics.lfMessageFont);
|
||||||
hwParent = GetParent(m_hwnd);
|
hwParent = GetParent(m_hwnd);
|
||||||
|
|
||||||
hMemDC = NULL;
|
hMemDC = NULL;
|
||||||
hMemBitmap = NULL;
|
hMemBitmap = NULL;
|
||||||
bmx = bmy = 0;
|
bmx = bmy = 0;
|
||||||
|
|
||||||
blackStatus = whiteStatus = NULL;
|
blackStatus = whiteStatus = NULL;
|
||||||
blackText = whiteText = NULL;
|
blackText = whiteText = NULL;
|
||||||
mouseDown = false;
|
mouseDown = false;
|
||||||
lastNote = lastKey = 0;
|
lastNote = lastKey = 0;
|
||||||
|
|
||||||
|
int touchSupport = GetSystemMetrics(SM_DIGITIZER);
|
||||||
|
T_RegisterTouchWindow F_RegisterTouchWindow = NULL;
|
||||||
|
hasTouch = false;
|
||||||
|
|
||||||
|
if (touchSupport & NID_READY) {
|
||||||
|
// Has touch
|
||||||
|
hasTouch = true;
|
||||||
|
|
||||||
|
F_GetTouchInputInfo = (T_GetTouchInputInfo) GetProcAddress(GetModuleHandle(TEXT("user32")), "GetTouchInputInfo");
|
||||||
|
F_CloseTouchInputHandle = (T_CloseTouchInputHandle) GetProcAddress(GetModuleHandle(TEXT("user32")), "CloseTouchInputHandle");
|
||||||
|
F_RegisterTouchWindow = (T_RegisterTouchWindow) GetProcAddress(GetModuleHandle(TEXT("user32")), "RegisterTouchWindow");
|
||||||
|
if (!F_GetTouchInputInfo || !F_CloseTouchInputHandle || !F_RegisterTouchWindow)
|
||||||
|
hasTouch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTouch) {
|
||||||
|
F_RegisterTouchWindow(m_hwnd, TWF_WANTPALM);
|
||||||
|
memset(touchPoint, 0, MAXPOINTS * sizeof(PianoTouchPoint));
|
||||||
|
|
||||||
|
ATOM atom = GlobalAddAtom(MICROSOFT_TABLETPENSERVICE_PROPERTY);
|
||||||
|
SetProp(m_hwnd, MICROSOFT_TABLETPENSERVICE_PROPERTY, (HANDLE) (
|
||||||
|
TABLET_DISABLE_PRESSANDHOLD | // disables press and hold (right-click) gesture
|
||||||
|
TABLET_DISABLE_PENTAPFEEDBACK | // disables UI feedback on pen up (waves)
|
||||||
|
TABLET_DISABLE_PENBARRELFEEDBACK | // disables UI feedback on pen button down
|
||||||
|
TABLET_DISABLE_FLICKS // disables pen flicks (back, forward, drag down, drag up)
|
||||||
|
));
|
||||||
|
GlobalDeleteAtom(atom);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAXPOINTS; ++i)
|
||||||
|
touchPointID[i] = (DWORD) -1;
|
||||||
|
|
||||||
SetOctaves(2);
|
SetOctaves(2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +86,7 @@ void PianoControl::SetOctaves(int octaves)
|
||||||
{
|
{
|
||||||
bool *newBlackStatus, *newWhiteStatus;
|
bool *newBlackStatus, *newWhiteStatus;
|
||||||
LPCWSTR *newBlackText, *newWhiteText;
|
LPCWSTR *newBlackText, *newWhiteText;
|
||||||
|
|
||||||
#define RENEW(type, newname, store) {\
|
#define RENEW(type, newname, store) {\
|
||||||
newname = new type[7 * octaves];\
|
newname = new type[7 * octaves];\
|
||||||
if (store) {\
|
if (store) {\
|
||||||
|
@ -63,7 +100,7 @@ void PianoControl::SetOctaves(int octaves)
|
||||||
RENEW(bool, newWhiteStatus, whiteStatus);
|
RENEW(bool, newWhiteStatus, whiteStatus);
|
||||||
RENEW(LPCWSTR, newBlackText, blackText);
|
RENEW(LPCWSTR, newBlackText, blackText);
|
||||||
RENEW(LPCWSTR, newWhiteText, whiteText);
|
RENEW(LPCWSTR, newWhiteText, whiteText);
|
||||||
|
|
||||||
this->octaves = octaves;
|
this->octaves = octaves;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +117,7 @@ void PianoControl::UpdateKey(int key, bool black)
|
||||||
bwidth = width / 12 / octaves; // smaller
|
bwidth = width / 12 / octaves; // smaller
|
||||||
bheight = height / 2;
|
bheight = height / 2;
|
||||||
hbwidth = bwidth / 2;
|
hbwidth = bwidth / 2;
|
||||||
|
|
||||||
if (black) {
|
if (black) {
|
||||||
client.left += (key * wwidth) - hbwidth + 2;
|
client.left += (key * wwidth) - hbwidth + 2;
|
||||||
client.right = client.left + bwidth - 5;
|
client.right = client.left + bwidth - 5;
|
||||||
|
@ -98,7 +135,7 @@ void PianoControl::SetKeyStatus(int key, bool down)
|
||||||
{
|
{
|
||||||
bool black;
|
bool black;
|
||||||
int id = keyIDToInternal(key, black);
|
int id = keyIDToInternal(key, black);
|
||||||
|
|
||||||
(black ? blackStatus : whiteStatus)[id] = down;
|
(black ? blackStatus : whiteStatus)[id] = down;
|
||||||
UpdateKey(id, black);
|
UpdateKey(id, black);
|
||||||
}
|
}
|
||||||
|
@ -107,7 +144,7 @@ bool PianoControl::GetKeyStatus(int key)
|
||||||
{
|
{
|
||||||
bool black;
|
bool black;
|
||||||
int id = keyIDToInternal(key, black);
|
int id = keyIDToInternal(key, black);
|
||||||
|
|
||||||
return (black ? blackStatus : whiteStatus)[id];
|
return (black ? blackStatus : whiteStatus)[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +152,7 @@ void PianoControl::SetKeyText(int key, LPCWSTR text)
|
||||||
{
|
{
|
||||||
bool black;
|
bool black;
|
||||||
int id = keyIDToInternal(key, black);
|
int id = keyIDToInternal(key, black);
|
||||||
|
|
||||||
(black ? blackText : whiteText)[id] = text;
|
(black ? blackText : whiteText)[id] = text;
|
||||||
UpdateKey(id, black);
|
UpdateKey(id, black);
|
||||||
}
|
}
|
||||||
|
@ -124,7 +161,7 @@ LPCWSTR PianoControl::GetKeyText(int key)
|
||||||
{
|
{
|
||||||
bool black;
|
bool black;
|
||||||
int id = keyIDToInternal(key, black);
|
int id = keyIDToInternal(key, black);
|
||||||
|
|
||||||
return (black ? blackText : whiteText)[id];
|
return (black ? blackText : whiteText)[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +177,7 @@ int PianoControl::keyIDToInternal(int id, bool &black) {
|
||||||
default:
|
default:
|
||||||
black = false;
|
black = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
switch (id % 12) {
|
switch (id % 12) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -170,7 +207,7 @@ int PianoControl::keyIDToInternal(int id, bool &black) {
|
||||||
ret = 6;
|
ret = 6;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return id / 12 * 7 + ret;
|
return id / 12 * 7 + ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +261,7 @@ int PianoControl::hitTest(int x, int y, bool &black)
|
||||||
RECT client;
|
RECT client;
|
||||||
int width, height;
|
int width, height;
|
||||||
int wwidth, bwidth, bheight, hbwidth;
|
int wwidth, bwidth, bheight, hbwidth;
|
||||||
|
|
||||||
GetClientRect(m_hwnd, &client);
|
GetClientRect(m_hwnd, &client);
|
||||||
width = client.right - client.left;
|
width = client.right - client.left;
|
||||||
height = client.bottom - client.top;
|
height = client.bottom - client.top;
|
||||||
|
@ -233,10 +270,10 @@ int PianoControl::hitTest(int x, int y, bool &black)
|
||||||
bheight = height / 2;
|
bheight = height / 2;
|
||||||
bheight = height / 2;
|
bheight = height / 2;
|
||||||
hbwidth = bwidth / 2;
|
hbwidth = bwidth / 2;
|
||||||
|
|
||||||
int key = x / wwidth;
|
int key = x / wwidth;
|
||||||
int dx = x % wwidth;
|
int dx = x % wwidth;
|
||||||
|
|
||||||
if (y < bheight && (dx < hbwidth || dx > (wwidth - hbwidth))) {
|
if (y < bheight && (dx < hbwidth || dx > (wwidth - hbwidth))) {
|
||||||
int temp = key;
|
int temp = key;
|
||||||
if (dx >= hbwidth)
|
if (dx >= hbwidth)
|
||||||
|
@ -251,7 +288,7 @@ int PianoControl::hitTest(int x, int y, bool &black)
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
black = false;
|
black = false;
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
@ -280,10 +317,10 @@ void PianoControl::PaintContent(PAINTSTRUCT *pps)
|
||||||
bheight = height / 2;
|
bheight = height / 2;
|
||||||
bheight = height / 2;
|
bheight = height / 2;
|
||||||
hbwidth = bwidth / 2;
|
hbwidth = bwidth / 2;
|
||||||
|
|
||||||
hbOriginal = SelectBrush(hdc, hBackground);
|
hbOriginal = SelectBrush(hdc, hBackground);
|
||||||
hPenOriginal = SelectPen(hdc, hPenDC);
|
hPenOriginal = SelectPen(hdc, hPenDC);
|
||||||
|
|
||||||
GetObject(hFont, sizeof(LOGFONT), &lf);
|
GetObject(hFont, sizeof(LOGFONT), &lf);
|
||||||
lf.lfWidth = 0;
|
lf.lfWidth = 0;
|
||||||
lf.lfHeight = min(bwidth, bheight / 4);
|
lf.lfHeight = min(bwidth, bheight / 4);
|
||||||
|
@ -333,18 +370,18 @@ void PianoControl::PaintContent(PAINTSTRUCT *pps)
|
||||||
#define GETBORDER0(down) (down ? GetSysColor(COLOR_3DLIGHT) : RGB(0, 0, 0))
|
#define GETBORDER0(down) (down ? GetSysColor(COLOR_3DLIGHT) : RGB(0, 0, 0))
|
||||||
#define GETBORDER1(down) (down ? GetSysColor(COLOR_3DSHADOW) : GetSysColor(COLOR_3DDKSHADOW))
|
#define GETBORDER1(down) (down ? GetSysColor(COLOR_3DSHADOW) : GetSysColor(COLOR_3DDKSHADOW))
|
||||||
#define GETBORDER2(down) (down ? GetSysColor(COLOR_3DDKSHADOW) : GetSysColor(COLOR_3DSHADOW))
|
#define GETBORDER2(down) (down ? GetSysColor(COLOR_3DDKSHADOW) : GetSysColor(COLOR_3DSHADOW))
|
||||||
|
|
||||||
rect.top = height - CURVE_SIZE, rect.bottom = height;
|
rect.top = height - CURVE_SIZE, rect.bottom = height;
|
||||||
rect.left = client.left, rect.right = client.right;
|
rect.left = client.left, rect.right = client.right;
|
||||||
FillRect(hdc, &rect, hBackground);
|
FillRect(hdc, &rect, hBackground);
|
||||||
|
|
||||||
rect.top = client.top, rect.bottom = client.bottom;
|
rect.top = client.top, rect.bottom = client.bottom;
|
||||||
rect.left = client.right - width % (7 * octaves), rect.right = client.right;
|
rect.left = client.right - width % (7 * octaves), rect.right = client.right;
|
||||||
FillRect(hdc, &rect, hBackground);
|
FillRect(hdc, &rect, hBackground);
|
||||||
for (int i = 0; i < 7 * octaves; ++i) {
|
for (int i = 0; i < 7 * octaves; ++i) {
|
||||||
int sx = i * wwidth, ex = i * wwidth + wwidth - 1;
|
int sx = i * wwidth, ex = i * wwidth + wwidth - 1;
|
||||||
bool down = whiteStatus[i];
|
bool down = whiteStatus[i];
|
||||||
|
|
||||||
SelectBrush(hdc, hbDC);
|
SelectBrush(hdc, hbDC);
|
||||||
SetDCBrushColor(hdc, GETBORDER1(down));
|
SetDCBrushColor(hdc, GETBORDER1(down));
|
||||||
DRAWBOX(bheight, 0, height, GETBORDER0(down));
|
DRAWBOX(bheight, 0, height, GETBORDER0(down));
|
||||||
|
@ -352,10 +389,10 @@ void PianoControl::PaintContent(PAINTSTRUCT *pps)
|
||||||
DRAWBOX(bheight, 1, height, GETBORDER1(down));
|
DRAWBOX(bheight, 1, height, GETBORDER1(down));
|
||||||
SelectBrush(hdc, hbFace);
|
SelectBrush(hdc, hbFace);
|
||||||
DRAWBOX(bheight, 2, height, GETBORDER2(down));
|
DRAWBOX(bheight, 2, height, GETBORDER2(down));
|
||||||
|
|
||||||
rect.top = 0, rect.bottom = bheight, rect.left = sx, rect.right = ex;
|
rect.top = 0, rect.bottom = bheight, rect.left = sx, rect.right = ex;
|
||||||
FillRect(hdc, &rect, hBackground);
|
FillRect(hdc, &rect, hBackground);
|
||||||
|
|
||||||
switch (haveBlack(i)) {
|
switch (haveBlack(i)) {
|
||||||
case 0: // none
|
case 0: // none
|
||||||
DRAWBORDER(bheight, 0, GETBORDER0(down));
|
DRAWBORDER(bheight, 0, GETBORDER0(down));
|
||||||
|
@ -405,7 +442,7 @@ void PianoControl::PaintContent(PAINTSTRUCT *pps)
|
||||||
FillRect(hdc, &rect, hbFace);
|
FillRect(hdc, &rect, hbFace);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (whiteText[i]) {
|
if (whiteText[i]) {
|
||||||
INITIALIZE_PAINT_TEXT(whiteText);
|
INITIALIZE_PAINT_TEXT(whiteText);
|
||||||
rect.top = bheight + bheight / 7, rect.bottom = height - bheight / 7;
|
rect.top = bheight + bheight / 7, rect.bottom = height - bheight / 7;
|
||||||
|
@ -413,7 +450,7 @@ void PianoControl::PaintContent(PAINTSTRUCT *pps)
|
||||||
SetTextColor(hdc, RGB(0, 0, 0));
|
SetTextColor(hdc, RGB(0, 0, 0));
|
||||||
DrawText(hdc, szBuffer, -1, &rect, DT_CENTER);
|
DrawText(hdc, szBuffer, -1, &rect, DT_CENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
rect.top = client.top, rect.bottom = client.bottom;
|
rect.top = client.top, rect.bottom = client.bottom;
|
||||||
rect.left = ex, rect.right = ex + 1;
|
rect.left = ex, rect.right = ex + 1;
|
||||||
FillRect(hdc, &rect, hBackground);
|
FillRect(hdc, &rect, hBackground);
|
||||||
|
@ -431,7 +468,7 @@ void PianoControl::PaintContent(PAINTSTRUCT *pps)
|
||||||
SetDCBrushColor(hdc, colour);
|
SetDCBrushColor(hdc, colour);
|
||||||
DRAWBOX(-CURVE_SIZE, j, bheight - 2, colour);
|
DRAWBOX(-CURVE_SIZE, j, bheight - 2, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blackText[i]) {
|
if (blackText[i]) {
|
||||||
INITIALIZE_PAINT_TEXT(blackText);
|
INITIALIZE_PAINT_TEXT(blackText);
|
||||||
rect.top = bheight / 7, rect.bottom = bheight - bheight / 7;
|
rect.top = bheight / 7, rect.bottom = bheight - bheight / 7;
|
||||||
|
@ -462,13 +499,13 @@ void PianoControl::OnPaint()
|
||||||
{
|
{
|
||||||
PAINTSTRUCT ps;
|
PAINTSTRUCT ps;
|
||||||
BeginPaint(m_hwnd, &ps);
|
BeginPaint(m_hwnd, &ps);
|
||||||
|
|
||||||
int x = ps.rcPaint.left;
|
int x = ps.rcPaint.left;
|
||||||
int y = ps.rcPaint.top;
|
int y = ps.rcPaint.top;
|
||||||
int cx = ps.rcPaint.right - ps.rcPaint.left;
|
int cx = ps.rcPaint.right - ps.rcPaint.left;
|
||||||
int cy = ps.rcPaint.bottom - ps.rcPaint.top;
|
int cy = ps.rcPaint.bottom - ps.rcPaint.top;
|
||||||
HDC hdc = ps.hdc;
|
HDC hdc = ps.hdc;
|
||||||
|
|
||||||
if (!hMemDC)
|
if (!hMemDC)
|
||||||
hMemDC = CreateCompatibleDC(hdc);
|
hMemDC = CreateCompatibleDC(hdc);
|
||||||
if (!hMemBitmap || cx > bmx || cy > bmy) {
|
if (!hMemBitmap || cx > bmx || cy > bmy) {
|
||||||
|
@ -481,7 +518,7 @@ void PianoControl::OnPaint()
|
||||||
}
|
}
|
||||||
if (hMemDC && hMemBitmap) {
|
if (hMemDC && hMemBitmap) {
|
||||||
ps.hdc = hMemDC;
|
ps.hdc = hMemDC;
|
||||||
|
|
||||||
HBITMAP hbmPrev = SelectBitmap(hMemDC, hMemBitmap);
|
HBITMAP hbmPrev = SelectBitmap(hMemDC, hMemBitmap);
|
||||||
SetWindowOrgEx(hMemDC, x, y, NULL);
|
SetWindowOrgEx(hMemDC, x, y, NULL);
|
||||||
|
|
||||||
|
@ -495,15 +532,72 @@ void PianoControl::OnPaint()
|
||||||
EndPaint(m_hwnd, &ps);
|
EndPaint(m_hwnd, &ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PianoControl::DisableDraw() {
|
void PianoControl::DisableDraw()
|
||||||
|
{
|
||||||
SendMessage(m_hwnd, WM_SETREDRAW, FALSE, 0);
|
SendMessage(m_hwnd, WM_SETREDRAW, FALSE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PianoControl::EnableDraw() {
|
void PianoControl::EnableDraw()
|
||||||
|
{
|
||||||
SendMessage(m_hwnd, WM_SETREDRAW, TRUE, 0);
|
SendMessage(m_hwnd, WM_SETREDRAW, TRUE, 0);
|
||||||
RedrawWindow(m_hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
|
RedrawWindow(m_hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PianoControl::OnTouchPoint(UINT id, int x, int y)
|
||||||
|
{
|
||||||
|
if (x != -1 && y != -1) {
|
||||||
|
// Touch point is down
|
||||||
|
if (touchPoint[id].down) {
|
||||||
|
// Dragged
|
||||||
|
bool black;
|
||||||
|
int internal = hitTest(x, y, black);
|
||||||
|
int key = internalToKeyID(internal, black);
|
||||||
|
int external = SendMessage(hwParent, MMWM_NOTEID, key, 0);
|
||||||
|
if (touchPoint[id].lastNote != external) {
|
||||||
|
SendMessage(hwParent, MMWM_TURNNOTE, touchPoint[id].lastNote, 0);
|
||||||
|
SetKeyStatus(touchPoint[id].lastKey, false);
|
||||||
|
SendMessage(hwParent, MMWM_TURNNOTE, external, 1);
|
||||||
|
SetKeyStatus(key, true);
|
||||||
|
touchPoint[id].lastNote = external;
|
||||||
|
touchPoint[id].lastKey = key;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Pressed
|
||||||
|
bool black;
|
||||||
|
int internal = hitTest(x, y, black);
|
||||||
|
int key = internalToKeyID(internal, black);
|
||||||
|
int external = SendMessage(hwParent, MMWM_NOTEID, key, 0);
|
||||||
|
SendMessage(hwParent, MMWM_TURNNOTE, external, 1);
|
||||||
|
SetKeyStatus(key, true);
|
||||||
|
touchPoint[id].lastNote = external;
|
||||||
|
touchPoint[id].lastKey = key;
|
||||||
|
touchPoint[id].down = true;
|
||||||
|
}
|
||||||
|
touchPoint[id].point.x = x;
|
||||||
|
touchPoint[id].point.y = y;
|
||||||
|
} else {
|
||||||
|
// It just went up
|
||||||
|
SendMessage(hwParent, MMWM_TURNNOTE, touchPoint[id].lastNote, 0);
|
||||||
|
SetKeyStatus(touchPoint[id].lastKey, false);
|
||||||
|
touchPoint[id].down = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int PianoControl::GetTouchPointID(DWORD dwID)
|
||||||
|
{
|
||||||
|
for (DWORD i = 0; i < MAXPOINTS; ++i) {
|
||||||
|
if (touchPointID[i] == dwID)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
for (DWORD i = 0; i < MAXPOINTS; ++i) {
|
||||||
|
if (touchPointID[i] == (DWORD) -1) {
|
||||||
|
touchPointID[i] = dwID;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
LRESULT PianoControl::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
LRESULT PianoControl::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
switch (uMsg) {
|
switch (uMsg) {
|
||||||
|
@ -520,27 +614,29 @@ LRESULT PianoControl::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
case WM_SIZE:
|
case WM_SIZE:
|
||||||
InvalidateRect(m_hwnd, NULL, TRUE);
|
InvalidateRect(m_hwnd, NULL, TRUE);
|
||||||
return 0;
|
return 0;
|
||||||
case WM_LBUTTONDOWN: {
|
case WM_LBUTTONDOWN:
|
||||||
bool black;
|
if ((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) != MOUSEEVENTF_FROMTOUCH) {
|
||||||
int internal = hitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), black);
|
bool black;
|
||||||
int key = internalToKeyID(internal, black);
|
int internal = hitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), black);
|
||||||
int external = SendMessage(hwParent, MMWM_NOTEID, key, 0);
|
int key = internalToKeyID(internal, black);
|
||||||
SendMessage(hwParent, MMWM_TURNNOTE, external, 1);
|
int external = SendMessage(hwParent, MMWM_NOTEID, key, 0);
|
||||||
SetKeyStatus(key, true);
|
SendMessage(hwParent, MMWM_TURNNOTE, external, 1);
|
||||||
lastNote = external;
|
SetKeyStatus(key, true);
|
||||||
lastKey = key;
|
lastNote = external;
|
||||||
mouseDown = true;
|
lastKey = key;
|
||||||
SetFocus(m_hwnd);
|
mouseDown = true;
|
||||||
return 0;
|
SetFocus(m_hwnd);
|
||||||
}
|
return 0;
|
||||||
case WM_LBUTTONUP: {
|
}
|
||||||
SendMessage(hwParent, MMWM_TURNNOTE, lastNote, 0);
|
case WM_LBUTTONUP:
|
||||||
SetKeyStatus(lastKey, false);
|
if ((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) != MOUSEEVENTF_FROMTOUCH) {
|
||||||
mouseDown = false;
|
SendMessage(hwParent, MMWM_TURNNOTE, lastNote, 0);
|
||||||
return 0;
|
SetKeyStatus(lastKey, false);
|
||||||
}
|
mouseDown = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
case WM_MOUSEMOVE:
|
case WM_MOUSEMOVE:
|
||||||
if (mouseDown) {
|
if ((GetMessageExtraInfo() & 0x82) != 0x82 && mouseDown) {
|
||||||
bool black;
|
bool black;
|
||||||
int internal = hitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), black);
|
int internal = hitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), black);
|
||||||
int key = internalToKeyID(internal, black);
|
int key = internalToKeyID(internal, black);
|
||||||
|
@ -564,6 +660,39 @@ LRESULT PianoControl::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
case WM_SYSCHAR:
|
case WM_SYSCHAR:
|
||||||
case WM_SYSDEADCHAR:
|
case WM_SYSDEADCHAR:
|
||||||
return SendMessage(hwParent, uMsg, wParam, lParam);
|
return SendMessage(hwParent, uMsg, wParam, lParam);
|
||||||
|
case WM_TOUCH: {
|
||||||
|
if (!hasTouch)
|
||||||
|
break;
|
||||||
|
|
||||||
|
UINT cInputs = LOWORD(wParam);
|
||||||
|
TOUCHINPUT *pInputs = new TOUCHINPUT[cInputs];
|
||||||
|
if (pInputs != NULL) {
|
||||||
|
if (F_GetTouchInputInfo((HTOUCHINPUT) lParam, cInputs, pInputs, sizeof(TOUCHINPUT))) {
|
||||||
|
for (UINT i = 0; i < cInputs; ++i) {
|
||||||
|
POINT ptInput;
|
||||||
|
int id = GetTouchPointID(pInputs[i].dwID);
|
||||||
|
if (id == -1)
|
||||||
|
continue; // presumably you had 20 touch points
|
||||||
|
|
||||||
|
ptInput.x = TOUCH_COORD_TO_PIXEL(pInputs[i].x);
|
||||||
|
ptInput.y = TOUCH_COORD_TO_PIXEL(pInputs[i].y);
|
||||||
|
ScreenToClient(m_hwnd, &ptInput);
|
||||||
|
|
||||||
|
if (pInputs[i].dwFlags & TOUCHEVENTF_UP) {
|
||||||
|
OnTouchPoint(id, -1, -1);
|
||||||
|
touchPointID[id] = (DWORD) -1; // Free the ID
|
||||||
|
} else {
|
||||||
|
OnTouchPoint(id, ptInput.x, ptInput.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
F_CloseTouchInputHandle((HTOUCHINPUT) lParam);
|
||||||
|
delete [] pInputs;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
delete [] pInputs;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case WM_GETFONT:
|
case WM_GETFONT:
|
||||||
return (LRESULT) GetFont();
|
return (LRESULT) GetFont();
|
||||||
case WM_SETFONT:
|
case WM_SETFONT:
|
||||||
|
|
Loading…
Reference in a new issue