// KeyPad.cpp : Defines the entry point for the keypad application.
//
#include "stdafx.h"
#include "stdio.h"
// Place a 10 key numeric pad on the cPad.
// Set up some per instance globals.
class Globals
{
public:
static HINSTANCE GetInstance() { return m_hInstance; }
static void SetInstance(HINSTANCE hInstance) { m_hInstance = hInstance; }
static HINSTANCE m_hInstance;
};
HINSTANCE Globals::m_hInstance;
// Maintain a button on the cPad.
class CPadButton
{
public:
CPadButton()
{
m_iX = m_iY = m_iH = m_iW = m_iBitmap = 0;
}
void Init(int iX, int iY, int iH, int iW, int iBitmap)
{
m_iX = iX;
m_iY = iY;
m_iH = iH;
m_iW = iW;
m_iBitmap = iBitmap;
}
void Draw(HDC hDC)
{
HBITMAP hMap = LoadBitmap(Globals::GetInstance(), MAKEINTRESOURCE(m_iBitmap));
HDC m_hMapDC = CreateCompatibleDC(hDC);
SelectObject(m_hMapDC, hMap);
BitBlt(hDC, m_iX, m_iY, m_iW, m_iH, m_hMapDC, 0, 0, SRCCOPY);
DeleteDC(m_hMapDC);
DeleteObject(hMap);
}
bool HitTest(long lX, long lY)
{
if (lX >= m_iX && lX = m_iY && lY return true;
else
return false;
}
virtual bool OnTap() {return true; }
private:
int m_iX;
int m_iY;
int m_iH;
int m_iW;
int m_iBitmap;
};
// Derive from CPadButton and add tenkey functionality.
class TenKeyButton : public CPadButton
{
public:
TenKeyButton() { m_cCharacter = 0;}
void Init(int iX, int iY, int iH, int iW, int iBitmap, char cChar)
{
m_cCharacter = cChar;
CPadButton::Init(iX, iY, iH, iW, iBitmap);
}
bool OnTap()
{
if (!m_cCharacter)
return false;
sendKeyPress(m_cCharacter);
return true;
}
private:
void sendKeyPress(char ch)
{
HWND topw = GetForegroundWindow();
if (topw == 0) return; // Don't know where to send input.
if (ch > 0) {
INPUT kbi;
kbi.type = INPUT_KEYBOARD;
kbi.ki.wVk = ch;
kbi.ki.dwFlags = 0;
SendInput(1, &kbi, sizeof(kbi));
kbi.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &kbi, sizeof(kbi));
}
}
char m_cCharacter;
};
class CKeyPad :
// Derive from Synaptics device and display events.
public _ISynDeviceEvents,
public _ISynDisplayEvents
{
public:
CKeyPad()
{
m_lLastX = m_lLastY = 0;
m_bTapSequence = false;
}
void InitButtons()
{
m_ButtonZero.Init(4, 124, 32, 88, IDB_BITMAP0, '0');
m_ButtonOne.Init(4, 84, 32, 40, IDB_BITMAP1, '1');
m_ButtonTwo.Init(52, 84, 32, 40, IDB_BITMAP2, '2');
m_ButtonThree.Init(100, 84, 32, 40, IDB_BITMAP3, '3');
m_ButtonFour.Init(4, 44, 32, 40, IDB_BITMAP4, '4');
m_ButtonFive.Init(52, 44, 32, 40, IDB_BITMAP5, '5');
m_ButtonSix.Init(100, 44, 32, 40, IDB_BITMAP6, '6');
m_ButtonSeven.Init(4, 4, 32, 40, IDB_BITMAP7, '7');
m_ButtonEight.Init(52, 4, 32, 40, IDB_BITMAP8, '8');
m_ButtonNine.Init(100, 4, 32, 40, IDB_BITMAP9, '9');
m_ButtonMult.Init(196, 44, 32, 40, IDB_BITMAPMULT, '*' + 0x40);
m_ButtonDiv.Init(148, 44, 32, 40, IDB_BITMAPDIV, '/' + 0x40);
m_ButtonDot.Init(100, 124, 32, 40, IDB_BITMAPDOT, '.' + 0x40);
m_ButtonPlus.Init(196, 84, 32, 40, IDB_BITMAPPLUS, '+' + 0x40);
m_ButtonMinus.Init(148, 84, 32, 40, IDB_BITMAPMINUS, '-' + 0x40);
m_ButtonEnter.Init(148, 124, 32, 88, IDB_BITMAPENTER, 0x0D);
m_ButtonExit.Init(204, 0, 32, 40, IDB_BITMAPEXIT, 0);
}
bool OnCreate(HWND hWnd)
{
m_hWnd = hWnd;
long lHandle = -1;
// Set the taskbar icon
HICON hSmallIcon = (HICON) LoadImage (Globals::GetInstance(),
MAKEINTRESOURCE (IDI_KEYPAD), IMAGE_ICON,
GetSystemMetrics (SM_CXSMICON), GetSystemMetrics (SM_CYSMICON),
LR_DEFAULTCOLOR);
SendMessage (hWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM) hSmallIcon);
DeleteObject(hSmallIcon);
CoInitialize(0); // Don't care if it fails.
if (CoCreateInstance(_uuidof(SynAPI), 0,
CLSCTX_INPROC_SERVER, _uuidof(ISynAPI), (void **) &m_pAPI) ||
m_pAPI->Initialize() ||
m_pAPI->FindDevice(SE_ConnectionAny, SE_DevicecPad, &lHandle) ||
m_pAPI->CreateDevice(lHandle, &m_pDevice) ||
m_pDevice->CreateDisplay(&m_pDisplay) ||
m_pDisplay->Acquire(SE_AcquireCooperative))
{
return false; // Couldn't initialize properly.
}
// Setup to receive device packets.
m_pDevice->SetSynchronousNotification(this);
// Setup to receive display acquisition notifications.
m_pDisplay->SetSynchronousNotification(this);
m_pDisplay->GetDC(&m_hdc);
InitButtons();
DrawPad();
m_pDevice->Acquire(0);
m_pDisplay->SetProperty(SP_BackLightState, 1);
return true;
}
void DrawButtons()
{
for (TenKeyButton *pButton = &m_ButtonZero; pButton pButton++)
{
pButton->Draw(m_hdc);
}
}
void ClearDisplay()
{
RECT rect;
// Clear the display dc.
rect.top = 0; rect.bottom = 160; rect.left = 0; rect.right = 240;
FillRect(m_hdc, &rect, (HBRUSH) GetStockObject(WHITE_BRUSH));
}
void DrawPad()
{
ClearDisplay();
DrawButtons();
m_pDisplay->FlushDC(SE_FlushSynchronous);
}
// Examine device packets and if a tap occurs in the exit icon in the
// upper right hand corner, exit.
long STDMETHODCALLTYPE OnSynDevicePacket(long lSeq)
{
m_pDevice->LoadPacket(m_Packet);
long lState = m_Packet.GetLongProperty(SP_FingerState);
if (lState & SF_FingerPresent)
{
// Store last finger down position.
m_lLastX = m_Packet.GetLongProperty(SP_X);
m_lLastY = m_Packet.GetLongProperty(SP_Y);
}
if (lState & SF_FingerTap)
{
if (!m_bTapSequence)
{
// A tap has occured, now examine the last finger present position
// to see if the tap occured in the exit icon.
long lPixelX, lPixelY;
m_pDisplay->TouchToPixel(m_lLastX, m_lLastY, &lPixelX, &lPixelY);
for (TenKeyButton *pButton = &m_ButtonZero; pButton pButton++)
{
if (pButton->HitTest(lPixelX, lPixelY))
if (!pButton->OnTap()) {
// If we are closing the application, clear the display.
ClearDisplay();
m_pDisplay->FlushDC(SE_FlushSynchronous);
DestroyWindow(m_hWnd);
}
}
}
m_bTapSequence = true; // Don't process contiguous tap indicators.
}
else
m_bTapSequence = false; // Start processing taps again.
return 0;
}
long STDMETHODCALLTYPE OnSynDisplayMessage(long lMessage)
{
switch(lMessage)
{
case SE_AcquisitionLost:
// The display is now controlled elsewhere, turn off finger data.
m_pDevice->SetSynchronousNotification(0);
m_pDevice->Unacquire();
break;
case SE_AcquisitionGained:
// The display is back, now look at finger data to potentially decide
// to exit.
m_pDevice->Acquire(0);
m_pDevice->SetSynchronousNotification(this);
DrawPad();
break;
default:
break;
}
return 0;
}
HWND m_hWnd;
ISynAPI *m_pAPI;
ISynDevice *m_pDevice;
ISynDisplay *m_pDisplay;
SynPacket m_Packet;
HDC m_hdc;
long m_lLastX;
long m_lLastY;
bool m_bTapSequence;
TenKeyButton m_ButtonZero;
TenKeyButton m_ButtonOne;
TenKeyButton m_ButtonTwo;
TenKeyButton m_ButtonThree;
TenKeyButton m_ButtonFour;
TenKeyButton m_ButtonFive;
TenKeyButton m_ButtonSix;
TenKeyButton m_ButtonSeven;
TenKeyButton m_ButtonEight;
TenKeyButton m_ButtonNine;
TenKeyButton m_ButtonMult;
TenKeyButton m_ButtonDiv;
TenKeyButton m_ButtonDot;
TenKeyButton m_ButtonPlus;
TenKeyButton m_ButtonMinus;
TenKeyButton m_ButtonEnter;
TenKeyButton m_ButtonExit;
};
// Standard window procedure.
LRESULT APIENTRY WndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
// Get the keypad object that was saved when the window was created.
CKeyPad *pThis = (CKeyPad *) GetWindowLong(hwnd, GWL_USERDATA);
switch (uMsg) {
case WM_CREATE:
{
// Save away the keypad object passed to CreateWindow.
CREATESTRUCT *pCreate = (CREATESTRUCT *) lParam;
SetWindowLong(hwnd, GWL_USERDATA,
(long) pCreate->lpCreateParams);
pThis = (CKeyPad *) pCreate->lpCreateParams;
}
// If keypad initialization fails, exit.
if (!pThis->OnCreate(hwnd))
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
// Application entry point.
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
Globals::SetInstance(hInstance);
// Create the keypad object.
CKeyPad KeyPad;
// Register the window class.
WNDCLASS WC;
WC.style = 0;
WC.lpfnWndProc = WndProc;
WC.cbClsExtra = 0;
WC.cbWndExtra = 0;
WC.hInstance = hInstance;
WC.hIcon = 0;
WC.hCursor = 0;
WC.hbrBackground = 0;
WC.lpszMenuName = NULL;
WC.lpszClassName = "KeyPadClass";
RegisterClass (&WC);
// Create the app window. It must be visible to get a taskbar button.
// It must have a system menu to get a taskbar button icon.
// Position it off the screen so that it won't be seen.
HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW, "KeyPadClass",
"KeyPad", WS_VISIBLE | WS_SYSMENU,
-1000, -1000, 0, 0, 0, 0, hInstance, &KeyPad);
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
DispatchMessage(&msg);
}
return 0;
}