softkeyboard.cpp

来自「自己用Markov模型做的一个整句物笔输入法的原型」· C++ 代码 · 共 597 行

CPP
597
字号
// softkeyboard.cpp : implementation file
//
#include "stdafx.h"
#include "resource.h"
#include "Afxtempl.h"
#include "HikerWBFunc.h"
#include "softkeyboard.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define BACKSPACE	8
#define TAB			9
#define CAPS		20
#define ENTER		13
#define SHIFT		16
#define ESC			27
#define SPACE		32
#define INS			45
#define DEL			46

#define BUTTONSIZE	29
#define KEYNAMECOLOR 0x00AF0000
#define KEYTEXTCOLOR 0x000000AF


static unsigned char gSpcKeyArr[9] = {BACKSPACE, TAB, CAPS, ENTER, SHIFT, ESC, SPACE, INS, DEL};
static unsigned char gVKArr[47] = {192, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 189, 187, 81, 87, 69, 82, 84, 89, 85, 73, 79, 80, 219, 221, 220, 65, 83, 68, 70, 71, 72, 74, 75, 76, 186, 222, 90, 88, 67, 86, 66, 78, 77, 188, 190, 191};

static unsigned char gKeyArr[SOFTKEYBOARD_NUM*2][SOFTKEYBOARD_LEN] = {
		/*PC keyboard*/
		{
			SOFTKEY_PCC
		},
		{
			SOFTKEY_PCL
		},
		/*Greece letter*/																																								
		{
			SOFTKEY_GLC
		},
		{
			SOFTKEY_GLL
		},
		/*Russia letter*/																																							
		{
			SOFTKEY_RLC
		},
		{
			SOFTKEY_RLL
		},
		/*chinese spell letter*/																																									
		{
			SOFTKEY_NON
		},	
		{
			SOFTKEY_CSL
		},
		/*phonetic notation*/																																										
		{
			SOFTKEY_NON
		},	
		{
			SOFTKEY_CPN
		},
		/*Japanese hiragana */																																								
		{
			SOFTKEY_JHC
		},		
		{
			SOFTKEY_JHL
		},
		/*Japanese katakana*/																																			
		{
			SOFTKEY_JKC
		},
		{
			SOFTKEY_JKL
		},
		/*punctuation*/																																						
		{
			SOFTKEY_NON
		},
		{
			SOFTKEY_PCT
		},
		/*serial number*/																					
		{
			SOFTKEY_SNC
		},
		{
			SOFTKEY_SNL
		},
		/*mathematics notation*/
		{
			SOFTKEY_NON
		},
		{
			SOFTKEY_MAT
		},
		/*special notation*/																																								
		{
			SOFTKEY_NON
		},
		{
			SOFTKEY_SPC
		},
		/*全角字符*/
		{
			SOFTKEY_SBC
		},
		{
			SOFTKEY_SBL
		},
};


/////////////////////////////////////////////////////////////////////////////
// CSoftKeyboard dialog


CSoftKeyboard::CSoftKeyboard(CWnd* pParent /*=NULL*/)
{
	//{{AFX_DATA_INIT(CSoftKeyboard)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


BEGIN_MESSAGE_MAP(CSoftKeyboard, CWnd)
	//{{AFX_MSG_MAP(CSoftKeyboard)
	ON_WM_CREATE()
	ON_WM_LBUTTONDOWN()
	ON_WM_PAINT()
	ON_WM_LBUTTONUP()
	ON_WM_RBUTTONDOWN()
	//}}AFX_MSG_MAP

	ON_COMMAND_RANGE(ID_MENU_SKB_CLOSE, ID_MENU_SKB_CLOSE, OnMenuSkb)
	ON_COMMAND_RANGE(ID_MENU_SKB_CSL,ID_MENU_SKB_CSL, OnMenuSkb)
	ON_COMMAND_RANGE(ID_MENU_SKB_GL, ID_MENU_SKB_GL, OnMenuSkb)
	ON_COMMAND_RANGE(ID_MENU_SKB_JH, ID_MENU_SKB_JH, OnMenuSkb)
	ON_COMMAND_RANGE(ID_MENU_SKB_JK, ID_MENU_SKB_JK, OnMenuSkb)
	ON_COMMAND_RANGE(ID_MENU_SKB_MN, ID_MENU_SKB_MN, OnMenuSkb)
	ON_COMMAND_RANGE(ID_MENU_SKB_PC, ID_MENU_SKB_PC, OnMenuSkb)
	ON_COMMAND_RANGE(ID_MENU_SKB_PN, ID_MENU_SKB_PN, OnMenuSkb)
	ON_COMMAND_RANGE(ID_MENU_SKB_PT, ID_MENU_SKB_PT, OnMenuSkb)
	ON_COMMAND_RANGE(ID_MENU_SKB_RL, ID_MENU_SKB_RL, OnMenuSkb)
	ON_COMMAND_RANGE(ID_MENU_SKB_SN, ID_MENU_SKB_SN, OnMenuSkb)
	ON_COMMAND_RANGE(ID_MENU_SKB_SP, ID_MENU_SKB_SP, OnMenuSkb)

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSoftKeyboard message handlers

int CSoftKeyboard::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here

	//ordinary key (0 ~ 46)
	CRect rt;
	int i;

	rt.SetRect(0, 0, BUTTONSIZE, BUTTONSIZE);		//backquote key
	m_cRectList.AddTail(rt);
	for (i = 0; i < 12; i++)
	{
		rt.OffsetRect(BUTTONSIZE, 0);
		m_cRectList.AddTail(rt);		//1 key
	}

	rt.SetRect(BUTTONSIZE+10, BUTTONSIZE,  BUTTONSIZE*2+10, BUTTONSIZE*2);			//q key
	m_cRectList.AddTail(rt);
	for (i = 0; i < 12; i++)
	{
		rt.OffsetRect(BUTTONSIZE, 0);
		m_cRectList.AddTail(rt);		//1 key
	}

	rt.SetRect(BUTTONSIZE+20, BUTTONSIZE*2, BUTTONSIZE*2+20, BUTTONSIZE*3);			//q key
	m_cRectList.AddTail(rt);
	for (i = 0; i < 10; i++)
	{
		rt.OffsetRect(BUTTONSIZE, 0);
		m_cRectList.AddTail(rt);		//1 key
	}

	rt.SetRect(BUTTONSIZE+30, BUTTONSIZE*3, BUTTONSIZE*2+30, BUTTONSIZE*4);			//q key
	m_cRectList.AddTail(rt);
	for (i = 0; i < 9; i++)
	{
		rt.OffsetRect(BUTTONSIZE, 0);
		m_cRectList.AddTail(rt);		//1 key
	}

	//special key (47~55)
	rt.SetRect(13*BUTTONSIZE, 0, 14*BUTTONSIZE+10, BUTTONSIZE);	//backspace key
	m_cRectList.AddTail(rt);
	rt.SetRect(0, BUTTONSIZE, BUTTONSIZE+10, BUTTONSIZE*2);		//tab key
	m_cRectList.AddTail(rt);
	rt.SetRect(0, BUTTONSIZE*2, BUTTONSIZE+20, BUTTONSIZE*3);		//caps lock key
	m_cRectList.AddTail(rt);
	rt.SetRect(BUTTONSIZE+20+11*BUTTONSIZE, BUTTONSIZE*2, 14*BUTTONSIZE+10, BUTTONSIZE*3);	//enter key
	m_cRectList.AddTail(rt);
	rt.SetRect(0, BUTTONSIZE*3, BUTTONSIZE+30, BUTTONSIZE*4);		//shift key
	m_cRectList.AddTail(rt);
	rt.SetRect(0, BUTTONSIZE*4, BUTTONSIZE, BUTTONSIZE*5);		//Esc key
	m_cRectList.AddTail(rt);
	rt.SetRect(BUTTONSIZE, BUTTONSIZE*4, BUTTONSIZE*12+10, BUTTONSIZE*5);		//space key
	m_cRectList.AddTail(rt);
	rt.SetRect(BUTTONSIZE*12+10, BUTTONSIZE*4, BUTTONSIZE*13+10, BUTTONSIZE*5);	//Ins key
	m_cRectList.AddTail(rt);
	rt.SetRect(BUTTONSIZE*13+10, BUTTONSIZE*4, BUTTONSIZE*14+10, BUTTONSIZE*5);	//Del key
	m_cRectList.AddTail(rt);

	LOGPEN lpen;
	lpen.lopnWidth = CPoint(1,1);
	lpen.lopnColor = KEYNAMECOLOR;
	lpen.lopnStyle = PS_SOLID;
	m_pen1.CreatePenIndirect(&lpen);
	lpen.lopnWidth = CPoint(2,2);
	m_pen2.CreatePenIndirect(&lpen);

	m_bShiftDown = FALSE;
	m_iDonwKey = -1;

	return 0;
}

void CSoftKeyboard::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	int iKey = HitTest(point);
	if (-1 == iKey)
		return;

	m_iDonwKey = iKey;
	POSITION pos = m_cRectList.FindIndex(iKey);
	CRect rt = m_cRectList.GetAt(pos);
	InvalidateRect(rt);

	if (20 == iKey)
		return;				//if capslock key down, don't post message

	if (51 == iKey)
	{
		m_bShiftDown = !m_bShiftDown;
		return;				//if shift key down, don't post the key-down message immediately
	}

	HANDLE hFile = OpenFileMapping(FILE_MAP_READ, FALSE, "Hook");
	if (hFile)
	{
		HWND *pHWnd = (HWND*)MapViewOfFile(hFile, FILE_MAP_READ, 0, 0, 0);

		if (iKey < 47)		//alphabetic or number key
		{
//			if (m_bShiftDown)
//			{
//				::PostMessage(*pHWnd, WM_HOOKKEY, gKeyArr[m_iKeyboardId*2][iKey*2], -1);
//				if (m_iKeyboardId > 0)	//double bytes keyboard
//					::PostMessage(*pHWnd, WM_HOOKKEY, gKeyArr[m_iKeyboardId*2][iKey*2+1], -1);
//			}
//			else
//			{
//				::PostMessage(*pHWnd, WM_HOOKKEY, gKeyArr[m_iKeyboardId*2+1][iKey*2], -1);
//				if (m_iKeyboardId > 0)	//double bytes keyborad
//					::PostMessage(*pHWnd, WM_HOOKKEY, gKeyArr[m_iKeyboardId*2+1][iKey*2+1], -1);
//			}
			::PostMessage(*pHWnd, WM_HOOKKEY, gVKArr[iKey], ((m_bShiftDown)?-100:0)-m_iKeyboardId);
		}
		else
		{
			::PostMessage(*pHWnd, WM_HOOKKEY, gSpcKeyArr[iKey-47], ((m_bShiftDown)?-100:0)-m_iKeyboardId);
		}

		UnmapViewOfFile(pHWnd);  //取消映射
		CloseHandle(hFile);   //关闭内存映射文件
	}

	if (m_bShiftDown)
		m_bShiftDown = FALSE;


	CWnd::OnLButtonDown(nFlags, point);
}

void CSoftKeyboard::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
	CRect rt;
	GetClientRect(&rt);
	dc.FillSolidRect(rt, GetSysColor(COLOR_BTNFACE));

	CFont* font = dc.GetCurrentFont();
	LOGFONT lfont;
	font->GetLogFont(&lfont);
	lfont.lfWeight = FW_NORMAL;
	lfont.lfHeight = -14;
	lstrcpy(lfont.lfFaceName, "Times New Roman");
	CFont ftnew;
	ftnew.CreateFontIndirect(&lfont);
	dc.SelectObject(&ftnew);

	
	DrawKeys(&dc);
	// Do not call CWnd::OnPaint() for painting messages
}

void CSoftKeyboard::DrawKeys(CDC *pdc) 
{
	CRect rt;
	POSITION pos = m_cRectList.GetHeadPosition();
	for(int i = 0; pos != 0; i++)
	{
		rt = m_cRectList.GetNext(pos);
		DrawButton(pdc, &rt, i);
	}
}

