Working touch support.

This commit is contained in:
Quantum 2016-02-14 16:26:49 -05:00
parent 0f297cfae3
commit c8a835e83f
3 changed files with 211 additions and 61 deletions

View file

@ -3,7 +3,7 @@ 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
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
RC=rc /nologo
RCFLAGS=/i$(INCDIR)

View file

@ -8,6 +8,10 @@
#include <commctrl.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_SETKEYSTATUS (WM_USER + 1)
#define MPCM_GETOCTAVES (WM_USER + 2)
@ -19,6 +23,15 @@
#define MMWM_TURNNOTE (WM_APP + 0)
#define MMWM_NOTEID (WM_APP + 1)
#define MAXPOINTS 20
typedef struct {
bool down;
POINTL point;
int lastNote;
int lastKey;
} PianoTouchPoint;
class PianoControl : public Window {
public:
virtual LPCTSTR ClassName() { return TEXT("KeyboardControl"); }
@ -52,6 +65,14 @@ protected:
virtual void PaintContent(PAINTSTRUCT *pps);
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 internalToKeyID(int id, bool black);
virtual bool haveBlackToLeft(int id);

View file

@ -4,11 +4,16 @@
#include <windowsx.h>
#include <stdio.h>
#include <tchar.h>
#include <tpcshrd.h>
#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
#define MOUSEEVENTF_FROMTOUCH 0xFF515700
BOOL PianoControl::WinRegisterClass(WNDCLASS *pwc)
{
return Window::WinRegisterClass(pwc);
@ -34,6 +39,38 @@ LRESULT PianoControl::OnCreate()
mouseDown = false;
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);
return 0;
}
@ -495,15 +532,72 @@ void PianoControl::OnPaint()
EndPaint(m_hwnd, &ps);
}
void PianoControl::DisableDraw() {
void PianoControl::DisableDraw()
{
SendMessage(m_hwnd, WM_SETREDRAW, FALSE, 0);
}
void PianoControl::EnableDraw() {
void PianoControl::EnableDraw()
{
SendMessage(m_hwnd, WM_SETREDRAW, TRUE, 0);
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)
{
switch (uMsg) {
@ -520,7 +614,8 @@ LRESULT PianoControl::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_SIZE:
InvalidateRect(m_hwnd, NULL, TRUE);
return 0;
case WM_LBUTTONDOWN: {
case WM_LBUTTONDOWN:
if ((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) != MOUSEEVENTF_FROMTOUCH) {
bool black;
int internal = hitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), black);
int key = internalToKeyID(internal, black);
@ -533,14 +628,15 @@ LRESULT PianoControl::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
SetFocus(m_hwnd);
return 0;
}
case WM_LBUTTONUP: {
case WM_LBUTTONUP:
if ((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) != MOUSEEVENTF_FROMTOUCH) {
SendMessage(hwParent, MMWM_TURNNOTE, lastNote, 0);
SetKeyStatus(lastKey, false);
mouseDown = false;
return 0;
}
case WM_MOUSEMOVE:
if (mouseDown) {
if ((GetMessageExtraInfo() & 0x82) != 0x82 && mouseDown) {
bool black;
int internal = hitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), black);
int key = internalToKeyID(internal, black);
@ -564,6 +660,39 @@ LRESULT PianoControl::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_SYSCHAR:
case WM_SYSDEADCHAR:
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:
return (LRESULT) GetFont();
case WM_SETFONT: