这几天在MFC项目上需要用到触摸屏,在一开始本来是调用外部键盘的,但是上级不太愿意只好自己写一个简单的数字键盘使用。下面我会把写的思路和代码贴出来,键盘界面还是得自己创建,我贴代码是给个参考。
下面是cpp
// CKeyBoard.cpp: 实现文件
//
#include "stdafx.h"
#include "Resource.h" //其它头文件里包括这个即可
#include "CKeyBoard.h"
#include "afxdialogex.h"
// CKeyBoard 对话框
IMPLEMENT_DYNAMIC(CKeyBoard, CDialogEx)
CKeyBoard::CKeyBoard(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_KEYBOARD, pParent)
{
}
CKeyBoard::~CKeyBoard()
{
}
void CKeyBoard::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CKeyBoard, CDialogEx)
ON_BN_CLICKED(IDC_BTN_Num1, &CKeyBoard::OnBnClickedBtnNum1)
ON_BN_CLICKED(IDC_BTN_Num2, &CKeyBoard::OnBnClickedBtnNum2)
ON_BN_CLICKED(IDC_BTN_Num3, &CKeyBoard::OnBnClickedBtnNum3)
ON_BN_CLICKED(IDC_BTN_Num4, &CKeyBoard::OnBnClickedBtnNum4)
ON_BN_CLICKED(IDC_BTN_Num5, &CKeyBoard::OnBnClickedBtnNum5)
ON_BN_CLICKED(IDC_BTN_Num6, &CKeyBoard::OnBnClickedBtnNum6)
ON_BN_CLICKED(IDC_BTN_Num7, &CKeyBoard::OnBnClickedBtnNum7)
ON_BN_CLICKED(IDC_BTN_Num8, &CKeyBoard::OnBnClickedBtnNum8)
ON_BN_CLICKED(IDC_BTN_Num9, &CKeyBoard::OnBnClickedBtnNum9)
ON_BN_CLICKED(IDC_BTN_Num0, &CKeyBoard::OnBnClickedBtnNum0)
ON_BN_CLICKED(IDC_BTN_Del, &CKeyBoard::OnBnClickedBtnDel)
ON_BN_CLICKED(IDC_BTN_Point, &CKeyBoard::OnBnClickedBtnPoint)
ON_BN_CLICKED(IDOK, &CKeyBoard::OnBnClickedOk)
END_MESSAGE_MAP()
// CKeyBoard 消息处理程序
BOOL CKeyBoard::OnInitDialog()
{
CDialogEx::OnInitDialog();
// TODO: 在此添加额外的初始化
CFont* f;
f = new CFont;
f->CreateFont(36, // 字体高度
0, // 字体宽度
0, // 字体倾斜角
0, // 字体倾斜角
FW_BOLD, // 字体的粗细
FALSE, // 字体是否为斜体
FALSE, // 字体是否有下划线
0, // 字体是否有删除线
ANSI_CHARSET, // 字体使用的字符集
OUT_DEFAULT_PRECIS, // 指定如何选择合适的字体
CLIP_DEFAULT_PRECIS, // 确定裁剪的精度
DEFAULT_QUALITY, // 怎么样跟选择的字体相符合
DEFAULT_PITCH | FF_SWISS, // 间距标志和属性标志
_T("楷体"));
GetDlgItem(IDC_EDIT1)->SetFont(f);
GetDlgItem(IDC_BTN_Num1)->SetFont(f);
GetDlgItem(IDC_BTN_Num2)->SetFont(f);
GetDlgItem(IDC_BTN_Num3)->SetFont(f);
GetDlgItem(IDC_BTN_Num4)->SetFont(f);
GetDlgItem(IDC_BTN_Num5)->SetFont(f);
GetDlgItem(IDC_BTN_Num6)->SetFont(f);
GetDlgItem(IDC_BTN_Num7)->SetFont(f);
GetDlgItem(IDC_BTN_Num8)->SetFont(f);
GetDlgItem(IDC_BTN_Num9)->SetFont(f);
GetDlgItem(IDC_BTN_Num0)->SetFont(f);
GetDlgItem(IDC_BTN_Del)->SetFont(f);
GetDlgItem(IDC_BTN_Point)->SetFont(f);
SetWindowText(_T("KeyBoard"));
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
void CKeyBoard::OnBnClickedBtnNum1()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT1, str);
if (str.IsEmpty())
{
SetDlgItemText(IDC_EDIT1, _T("1"));
}
else
{
str.Append(_T("1"));
SetDlgItemText(IDC_EDIT1, str);
}
}
void CKeyBoard::OnBnClickedBtnNum2()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT1, str);
if (str.IsEmpty())
{
SetDlgItemText(IDC_EDIT1, _T("2"));
}
else
{
str.Append(_T("2"));
SetDlgItemText(IDC_EDIT1, str);
}
}
void CKeyBoard::OnBnClickedBtnNum3()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT1, str);
if (str.IsEmpty())
{
SetDlgItemText(IDC_EDIT1, _T("3"));
}
else
{
str.Append(_T("3"));
SetDlgItemText(IDC_EDIT1, str);
}
}
void CKeyBoard::OnBnClickedBtnNum4()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT1, str);
if (str.IsEmpty())
{
SetDlgItemText(IDC_EDIT1, _T("4"));
}
else
{
str.Append(_T("4"));
SetDlgItemText(IDC_EDIT1, str);
}
}
void CKeyBoard::OnBnClickedBtnNum5()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT1, str);
if (str.IsEmpty())
{
SetDlgItemText(IDC_EDIT1, _T("5"));
}
else
{
str.Append(_T("5"));
SetDlgItemText(IDC_EDIT1, str);
}
}
void CKeyBoard::OnBnClickedBtnNum6()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT1, str);
if (str.IsEmpty())
{
SetDlgItemText(IDC_EDIT1, _T("6"));
}
else
{
str.Append(_T("6"));
SetDlgItemText(IDC_EDIT1, str);
}
}
void CKeyBoard::OnBnClickedBtnNum7()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT1, str);
if (str.IsEmpty())
{
SetDlgItemText(IDC_EDIT1, _T("7"));
}
else
{
str.Append(_T("7"));
SetDlgItemText(IDC_EDIT1, str);
}
}
void CKeyBoard::OnBnClickedBtnNum8()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT1, str);
if (str.IsEmpty())
{
SetDlgItemText(IDC_EDIT1, _T("8"));
}
else
{
str.Append(_T("8"));
SetDlgItemText(IDC_EDIT1, str);
}
}
void CKeyBoard::OnBnClickedBtnNum9()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT1, str);
if (str.IsEmpty())
{
SetDlgItemText(IDC_EDIT1, _T("9"));
}
else
{
str.Append(_T("9"));
SetDlgItemText(IDC_EDIT1, str);
}
}
void CKeyBoard::OnBnClickedBtnNum0()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT1, str);
if (str.IsEmpty())
{
SetDlgItemText(IDC_EDIT1, _T("0"));
}
else
{
str.Append(_T("0"));
SetDlgItemText(IDC_EDIT1, str);
}
}
void CKeyBoard::OnBnClickedBtnDel()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT1, str);
if (str.IsEmpty())
{
}
else
{
string res = str.GetBuffer();
res.erase(res.end() - 1);
SetDlgItemText(IDC_EDIT1, res.c_str());
}
}
void CKeyBoard::OnBnClickedBtnPoint()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT1, str);
if (str.IsEmpty())
{
}
else
{
str.Append(_T("."));
SetDlgItemText(IDC_EDIT1, str);
}
}
void CKeyBoard::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
isConfirm = TRUE;
CDialogEx::OnOK();
}
CString CKeyBoard::GetEdit1Str()
{
CString str;
GetDlgItemText(IDC_EDIT1, str);
return str;
}
BOOL CKeyBoard::GetIsConfirm()
{
return isConfirm;
}
void CKeyBoard::SetIsConfirm(BOOL isconfirm)
{
isConfirm = isconfirm;
}
void CKeyBoard::RefrashEdit()
{
SetDlgItemText(IDC_EDIT1, _T(""));
}
其实整个代码并不复杂,简单点就是字符串处理,当然你键盘再加其它键同样道理。
下面是.h
#pragma once
// CKeyBoard 对话框
class CKeyBoard : public CDialogEx
{
DECLARE_DYNAMIC(CKeyBoard)
public:
CKeyBoard(CWnd* pParent = nullptr); // 标准构造函数
virtual ~CKeyBoard();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_KEYBOARD };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedBtnNum1();
afx_msg void OnBnClickedBtnNum2();
afx_msg void OnBnClickedBtnNum3();
afx_msg void OnBnClickedBtnNum4();
afx_msg void OnBnClickedBtnNum5();
afx_msg void OnBnClickedBtnNum6();
afx_msg void OnBnClickedBtnNum7();
afx_msg void OnBnClickedBtnNum8();
afx_msg void OnBnClickedBtnNum9();
afx_msg void OnBnClickedBtnNum0();
afx_msg void OnBnClickedBtnDel();
afx_msg void OnBnClickedBtnPoint();
afx_msg void OnBnClickedOk();
virtual BOOL OnInitDialog();
CString NumResult;
CString GetEdit1Str();
BOOL isConfirm;
BOOL GetIsConfirm();
void SetIsConfirm(BOOL isconfirm);
void RefrashEdit();
};
键盘的图片界面
那么简单的键盘就完成了。接下来就是如何调用键盘的问题。
这里需要调用MFC的一个虚函数。PreTranslateMessage是一个虚函数,用于截获消息。我们可以通过重载它来处理键盘和鼠标消息。PreTranslateMessage在消息送给TranslateMessage函数之前被调用,绝大多数本窗口的消息都要通过这里。当你需要在MFC之前处理某些消息时,常常要在这里添加代码。
这里我调用的是鼠标左键单击,至于这个虚函数如何添加,网上一搜大把,这里不再贴出来。
BOOL 你的对话框类名::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if (targetID != 0 || KeyBoard->GetEdit1Str() != "")
{
if (KeyBoard->GetIsConfirm())
{
SetEditNum(targetID, KeyBoard->GetEdit1Str());
KeyBoard->SetIsConfirm(FALSE);
KeyBoard->RefrashEdit();
}
}
if (pMsg->message == WM_LBUTTONDOWN)
{
int nID = 0;
//这一段的作用是为了获取鼠标点击控件的ID,将通过ID获取控件的类名,因为键盘主要作用于
//文本编辑框上,所以只需要找到Edit类就行
CWnd* pWnd = GetFocus();
nID = pWnd->GetDlgCtrlID();
wchar_t CClassName[255] = { 0 };
GetClassNameW(pWnd->GetSafeHwnd(), CClassName, 255);//得到控件的类名,主要有Edit,Button,Static等等
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, CClassName, -1, nullptr, 0, nullptr, nullptr);
std::string cClassName(bufferSize, 0);
WideCharToMultiByte(CP_UTF8, 0, CClassName, -1, &cClassName[0], bufferSize, nullptr, nullptr);
string comp(cClassName);
if (strcmp(cClassName.c_str(), "Edit") == 0)
{
CEdit* ptr = (CEdit*)GetDlgItem(nID);
CRect rect; ptr->GetWindowRect(&rect);
if (rect.PtInRect(pMsg->pt) && m_NestSaveParm.IsOpenKeyboard)
{
//获取按钮的矩形区域
CRect rect;
GetDlgItem(nID)->GetWindowRect(rect);
//对话框窗体大小
CRect rectDlg;
GetWindowRect(rectDlg);//获得窗体的大小
//键盘窗体大小
CRect rectKey;
KeyBoard->GetWindowRect(rectKey);
//下面这里就是设置键盘的位置了。
if (rect.right + rectKey.Width() > rectDlg.Width())
{
//新建键盘
KeyBoard->SetWindowPos(NULL, rect.left - rectKey.Width(), rect.top, 0, 0, SWP_NOSIZE);
KeyBoard->ShowWindow(SW_NORMAL);
targetID = nID;
}
else
{
//新建键盘
KeyBoard->SetWindowPos(NULL, rect.right, rect.top, 0, 0, SWP_NOSIZE);
KeyBoard->ShowWindow(SW_NORMAL);
targetID = nID;
}
return TRUE;
}
}
}
return CDialogEx::PreTranslateMessage(pMsg);
}
void 你的对话框类名::SetEditNum(int nID, CString text)
{
SetDlgItemText(nID, text);
}
那么大概的基本过程就这样完成了,剩下的就是在你所需要的对话框添加键盘头文件还有把键盘初始化,
//在你调用的对话框的头文件中:
CKeyBoard* KeyBoard;
void SetEditNum(int nID, CString text);
int targetID;
//在你调用的对话框进行初始化
KeyBoard = NULL;
KeyBoard = new CKeyBoard();
KeyBoard->Create(IDD_KEYBOARD, this);
targetID = 0;
思路是这么个思路,希望对你有所帮助。