void CSoftKeyboard::DrawButton(CDC *pdc, CRect *rt, int id) 
{
	char c, c1, c2;
	POINT pt;
	int i;

	if (id != m_iDonwKey)
		pdc->Draw3dRect(rt, GetSysColor(COLOR_BTNHIGHLIGHT), GetSysColor(COLOR_3DSHADOW));
	else
		pdc->Draw3dRect(rt, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_BTNHIGHLIGHT));

	pdc->SetBkColor(GetSysColor(COLOR_BTNFACE));
	if (id < 47)
	{
		//display key name
		pdc->SetTextColor(KEYNAMECOLOR);
		rt->DeflateRect(1, 1, 8, 8);
		if (id >= 13)
			c = gKeyArr[0][id*2];
		else
			c = gKeyArr[1][id*2];
		pdc->DrawText(CString(c), rt, DT_LEFT|DT_TOP);

		pdc->SetTextColor(KEYTEXTCOLOR);
		rt->OffsetRect(11, 0);
		c1 = gKeyArr[m_iKeyboardId*2][id*2];
		c2 = gKeyArr[m_iKeyboardId*2][id*2+1];
		if (0 != c1)
			pdc->DrawText(CString(c1)+CString(c2), rt, DT_LEFT|DT_TOP);

		rt->OffsetRect(-6, 12);
		c1 = gKeyArr[m_iKeyboardId*2+1][id*2];
		c2 = gKeyArr[m_iKeyboardId*2+1][id*2+1];
		if (0 != c1)
			pdc->DrawText(CString(c1)+CString(c2), rt, DT_LEFT|DT_TOP);
	}
	else
	{
		pdc->SetTextColor(KEYNAMECOLOR);
		rt->DeflateRect(2, 1, 1, 1);
		switch(id) {
		case 47:			//BACKSPACE key
			//pdc->DrawText(CString("Backspace"), rt, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
			pdc->SelectObject(&m_pen2);
			pdc->MoveTo(rt->left+17, rt->CenterPoint().y);
			pdc->LineTo(rt->right-9,rt->CenterPoint().y);
			pdc->SelectObject(&m_pen1);
			pt = CPoint(rt->left+9, rt->CenterPoint().y-1);
			for (i = 0; i < 4; i++)
			{
				pdc->MoveTo(pt);
				pdc->LineTo(pt.x + 8 - 2*i, pt.y);
				pt.x += 2;
				pt.y --;
			}
			pt = CPoint(rt->left+9, rt->CenterPoint().y);
			for (i = 0; i < 4; i++)
			{
				pdc->MoveTo(pt);
				pdc->LineTo(pt.x + 8 - 2*i, pt.y);
				pt.x +=2;
				pt.y ++;
			}
			break;
		case 48:
			pdc->DrawText(CString("Tab"), rt, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
			break;
		case 49:
			pdc->DrawText(CString("Caps"), rt, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
			break;
		case 50:
			pdc->DrawText(CString("Enter"), rt, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
			break;
		case 51:
			pdc->DrawText(CString("Shift"), rt, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
			break;
		case 52:
			pdc->DrawText(CString("Esc"), rt, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
			break;
		case 54:
			pdc->DrawText(CString("Ins"), rt, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
			break;
		case 55:
			pdc->DrawText(CString("Del"), rt, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
			break;
		default:
			break;
		}
	}
}

int CSoftKeyboard::HitTest(POINT pt)
{
	CRect rt;

	POSITION pos = m_cRectList.GetHeadPosition();
	for (int i = 0; pos != 0; i++)
	{
		rt = m_cRectList.GetNext(pos);
		if (rt.PtInRect(pt))
			return i;
	}

	return -1;
}

//05.11.10
void CSoftKeyboard::LockInputWnd()
{
	HWND wnd = ::GetForegroundWindow();
	if(IsWindow(wnd))
	{
		if(wnd != this->m_hWnd)
		{
			if(m_hInputWnd != wnd)
			{
				if(IsWindow(m_hInputWnd))
				{
					AttachThreadInput(
						GetWindowThreadProcessId(m_hWnd,NULL),
						GetWindowThreadProcessId(m_hInputWnd, NULL),
						FALSE);
				}

				m_hInputWnd = wnd;
				AttachThreadInput(
					GetWindowThreadProcessId(m_hWnd,NULL),
					GetWindowThreadProcessId(m_hInputWnd,NULL),
					TRUE);
			}
		}
	}
}

void CSoftKeyboard::ReleaseFocus()
{
	if(IsWindow(m_hInputWnd))
	{
		HWND wnd = ::GetForegroundWindow();
		if(IsWindow(wnd))
		{
			if(wnd == m_hInputWnd)
			{
				return;
			}
		}
		::SetForegroundWindow(m_hInputWnd);
		::SetFocus(m_hInputWnd);
	}
}

BOOL CSoftKeyboard::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	HCURSOR hcur = LoadCursor(NULL, IDC_ARROW);
	SetCursor(hcur);
	
	LockInputWnd();
	ReleaseFocus();
	
	return CWnd::PreTranslateMessage(pMsg);
}

void CSoftKeyboard::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	if (m_iDonwKey < 0)
		return;

	POSITION pos = m_cRectList.FindIndex(m_iDonwKey);
	CRect rt = m_cRectList.GetAt(pos);
	m_iDonwKey = -1;
	InvalidateRect(rt);
	
	CWnd::OnLButtonUp(nFlags, point);
}

void CSoftKeyboard::OnRButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	CMenu menuskb;
	CPoint pt = point;

	ClientToScreen(&pt);

	menuskb.CreatePopupMenu();
	menuskb.AppendMenu(MF_STRING, ID_MENU_SKB_PC, "PC  键盘");
	menuskb.AppendMenu(MF_SEPARATOR);
	menuskb.AppendMenu(MF_STRING, ID_MENU_SKB_GL, "希腊字母");
	menuskb.AppendMenu(MF_SEPARATOR);
	menuskb.AppendMenu(MF_STRING, ID_MENU_SKB_RL, "俄文字母");
	menuskb.AppendMenu(MF_SEPARATOR);
	menuskb.AppendMenu(MF_STRING, ID_MENU_SKB_CSL, "拼  音");
	menuskb.AppendMenu(MF_SEPARATOR);
	menuskb.AppendMenu(MF_STRING, ID_MENU_SKB_PN, "注  音");
	menuskb.AppendMenu(MF_SEPARATOR);
	menuskb.AppendMenu(MF_STRING, ID_MENU_SKB_JH, "日文平假名");
	menuskb.AppendMenu(MF_SEPARATOR);
	menuskb.AppendMenu(MF_STRING, ID_MENU_SKB_JK, "日文片假名");
	menuskb.AppendMenu(MF_SEPARATOR);
	menuskb.AppendMenu(MF_STRING, ID_MENU_SKB_PT, "标点符号");
	menuskb.AppendMenu(MF_SEPARATOR);
	menuskb.AppendMenu(MF_STRING, ID_MENU_SKB_SN, "数字序号");
	menuskb.AppendMenu(MF_SEPARATOR);
	menuskb.AppendMenu(MF_STRING, ID_MENU_SKB_MN, "数学符号");
	menuskb.AppendMenu(MF_SEPARATOR);
	menuskb.AppendMenu(MF_STRING, ID_MENU_SKB_SP, "特殊符号");
	menuskb.AppendMenu(MF_SEPARATOR);
	menuskb.AppendMenu(MF_STRING, ID_MENU_SKB_CLOSE, "关闭软键盘");

	menuskb.TrackPopupMenu(TPM_RIGHTALIGN, pt.x, pt.y, this);
	
	CWnd::OnRButtonDown(nFlags, point);
}

void CSoftKeyboard::OnMenuSkb(int nID)
{
	// TODO: Add your command handler code here
	//LockInputWnd();

	switch(nID) {
	case ID_MENU_SKB_PC:
		ShowSoftKeyboard(TRUE, 0);
		break;
	case ID_MENU_SKB_GL:
		ShowSoftKeyboard(TRUE, 1);
		break;
	case ID_MENU_SKB_RL:
		ShowSoftKeyboard(TRUE, 2);
		break;
	case ID_MENU_SKB_CSL:
		ShowSoftKeyboard(TRUE, 3);
		break;
	case ID_MENU_SKB_PN:
		ShowSoftKeyboard(TRUE, 4);
		break;
	case ID_MENU_SKB_JH:
		ShowSoftKeyboard(TRUE, 5);
		break;
	case ID_MENU_SKB_JK:
		ShowSoftKeyboard(TRUE, 6);
		break;
	case ID_MENU_SKB_PT:
		ShowSoftKeyboard(TRUE, 7);
		break;
	case ID_MENU_SKB_SN:
		ShowSoftKeyboard(TRUE, 8);
		break;
	case ID_MENU_SKB_MN:
		ShowSoftKeyboard(TRUE, 9);
		break;
	case ID_MENU_SKB_SP:
		ShowSoftKeyboard(TRUE, 10);
		break;
	case ID_MENU_SKB_CLOSE:
		ShowSoftKeyboard(FALSE);
		break;
	default:
		break;
	}

	//ReleaseFocus();
	
	return;
}


⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?