Windows/MFC
Virtual Key board
aucd29
2013. 10. 2. 18:23
http://lionroast.tistory.com/tag/%EA%B0%80%EC%83%81%20%ED%82%A4%EB%B3%B4%EB%93%9C
[code]
// CVirtualKeyboardDlg.cpp : implementation file
//
#include "stdafx.h"
#include "VirtualKeyboardDlg.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define WM_ICON_NOTIFY WM_USER + 10
#define TIMER_ID 101
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
/////////////////////////////////////////////////////////////////////////////
// CVirtualKeyboardDlg dialog
CVirtualKeyboardDlg::CVirtualKeyboardDlg(CWnd* pParent /*=NULL*/)
: CDialog(CVirtualKeyboardDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CVirtualKeyboardDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CVirtualKeyboardDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CVirtualKeyboardDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CVirtualKeyboardDlg, CDialog)
//{{AFX_MSG_MAP(CVirtualKeyboardDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_RBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_MOUSEWHEEL()
ON_WM_LBUTTONUP()
ON_WM_SIZE()
// ON_COMMAND(IDM_SHOW_KEYBOARD, OnShowKeyboard)
// ON_UPDATE_COMMAND_UI(IDM_SHOW_KEYBOARD, OnUpdateShowKeyboard)
// ON_COMMAND(IDM_HIDE_KEYBOARD, OnHideKeyboard)
// ON_UPDATE_COMMAND_UI(IDM_HIDE_KEYBOARD, OnUpdateHideKeyboard)
// ON_COMMAND(IDM_EXIT, OnExit)
ON_WM_SHOWWINDOW()
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CVirtualKeyboardDlg message handlers
#define TAB 0x02
#define CAPSLOCK 0x03
#define SHIFT 0x04
#define CTRL 0x05
#define BSPACE 0x06
#define ENTER 0x07
#define ALT 0x08
#define WINDOW 0x9
#define LEFT 0x0A
#define RIGHT 0x0B
#define UP 0x0C
#define DOWN 0x0D
#define ESC 0x0E
#define PUP 0x0F
#define PDN 0x10
#define HOME 0x11
#define END 0x12
#define INS 0x13
#define DEL 0x14
#define WWW 0x15
BOOL CVirtualKeyboardDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
//build the keyboard definition
//control row
AddKey(0x00,0x00,0); //signal row change
AddKey(0x00,ESC,10);
for(int fnkey = 0x70; fnkey < 0x7C; fnkey++)
{
AddKey(0x00,fnkey & 0xFF,10);
}
AddKey(0x00,INS,14);
AddKey(0x00,DEL,-10);
//first row
AddKey(0x00,0x00,1); //signal row change
AddKey('`','~',10);
AddKey('1','!',10);
AddKey('2','@',10);
AddKey('3','#',10);
AddKey('4','$',10);
AddKey('5','%',10);
AddKey('6','^',10);
AddKey('7','&',10);
AddKey('8','*',10);
AddKey('9','(',10);
AddKey('0',')',10);
AddKey('-','_',10);
AddKey('=','+',10);
AddKey(0x00,BSPACE,14); //backspace
AddKey(0x00,PUP,-12);
//second row
AddKey(0x00,0x00,2); //signal row change
AddKey(0x00,TAB,14); //tab
AddKey('q','Q',10);
AddKey('w','W',10);
AddKey('e','E',10);
AddKey('r','R',10);
AddKey('t','T',10);
AddKey('y','Y',10);
AddKey('u','U',10);
AddKey('i','I',10);
AddKey('o','O',10);
AddKey('p','P',10);
AddKey('[','{',10);
AddKey(']','}',10);
AddKey('\\','|',10);
AddKey(0x00,PDN,-12);
//third row
AddKey(0x00,0x00,3); //signal row change
AddKey(0x00,CAPSLOCK,18); //caps lock
AddKey('a','A',10);
AddKey('s','S',10);
AddKey('d','D',10);
AddKey('f','F',10);
AddKey('g','G',10);
AddKey('h','H',10);
AddKey('j','J',10);
AddKey('k','K',10);
AddKey('l','L',10);
AddKey(';',':',10);
AddKey('\'','\"',10);
AddKey(0x00,ENTER,16); //enter
AddKey(0x00,HOME,-10);
//fourth row
AddKey(0x00,0x00,4); //signal row change
AddKey(0x00,SHIFT,22); //shift
AddKey('z','Z',10);
AddKey('x','X',10);
AddKey('c','C',10);
AddKey('v','V',10);
AddKey('b','B',10);
AddKey('n','N',10);
AddKey('m','M',10);
AddKey(',','<',10);
AddKey('.','>',10);
AddKey('/','?',10);
AddKey(0x00,SHIFT,22); //shift
AddKey(0x00,END,-10);
//fifth row
AddKey(0x00,0x00,5); //signal row change
AddKey(0x00,CTRL,12); //ctrl
AddKey(0x00,WINDOW,12); //window
AddKey(0x00,ALT,12); //alt
AddKey(' ',' ',60);
AddKey(0x00,LEFT,12); //left
AddKey(0x00,UP,12); //up
AddKey(0x00,DOWN,12); //down
AddKey(0x00,RIGHT,12); //right
//AddKey(0x00,WWW,-10); //http://WWW
CalcWidthHeight();
//put an icon for us in the system tray
//add us the the system tray
// SetTimer(TIMER_ID,250,NULL);
return TRUE; // return TRUE unless you set the focus to a control
}
void CVirtualKeyboardDlg::CalcWidthHeight()
{
pKeyWidth = 0;
pKeyHeight = 0;
KEYDEF * key;
POSITION pos = cKeys.GetHeadPosition();
long totalWidth = 0;
long longest = 0;
long rows = 0;
while(pos)
{
key = cKeys.GetNext(pos);
if((key->cNormal == 0x00) && (key->cShifted == 0x00))
{
rows++;
if(totalWidth > longest)
{
longest = totalWidth;
}
totalWidth = 0;
}
else
{
totalWidth += abs(key->cWidth);
}
}
CRect rect;
GetClientRect(rect);
pKeyHeight = rect.Height() / rows;
pKeyWidth = (int)(((double)rect.Width()) / ((((double)(longest)) / 10)));
}
void CVirtualKeyboardDlg::AddKey(
char pNormal,
char pShifted,
int pWidth)
{
KEYDEF * key = new KEYDEF;
key->cNormal = pNormal;
key->cShifted = pShifted;
key->cWidth = pWidth;
cKeys.AddTail(key);
}
void CVirtualKeyboardDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
CDialog::OnSysCommand(nID, lParam);
}
void CVirtualKeyboardDlg::DrawKey(CDC * dc, CRect & rc, KEYDEF * key, BOOL cHilight)
{
if(!cHilight)
{
rc.DeflateRect(1,1);
dc->FillSolidRect(rc,GetSysColor(COLOR_3DFACE));
dc->Draw3dRect(rc,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DDKSHADOW));
rc.DeflateRect(1,1);
dc->Draw3dRect(rc,GetSysColor(COLOR_3DLIGHT),GetSysColor(COLOR_3DSHADOW));
}
else
{
rc.DeflateRect(1,1);
dc->FillSolidRect(rc,GetSysColor(COLOR_3DLIGHT));
dc->Draw3dRect(rc,GetSysColor(COLOR_3DLIGHT),GetSysColor(COLOR_3DSHADOW));
rc.DeflateRect(1,1);
dc->Draw3dRect(rc,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DDKSHADOW));
}
rc.DeflateRect(3,1);
if(key->cNormal == 0x00)
{
CString label = " ";
BOOL special = FALSE;
if(key->cShifted > 0x6F) //is a function
{
int fkeynum = key->cShifted - 0x6F;
label.Format("F%d",fkeynum);
}
else
{
switch(key->cShifted)
{
case TAB: // 0x02
label = "Tab->";
break;
case CAPSLOCK: // 0x03
label = "Caps";
break;
case SHIFT: // 0x04
label = "Shift";
break;
case CTRL: // 0x05
label = "Ctrl";
break;
case BSPACE: // 0x06
label = "<-Bspc";
break;
case ENTER: // 0x07
label = "Enter";
break;
case ALT: // 0x08
label = "Alt";
break;
case WINDOW: // 0x9
label = "Wnd";
break;
case ESC:
label = "Esc";
break;
case LEFT: // 0x0A
special = TRUE;
{
int cx = (rc.left + rc.right)/2;
int cy = (rc.top + rc.bottom)/2;
int siz = rc.Width()/3;
dc->MoveTo(cx+siz, cy);
dc->LineTo(cx-siz, cy);
dc->LineTo(cx-siz + (siz*4)/5, cy - siz/2);
dc->MoveTo(cx-siz, cy);
dc->LineTo(cx-siz + (siz*4)/5, cy + siz/2);
}
break;
case RIGHT: // 0x0B
special = TRUE;
{
int cx = (rc.left + rc.right)/2;
int cy = (rc.top + rc.bottom)/2;
int siz = rc.Width()/3;
dc->MoveTo(cx-siz, cy);
dc->LineTo(cx+siz, cy);
dc->LineTo(cx+siz - (siz*4)/5, cy - siz/2);
dc->MoveTo(cx+siz, cy);
dc->LineTo(cx+siz - (siz*4)/5, cy + siz/2);
}
break;
case UP: // 0x0C
special = TRUE;
{
int cx = (rc.left + rc.right)/2;
int cy = (rc.top + rc.bottom)/2;
int siz = rc.Width()/3;
dc->MoveTo(cx, cy+siz);
dc->LineTo(cx, cy-siz);
dc->LineTo(cx - siz/2, cy-siz + (siz*4)/5);
dc->LineTo(cx, cy-siz);
dc->LineTo(cx + siz/2, cy-siz + (siz*4)/5);
}
break;
case DOWN: // 0x0D
special = TRUE;
{
int cx = (rc.left + rc.right)/2;
int cy = (rc.top + rc.bottom)/2;
int siz = rc.Width()/3;
dc->MoveTo(cx, cy-siz);
dc->LineTo(cx, cy+siz);
dc->LineTo(cx - siz/2, cy+siz - (siz*4)/5);
dc->LineTo(cx, cy+siz);
dc->LineTo(cx + siz/2, cy+siz - (siz*4)/5);
}
break;
case PUP: //0x0F
label = "PgUp";
break;
case PDN: //0x10
label = "PgDn";
break;
case HOME: //0x11
label = "Home";
break;
case END: //0x12
label = "End";
break;
case INS: //0x13
label = "Ins";
break;
case DEL: //0x14
label = "Del";
break;
case WWW:
label = "WWW";
break;
default:
ASSERT(FALSE);
label = "#ERR#";
break;
}
}
if(!special)
{
CSize tsize;
tsize = dc->GetTextExtent(label);
dc->TextOut(
((rc.left + rc.right)/2) - (tsize.cx/2),
((rc.top + rc.bottom)/2) - (tsize.cy/2),
label);
}
}
else
{
if((key->cShifted >= 'A') && (key->cShifted <= 'Z'))
{
CSize tsize;
tsize = dc->GetTextExtent(key->cShifted);
dc->TextOut(
((rc.left + rc.right)/2) - (tsize.cx/2),
((rc.top + rc.bottom)/2) - (tsize.cy/2),
key->cShifted);
}
else
{
CSize tsize;
tsize = dc->GetTextExtent('M');
dc->TextOut(rc.left, rc.top, key->cShifted);
dc->TextOut(
rc.right - tsize.cx,
rc.bottom - tsize.cy,
key->cNormal);
}
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CVirtualKeyboardDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
DrawKeyboard();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CVirtualKeyboardDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CVirtualKeyboardDlg::SendKey(KEYDEF * keydef)
{
if(keydef->cNormal == 0x00)
{
int vk;
BOOL uptoo = TRUE;
if(keydef->cShifted > 0x6F) //is a function key
{
vk = keydef->cShifted;
}
else
{
switch(keydef->cShifted)
{
case TAB: // 0x02
vk = VkKeyScan(0x09) & 0xFF;
break;
case CAPSLOCK: // 0x03
vk = VK_CAPITAL;
break;
case SHIFT: // 0x04
vk = VK_SHIFT;
if(GetKeyState(vk) & 0xF000) return;
uptoo = FALSE;
break;
case CTRL: // 0x05
vk = VK_CONTROL;
if(GetKeyState(vk) & 0xF000) return;
uptoo = FALSE;
break;
case BSPACE: // 0x06
vk = VK_BACK;
break;
case ENTER: // 0x07
vk = VkKeyScan(0x0D) & 0xFF;
break;
case ALT: // 0x08
vk = VK_MENU;
break;
case WINDOW: // 0x9
vk = VK_LWIN;
break;
case LEFT: // 0x0A
vk = VK_LEFT;
break;
case RIGHT: // 0x0B
vk = VK_RIGHT;
break;
case UP: // 0x0C
vk = VK_UP;
break;
case DOWN: // 0x0D
vk = VK_DOWN;
break;
case PUP: //0x0F
vk = VK_PRIOR;
break;
case PDN: //0x10
vk = VK_NEXT;
break;
case HOME: //0x11
vk = VK_HOME;
break;
case END: //0x12
vk = VK_END;
break;
case INS: //0x13
vk = VK_INSERT;
break;
case DEL: //0x14
vk = VK_DELETE;
break;
case ESC:
vk = VK_HANGUL;
break;
case WWW:
KEYDEF key;
key.cNormal = key.cShifted = 'H';
SendKey(&key);
key.cNormal = key.cShifted = 'T';
SendKey(&key);
SendKey(&key);
key.cNormal = key.cShifted = 'P';
SendKey(&key);
key.cNormal = key.cShifted = ':';
SendKey(&key);
key.cNormal = key.cShifted = '/';
SendKey(&key);
SendKey(&key);
key.cNormal = key.cShifted = 'W';
SendKey(&key);
SendKey(&key);
SendKey(&key);
vk = VkKeyScan('.') & 0xFF;
break;
default:
ASSERT(FALSE);
break;
}
}
keybd_event(vk,0,0,0);
if(uptoo)
{
keybd_event(vk,0,KEYEVENTF_KEYUP,0);
}
}
else
{
char pChar = keydef->cNormal;
SHORT ks = VkKeyScan(pChar);
BYTE key = ks & 0xFF;
keybd_event(key,0,0,0);
keybd_event(key,0,KEYEVENTF_KEYUP,0);
//turn off the control and shift if they were down
unsigned char vk = VK_SHIFT;
if(GetKeyState(vk) & 0xF000)
{
keybd_event(vk,0,KEYEVENTF_KEYUP,0);
}
vk = VK_CONTROL;
if(GetKeyState(vk) & 0xF000) //allow toggle
{
keybd_event(vk,0,KEYEVENTF_KEYUP,0);
}
}
}
void CVirtualKeyboardDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
ReleaseFocus();
CRect client;
GetClientRect(client);
int x = 0;
int y = -pKeyHeight;
KEYDEF * key;
POSITION pos = cKeys.GetHeadPosition();
while(pos)
{
key = cKeys.GetNext(pos);
if((key->cNormal == 0x00) && (key->cShifted == 0x00))
{
x = 0;
y += pKeyHeight;
}
else
{
int width = ((abs(key->cWidth) * pKeyWidth) / 10);
CRect rc(x,y,x + width, y + pKeyHeight);
if(key->cWidth < 0)
{
rc.right = client.right;
}
x += width;
if(rc.PtInRect(point))
{
SendKey(key);
}
}
}
}
void CVirtualKeyboardDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
OnLButtonDown(nFlags, point);
}
BOOL CVirtualKeyboardDlg::PreTranslateMessage(MSG* pMsg)
{
HWND wnd = ::GetForegroundWindow();
if(IsWindow(wnd))
{
if(wnd != this->m_hWnd)
{
if(gFocus != wnd)
{
if(IsWindow(gFocus))
{
AttachThreadInput(
GetWindowThreadProcessId(m_hWnd,NULL),
GetWindowThreadProcessId(gFocus,NULL),
FALSE);
}
gFocus = wnd;
AttachThreadInput(
GetWindowThreadProcessId(m_hWnd,NULL),
GetWindowThreadProcessId(gFocus,NULL),
TRUE);
}
}
}
return CDialog::PreTranslateMessage(pMsg);
}
void CVirtualKeyboardDlg::OnRButtonDblClk(UINT nFlags, CPoint point)
{
OnLButtonDown(nFlags, point);
}
void CVirtualKeyboardDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
OnLButtonDown(nFlags, point);
}
void CVirtualKeyboardDlg::OnRButtonUp(UINT nFlags, CPoint point)
{
ReleaseFocus();
}
BOOL CVirtualKeyboardDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
ReleaseFocus();
return TRUE;
}
void CVirtualKeyboardDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
//ReleaseFocus();
}
void CVirtualKeyboardDlg::ReleaseFocus()
{
if(IsWindow(gFocus))
{
HWND wnd = ::GetForegroundWindow();
if(IsWindow(wnd))
{
if(wnd == gFocus)
{
return;
}
}
::SetForegroundWindow(gFocus);
::SetFocus(gFocus);
}
}
void CVirtualKeyboardDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
if(IsWindow(m_hWnd))
{
if(cKeys.GetCount())
{
CalcWidthHeight();
Invalidate();
}
}
}
void CVirtualKeyboardDlg::OnOK()
{
//ShowWindow(SW_HIDE);
}
void CVirtualKeyboardDlg::OnCancel()
{
//ShowWindow(SW_HIDE);
CDialog::OnCancel();
}
void CVirtualKeyboardDlg::OnShowKeyboard()
{
ShowWindow(SW_SHOW);
}
void CVirtualKeyboardDlg::OnUpdateShowKeyboard(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!IsWindowVisible());
}
void CVirtualKeyboardDlg::OnHideKeyboard()
{
ShowWindow(SW_HIDE);
}
void CVirtualKeyboardDlg::OnUpdateHideKeyboard(CCmdUI* pCmdUI)
{
pCmdUI->Enable(IsWindowVisible());
}
void CVirtualKeyboardDlg::OnExit()
{
POSITION pos = cKeys.GetHeadPosition();
while(pos)
{
delete cKeys.GetNext(pos);
}
int state = DescribeKeyState();
if(state & 0x01) keybd_event(VK_CAPITAL,0,KEYEVENTF_KEYUP,0);
if(state & 0x02) keybd_event(VK_SHIFT,0,KEYEVENTF_KEYUP,0);
if(state & 0x04) keybd_event(VK_CONTROL,0,KEYEVENTF_KEYUP,0);
CDialog::OnOK();
}
void CVirtualKeyboardDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
CDialog::OnShowWindow(bShow, nStatus);
}
int CVirtualKeyboardDlg::DescribeKeyState()
{
int state = 0;
short ks;
ks = GetKeyState(VK_CAPITAL);
if(ks & 0x000F) state += 0x01;
ks = GetKeyState(VK_SHIFT);
if(ks & 0xF000) state += 0x02;
ks = GetKeyState(VK_CONTROL);
if(ks & 0xF000) state += 0x04;
return state;
}
void CVirtualKeyboardDlg::DrawKeyboard()
{
CClientDC dc(this);
CRect client;
GetClientRect(client);
CRgn clipRgn;
clipRgn.CreateRectRgnIndirect(&client);
dc.SelectClipRgn(&clipRgn);
dc.SelectObject(GetStockObject(DEFAULT_GUI_FONT));
dc.SetBkMode(TRANSPARENT);
int x = 0;
int y = -pKeyHeight;
KEYDEF * key;
POSITION pos = cKeys.GetHeadPosition();
cCurrentKeyState = DescribeKeyState();
int state = cCurrentKeyState;
while(pos)
{
key = cKeys.GetNext(pos);
if((key->cNormal == 0x00) && (key->cShifted == 0x00))
{
x = 0;
y += pKeyHeight;
}
else
{
int width = ((abs(key->cWidth) * pKeyWidth) / 10);
CRect rc(x,y,x + width, y + pKeyHeight);
x += width;
if(key->cWidth < 0)
{
rc.right = client.right;
}
BOOL hilight = FALSE;
if(key->cNormal == 0x00)
{
switch(key->cShifted)
{
case CAPSLOCK:
if(state & 0x01)
{
hilight = TRUE;
}
break;
case SHIFT:
if(state & 0x02)
{
hilight = TRUE;
}
break;
case CTRL:
if(state & 0x04)
{
hilight = TRUE;
}
break;
default:
break;
}
}
DrawKey(&dc, rc, key, hilight);
}
}
}
long x = 0;
void CVirtualKeyboardDlg::OnTimer(UINT nIDEvent)
{
if(nIDEvent == TIMER_ID)
{
int state = DescribeKeyState();
if(state != cCurrentKeyState)
{
DrawKeyboard();
}
}
}
//
// header ----------------------------------------------------------------------------
//
// FocusTestDlg.h : header file
//
#if !defined(AFX_FOCUSTESTDLG_H__EFE558FB_FB84_11D3_8D1D_00C0F0405B24__INCLUDED_)
#define AFX_FOCUSTESTDLG_H__EFE558FB_FB84_11D3_8D1D_00C0F0405B24__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
/////////////////////////////////////////////////////////////////////////////
// CVirtualKeyboardDlg dialog
#include <afxtempl.h>
#include "resource.h"
struct KEYDEF
{
char cNormal;
char cShifted;
int cWidth;
};
class CVirtualKeyboardDlg : public CDialog
{
// Construction
public:
int pKeyWidth;
int pKeyHeight;
CTypedPtrList<CPtrList, KEYDEF*> cKeys;
void AddKey(
char pNormal,
char pShifted,
int pWidth);
void CalcWidthHeight();
void DrawKey(CDC * dc, CRect & rc, KEYDEF * key, BOOL cHilight=FALSE);
void SendKey(KEYDEF * key);
void ReleaseFocus();
int DescribeKeyState();
void DrawKeyboard();
int cCurrentKeyState;
HWND gFocus;
public:
CVirtualKeyboardDlg(CWnd* pParent = NULL); // standard constructor
virtual ~CVirtualKeyboardDlg(){}
// Dialog Data
//{{AFX_DATA(CVirtualKeyboardDlg)
enum { IDD = IDD_VIRTUAL_KEYBOARD_DLG };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CVirtualKeyboardDlg)
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CVirtualKeyboardDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnSize(UINT nType, int cx, int cy);
virtual void OnOK();
virtual void OnCancel();
afx_msg void OnShowKeyboard();
afx_msg void OnUpdateShowKeyboard(CCmdUI* pCmdUI);
afx_msg void OnHideKeyboard();
afx_msg void OnUpdateHideKeyboard(CCmdUI* pCmdUI);
afx_msg void OnExit();
afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
afx_msg void OnTimer(UINT nIDEvent);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_FOCUSTESTDLG_H__EFE558FB_FB84_11D3_8D1D_00C0F0405B24__INCLUDED_)
[/code]
[code]
// CVirtualKeyboardDlg.cpp : implementation file
//
#include "stdafx.h"
#include "VirtualKeyboardDlg.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define WM_ICON_NOTIFY WM_USER + 10
#define TIMER_ID 101
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
/////////////////////////////////////////////////////////////////////////////
// CVirtualKeyboardDlg dialog
CVirtualKeyboardDlg::CVirtualKeyboardDlg(CWnd* pParent /*=NULL*/)
: CDialog(CVirtualKeyboardDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CVirtualKeyboardDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CVirtualKeyboardDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CVirtualKeyboardDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CVirtualKeyboardDlg, CDialog)
//{{AFX_MSG_MAP(CVirtualKeyboardDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_RBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_MOUSEWHEEL()
ON_WM_LBUTTONUP()
ON_WM_SIZE()
// ON_COMMAND(IDM_SHOW_KEYBOARD, OnShowKeyboard)
// ON_UPDATE_COMMAND_UI(IDM_SHOW_KEYBOARD, OnUpdateShowKeyboard)
// ON_COMMAND(IDM_HIDE_KEYBOARD, OnHideKeyboard)
// ON_UPDATE_COMMAND_UI(IDM_HIDE_KEYBOARD, OnUpdateHideKeyboard)
// ON_COMMAND(IDM_EXIT, OnExit)
ON_WM_SHOWWINDOW()
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CVirtualKeyboardDlg message handlers
#define TAB 0x02
#define CAPSLOCK 0x03
#define SHIFT 0x04
#define CTRL 0x05
#define BSPACE 0x06
#define ENTER 0x07
#define ALT 0x08
#define WINDOW 0x9
#define LEFT 0x0A
#define RIGHT 0x0B
#define UP 0x0C
#define DOWN 0x0D
#define ESC 0x0E
#define PUP 0x0F
#define PDN 0x10
#define HOME 0x11
#define END 0x12
#define INS 0x13
#define DEL 0x14
#define WWW 0x15
BOOL CVirtualKeyboardDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
//build the keyboard definition
//control row
AddKey(0x00,0x00,0); //signal row change
AddKey(0x00,ESC,10);
for(int fnkey = 0x70; fnkey < 0x7C; fnkey++)
{
AddKey(0x00,fnkey & 0xFF,10);
}
AddKey(0x00,INS,14);
AddKey(0x00,DEL,-10);
//first row
AddKey(0x00,0x00,1); //signal row change
AddKey('`','~',10);
AddKey('1','!',10);
AddKey('2','@',10);
AddKey('3','#',10);
AddKey('4','$',10);
AddKey('5','%',10);
AddKey('6','^',10);
AddKey('7','&',10);
AddKey('8','*',10);
AddKey('9','(',10);
AddKey('0',')',10);
AddKey('-','_',10);
AddKey('=','+',10);
AddKey(0x00,BSPACE,14); //backspace
AddKey(0x00,PUP,-12);
//second row
AddKey(0x00,0x00,2); //signal row change
AddKey(0x00,TAB,14); //tab
AddKey('q','Q',10);
AddKey('w','W',10);
AddKey('e','E',10);
AddKey('r','R',10);
AddKey('t','T',10);
AddKey('y','Y',10);
AddKey('u','U',10);
AddKey('i','I',10);
AddKey('o','O',10);
AddKey('p','P',10);
AddKey('[','{',10);
AddKey(']','}',10);
AddKey('\\','|',10);
AddKey(0x00,PDN,-12);
//third row
AddKey(0x00,0x00,3); //signal row change
AddKey(0x00,CAPSLOCK,18); //caps lock
AddKey('a','A',10);
AddKey('s','S',10);
AddKey('d','D',10);
AddKey('f','F',10);
AddKey('g','G',10);
AddKey('h','H',10);
AddKey('j','J',10);
AddKey('k','K',10);
AddKey('l','L',10);
AddKey(';',':',10);
AddKey('\'','\"',10);
AddKey(0x00,ENTER,16); //enter
AddKey(0x00,HOME,-10);
//fourth row
AddKey(0x00,0x00,4); //signal row change
AddKey(0x00,SHIFT,22); //shift
AddKey('z','Z',10);
AddKey('x','X',10);
AddKey('c','C',10);
AddKey('v','V',10);
AddKey('b','B',10);
AddKey('n','N',10);
AddKey('m','M',10);
AddKey(',','<',10);
AddKey('.','>',10);
AddKey('/','?',10);
AddKey(0x00,SHIFT,22); //shift
AddKey(0x00,END,-10);
//fifth row
AddKey(0x00,0x00,5); //signal row change
AddKey(0x00,CTRL,12); //ctrl
AddKey(0x00,WINDOW,12); //window
AddKey(0x00,ALT,12); //alt
AddKey(' ',' ',60);
AddKey(0x00,LEFT,12); //left
AddKey(0x00,UP,12); //up
AddKey(0x00,DOWN,12); //down
AddKey(0x00,RIGHT,12); //right
//AddKey(0x00,WWW,-10); //http://WWW
CalcWidthHeight();
//put an icon for us in the system tray
//add us the the system tray
// SetTimer(TIMER_ID,250,NULL);
return TRUE; // return TRUE unless you set the focus to a control
}
void CVirtualKeyboardDlg::CalcWidthHeight()
{
pKeyWidth = 0;
pKeyHeight = 0;
KEYDEF * key;
POSITION pos = cKeys.GetHeadPosition();
long totalWidth = 0;
long longest = 0;
long rows = 0;
while(pos)
{
key = cKeys.GetNext(pos);
if((key->cNormal == 0x00) && (key->cShifted == 0x00))
{
rows++;
if(totalWidth > longest)
{
longest = totalWidth;
}
totalWidth = 0;
}
else
{
totalWidth += abs(key->cWidth);
}
}
CRect rect;
GetClientRect(rect);
pKeyHeight = rect.Height() / rows;
pKeyWidth = (int)(((double)rect.Width()) / ((((double)(longest)) / 10)));
}
void CVirtualKeyboardDlg::AddKey(
char pNormal,
char pShifted,
int pWidth)
{
KEYDEF * key = new KEYDEF;
key->cNormal = pNormal;
key->cShifted = pShifted;
key->cWidth = pWidth;
cKeys.AddTail(key);
}
void CVirtualKeyboardDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
CDialog::OnSysCommand(nID, lParam);
}
void CVirtualKeyboardDlg::DrawKey(CDC * dc, CRect & rc, KEYDEF * key, BOOL cHilight)
{
if(!cHilight)
{
rc.DeflateRect(1,1);
dc->FillSolidRect(rc,GetSysColor(COLOR_3DFACE));
dc->Draw3dRect(rc,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DDKSHADOW));
rc.DeflateRect(1,1);
dc->Draw3dRect(rc,GetSysColor(COLOR_3DLIGHT),GetSysColor(COLOR_3DSHADOW));
}
else
{
rc.DeflateRect(1,1);
dc->FillSolidRect(rc,GetSysColor(COLOR_3DLIGHT));
dc->Draw3dRect(rc,GetSysColor(COLOR_3DLIGHT),GetSysColor(COLOR_3DSHADOW));
rc.DeflateRect(1,1);
dc->Draw3dRect(rc,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DDKSHADOW));
}
rc.DeflateRect(3,1);
if(key->cNormal == 0x00)
{
CString label = " ";
BOOL special = FALSE;
if(key->cShifted > 0x6F) //is a function
{
int fkeynum = key->cShifted - 0x6F;
label.Format("F%d",fkeynum);
}
else
{
switch(key->cShifted)
{
case TAB: // 0x02
label = "Tab->";
break;
case CAPSLOCK: // 0x03
label = "Caps";
break;
case SHIFT: // 0x04
label = "Shift";
break;
case CTRL: // 0x05
label = "Ctrl";
break;
case BSPACE: // 0x06
label = "<-Bspc";
break;
case ENTER: // 0x07
label = "Enter";
break;
case ALT: // 0x08
label = "Alt";
break;
case WINDOW: // 0x9
label = "Wnd";
break;
case ESC:
label = "Esc";
break;
case LEFT: // 0x0A
special = TRUE;
{
int cx = (rc.left + rc.right)/2;
int cy = (rc.top + rc.bottom)/2;
int siz = rc.Width()/3;
dc->MoveTo(cx+siz, cy);
dc->LineTo(cx-siz, cy);
dc->LineTo(cx-siz + (siz*4)/5, cy - siz/2);
dc->MoveTo(cx-siz, cy);
dc->LineTo(cx-siz + (siz*4)/5, cy + siz/2);
}
break;
case RIGHT: // 0x0B
special = TRUE;
{
int cx = (rc.left + rc.right)/2;
int cy = (rc.top + rc.bottom)/2;
int siz = rc.Width()/3;
dc->MoveTo(cx-siz, cy);
dc->LineTo(cx+siz, cy);
dc->LineTo(cx+siz - (siz*4)/5, cy - siz/2);
dc->MoveTo(cx+siz, cy);
dc->LineTo(cx+siz - (siz*4)/5, cy + siz/2);
}
break;
case UP: // 0x0C
special = TRUE;
{
int cx = (rc.left + rc.right)/2;
int cy = (rc.top + rc.bottom)/2;
int siz = rc.Width()/3;
dc->MoveTo(cx, cy+siz);
dc->LineTo(cx, cy-siz);
dc->LineTo(cx - siz/2, cy-siz + (siz*4)/5);
dc->LineTo(cx, cy-siz);
dc->LineTo(cx + siz/2, cy-siz + (siz*4)/5);
}
break;
case DOWN: // 0x0D
special = TRUE;
{
int cx = (rc.left + rc.right)/2;
int cy = (rc.top + rc.bottom)/2;
int siz = rc.Width()/3;
dc->MoveTo(cx, cy-siz);
dc->LineTo(cx, cy+siz);
dc->LineTo(cx - siz/2, cy+siz - (siz*4)/5);
dc->LineTo(cx, cy+siz);
dc->LineTo(cx + siz/2, cy+siz - (siz*4)/5);
}
break;
case PUP: //0x0F
label = "PgUp";
break;
case PDN: //0x10
label = "PgDn";
break;
case HOME: //0x11
label = "Home";
break;
case END: //0x12
label = "End";
break;
case INS: //0x13
label = "Ins";
break;
case DEL: //0x14
label = "Del";
break;
case WWW:
label = "WWW";
break;
default:
ASSERT(FALSE);
label = "#ERR#";
break;
}
}
if(!special)
{
CSize tsize;
tsize = dc->GetTextExtent(label);
dc->TextOut(
((rc.left + rc.right)/2) - (tsize.cx/2),
((rc.top + rc.bottom)/2) - (tsize.cy/2),
label);
}
}
else
{
if((key->cShifted >= 'A') && (key->cShifted <= 'Z'))
{
CSize tsize;
tsize = dc->GetTextExtent(key->cShifted);
dc->TextOut(
((rc.left + rc.right)/2) - (tsize.cx/2),
((rc.top + rc.bottom)/2) - (tsize.cy/2),
key->cShifted);
}
else
{
CSize tsize;
tsize = dc->GetTextExtent('M');
dc->TextOut(rc.left, rc.top, key->cShifted);
dc->TextOut(
rc.right - tsize.cx,
rc.bottom - tsize.cy,
key->cNormal);
}
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CVirtualKeyboardDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
DrawKeyboard();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CVirtualKeyboardDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CVirtualKeyboardDlg::SendKey(KEYDEF * keydef)
{
if(keydef->cNormal == 0x00)
{
int vk;
BOOL uptoo = TRUE;
if(keydef->cShifted > 0x6F) //is a function key
{
vk = keydef->cShifted;
}
else
{
switch(keydef->cShifted)
{
case TAB: // 0x02
vk = VkKeyScan(0x09) & 0xFF;
break;
case CAPSLOCK: // 0x03
vk = VK_CAPITAL;
break;
case SHIFT: // 0x04
vk = VK_SHIFT;
if(GetKeyState(vk) & 0xF000) return;
uptoo = FALSE;
break;
case CTRL: // 0x05
vk = VK_CONTROL;
if(GetKeyState(vk) & 0xF000) return;
uptoo = FALSE;
break;
case BSPACE: // 0x06
vk = VK_BACK;
break;
case ENTER: // 0x07
vk = VkKeyScan(0x0D) & 0xFF;
break;
case ALT: // 0x08
vk = VK_MENU;
break;
case WINDOW: // 0x9
vk = VK_LWIN;
break;
case LEFT: // 0x0A
vk = VK_LEFT;
break;
case RIGHT: // 0x0B
vk = VK_RIGHT;
break;
case UP: // 0x0C
vk = VK_UP;
break;
case DOWN: // 0x0D
vk = VK_DOWN;
break;
case PUP: //0x0F
vk = VK_PRIOR;
break;
case PDN: //0x10
vk = VK_NEXT;
break;
case HOME: //0x11
vk = VK_HOME;
break;
case END: //0x12
vk = VK_END;
break;
case INS: //0x13
vk = VK_INSERT;
break;
case DEL: //0x14
vk = VK_DELETE;
break;
case ESC:
vk = VK_HANGUL;
break;
case WWW:
KEYDEF key;
key.cNormal = key.cShifted = 'H';
SendKey(&key);
key.cNormal = key.cShifted = 'T';
SendKey(&key);
SendKey(&key);
key.cNormal = key.cShifted = 'P';
SendKey(&key);
key.cNormal = key.cShifted = ':';
SendKey(&key);
key.cNormal = key.cShifted = '/';
SendKey(&key);
SendKey(&key);
key.cNormal = key.cShifted = 'W';
SendKey(&key);
SendKey(&key);
SendKey(&key);
vk = VkKeyScan('.') & 0xFF;
break;
default:
ASSERT(FALSE);
break;
}
}
keybd_event(vk,0,0,0);
if(uptoo)
{
keybd_event(vk,0,KEYEVENTF_KEYUP,0);
}
}
else
{
char pChar = keydef->cNormal;
SHORT ks = VkKeyScan(pChar);
BYTE key = ks & 0xFF;
keybd_event(key,0,0,0);
keybd_event(key,0,KEYEVENTF_KEYUP,0);
//turn off the control and shift if they were down
unsigned char vk = VK_SHIFT;
if(GetKeyState(vk) & 0xF000)
{
keybd_event(vk,0,KEYEVENTF_KEYUP,0);
}
vk = VK_CONTROL;
if(GetKeyState(vk) & 0xF000) //allow toggle
{
keybd_event(vk,0,KEYEVENTF_KEYUP,0);
}
}
}
void CVirtualKeyboardDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
ReleaseFocus();
CRect client;
GetClientRect(client);
int x = 0;
int y = -pKeyHeight;
KEYDEF * key;
POSITION pos = cKeys.GetHeadPosition();
while(pos)
{
key = cKeys.GetNext(pos);
if((key->cNormal == 0x00) && (key->cShifted == 0x00))
{
x = 0;
y += pKeyHeight;
}
else
{
int width = ((abs(key->cWidth) * pKeyWidth) / 10);
CRect rc(x,y,x + width, y + pKeyHeight);
if(key->cWidth < 0)
{
rc.right = client.right;
}
x += width;
if(rc.PtInRect(point))
{
SendKey(key);
}
}
}
}
void CVirtualKeyboardDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
OnLButtonDown(nFlags, point);
}
BOOL CVirtualKeyboardDlg::PreTranslateMessage(MSG* pMsg)
{
HWND wnd = ::GetForegroundWindow();
if(IsWindow(wnd))
{
if(wnd != this->m_hWnd)
{
if(gFocus != wnd)
{
if(IsWindow(gFocus))
{
AttachThreadInput(
GetWindowThreadProcessId(m_hWnd,NULL),
GetWindowThreadProcessId(gFocus,NULL),
FALSE);
}
gFocus = wnd;
AttachThreadInput(
GetWindowThreadProcessId(m_hWnd,NULL),
GetWindowThreadProcessId(gFocus,NULL),
TRUE);
}
}
}
return CDialog::PreTranslateMessage(pMsg);
}
void CVirtualKeyboardDlg::OnRButtonDblClk(UINT nFlags, CPoint point)
{
OnLButtonDown(nFlags, point);
}
void CVirtualKeyboardDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
OnLButtonDown(nFlags, point);
}
void CVirtualKeyboardDlg::OnRButtonUp(UINT nFlags, CPoint point)
{
ReleaseFocus();
}
BOOL CVirtualKeyboardDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
ReleaseFocus();
return TRUE;
}
void CVirtualKeyboardDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
//ReleaseFocus();
}
void CVirtualKeyboardDlg::ReleaseFocus()
{
if(IsWindow(gFocus))
{
HWND wnd = ::GetForegroundWindow();
if(IsWindow(wnd))
{
if(wnd == gFocus)
{
return;
}
}
::SetForegroundWindow(gFocus);
::SetFocus(gFocus);
}
}
void CVirtualKeyboardDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
if(IsWindow(m_hWnd))
{
if(cKeys.GetCount())
{
CalcWidthHeight();
Invalidate();
}
}
}
void CVirtualKeyboardDlg::OnOK()
{
//ShowWindow(SW_HIDE);
}
void CVirtualKeyboardDlg::OnCancel()
{
//ShowWindow(SW_HIDE);
CDialog::OnCancel();
}
void CVirtualKeyboardDlg::OnShowKeyboard()
{
ShowWindow(SW_SHOW);
}
void CVirtualKeyboardDlg::OnUpdateShowKeyboard(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!IsWindowVisible());
}
void CVirtualKeyboardDlg::OnHideKeyboard()
{
ShowWindow(SW_HIDE);
}
void CVirtualKeyboardDlg::OnUpdateHideKeyboard(CCmdUI* pCmdUI)
{
pCmdUI->Enable(IsWindowVisible());
}
void CVirtualKeyboardDlg::OnExit()
{
POSITION pos = cKeys.GetHeadPosition();
while(pos)
{
delete cKeys.GetNext(pos);
}
int state = DescribeKeyState();
if(state & 0x01) keybd_event(VK_CAPITAL,0,KEYEVENTF_KEYUP,0);
if(state & 0x02) keybd_event(VK_SHIFT,0,KEYEVENTF_KEYUP,0);
if(state & 0x04) keybd_event(VK_CONTROL,0,KEYEVENTF_KEYUP,0);
CDialog::OnOK();
}
void CVirtualKeyboardDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
CDialog::OnShowWindow(bShow, nStatus);
}
int CVirtualKeyboardDlg::DescribeKeyState()
{
int state = 0;
short ks;
ks = GetKeyState(VK_CAPITAL);
if(ks & 0x000F) state += 0x01;
ks = GetKeyState(VK_SHIFT);
if(ks & 0xF000) state += 0x02;
ks = GetKeyState(VK_CONTROL);
if(ks & 0xF000) state += 0x04;
return state;
}
void CVirtualKeyboardDlg::DrawKeyboard()
{
CClientDC dc(this);
CRect client;
GetClientRect(client);
CRgn clipRgn;
clipRgn.CreateRectRgnIndirect(&client);
dc.SelectClipRgn(&clipRgn);
dc.SelectObject(GetStockObject(DEFAULT_GUI_FONT));
dc.SetBkMode(TRANSPARENT);
int x = 0;
int y = -pKeyHeight;
KEYDEF * key;
POSITION pos = cKeys.GetHeadPosition();
cCurrentKeyState = DescribeKeyState();
int state = cCurrentKeyState;
while(pos)
{
key = cKeys.GetNext(pos);
if((key->cNormal == 0x00) && (key->cShifted == 0x00))
{
x = 0;
y += pKeyHeight;
}
else
{
int width = ((abs(key->cWidth) * pKeyWidth) / 10);
CRect rc(x,y,x + width, y + pKeyHeight);
x += width;
if(key->cWidth < 0)
{
rc.right = client.right;
}
BOOL hilight = FALSE;
if(key->cNormal == 0x00)
{
switch(key->cShifted)
{
case CAPSLOCK:
if(state & 0x01)
{
hilight = TRUE;
}
break;
case SHIFT:
if(state & 0x02)
{
hilight = TRUE;
}
break;
case CTRL:
if(state & 0x04)
{
hilight = TRUE;
}
break;
default:
break;
}
}
DrawKey(&dc, rc, key, hilight);
}
}
}
long x = 0;
void CVirtualKeyboardDlg::OnTimer(UINT nIDEvent)
{
if(nIDEvent == TIMER_ID)
{
int state = DescribeKeyState();
if(state != cCurrentKeyState)
{
DrawKeyboard();
}
}
}
//
// header ----------------------------------------------------------------------------
//
// FocusTestDlg.h : header file
//
#if !defined(AFX_FOCUSTESTDLG_H__EFE558FB_FB84_11D3_8D1D_00C0F0405B24__INCLUDED_)
#define AFX_FOCUSTESTDLG_H__EFE558FB_FB84_11D3_8D1D_00C0F0405B24__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
/////////////////////////////////////////////////////////////////////////////
// CVirtualKeyboardDlg dialog
#include <afxtempl.h>
#include "resource.h"
struct KEYDEF
{
char cNormal;
char cShifted;
int cWidth;
};
class CVirtualKeyboardDlg : public CDialog
{
// Construction
public:
int pKeyWidth;
int pKeyHeight;
CTypedPtrList<CPtrList, KEYDEF*> cKeys;
void AddKey(
char pNormal,
char pShifted,
int pWidth);
void CalcWidthHeight();
void DrawKey(CDC * dc, CRect & rc, KEYDEF * key, BOOL cHilight=FALSE);
void SendKey(KEYDEF * key);
void ReleaseFocus();
int DescribeKeyState();
void DrawKeyboard();
int cCurrentKeyState;
HWND gFocus;
public:
CVirtualKeyboardDlg(CWnd* pParent = NULL); // standard constructor
virtual ~CVirtualKeyboardDlg(){}
// Dialog Data
//{{AFX_DATA(CVirtualKeyboardDlg)
enum { IDD = IDD_VIRTUAL_KEYBOARD_DLG };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CVirtualKeyboardDlg)
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CVirtualKeyboardDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnSize(UINT nType, int cx, int cy);
virtual void OnOK();
virtual void OnCancel();
afx_msg void OnShowKeyboard();
afx_msg void OnUpdateShowKeyboard(CCmdUI* pCmdUI);
afx_msg void OnHideKeyboard();
afx_msg void OnUpdateHideKeyboard(CCmdUI* pCmdUI);
afx_msg void OnExit();
afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
afx_msg void OnTimer(UINT nIDEvent);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_FOCUSTESTDLG_H__EFE558FB_FB84_11D3_8D1D_00C0F0405B24__INCLUDED_)
[/code]