These days, I need to use a touch screen in MFC projects. At the beginning, I originally called an external keyboard, but my superiors were reluctant and had to write a simple numeric keyboard myself. I will post the ideas and code below. You still have to create the keyboard interface yourself. I am posting the code as a reference.
The following is cpp
// CKeyBoard.cpp: implementation file // #include "stdafx.h" #include "Resource.h" //Just include this in other header files #include "CKeyBoard.h" #include "afxdialogex.h" // CKeyBoard dialog box 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, & amp;CKeyBoard::OnBnClickedOk) END_MESSAGE_MAP() // CKeyBoard message handler BOOL CKeyBoard::OnInitDialog() { CDialogEx::OnInitDialog(); // TODO: Add additional initialization here CFont* f; f = new CFont; f->CreateFont(36, // font height 0, // font width 0, // font tilt angle 0, // font tilt angle FW_BOLD, // font thickness FALSE, // Whether the font is italic FALSE, // Whether the font is underlined 0, // Whether the font has strikethrough ANSI_CHARSET, //Character set used by the font OUT_DEFAULT_PRECIS, // Specify how to select the appropriate font CLIP_DEFAULT_PRECIS, // Determine the precision of cropping DEFAULT_QUALITY, // How does it match the selected font? DEFAULT_PITCH | FF_SWISS, // Spacing flag and attribute flag _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 //Exception: OCX property page should return FALSE } void CKeyBoard::OnBnClickedBtnNum1() { // TODO: Add control notification handler code here 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: Add control notification handler code here 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: Add control notification handler code here 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: Add control notification handler code here 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: Add control notification handler code here 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: Add control notification handler code here 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: Add control notification handler code here 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: Add control notification handler code here 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: Add control notification handler code here 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: Add control notification handler code here 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: Add control notification handler code here 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: Add control notification handler code here CString str; GetDlgItemText(IDC_EDIT1, str); if (str.IsEmpty()) { } else { str.Append(_T(".")); SetDlgItemText(IDC_EDIT1, str); } } void CKeyBoard::OnBnClickedOk() { // TODO: Add control notification handler code here 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("")); }
In fact, the whole code is not complicated. It is simply string processing. Of course, the same is true for adding other keys on your keyboard.
Below is .h
#pragma once // CKeyBoard dialog box class CKeyBoard : public CDialogEx { DECLARE_DYNAMIC(CKeyBoard) public: CKeyBoard(CWnd* pParent = nullptr); // Standard constructor virtual ~CKeyBoard(); //Dialog data #ifdef AFX_DESIGN_TIME enum { IDD = IDD_KEYBOARD }; #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 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(); };
Keyboard picture interface
Then the simple keyboard is completed. The next step is how to call the keyboard.
Here you need to call a virtual function of MFC. PreTranslateMessage is a virtual function used to intercept messages. We can handle keyboard and mouse messages by overloading it. PreTranslateMessage is called before the message is sent to the TranslateMessage function, and most of the messages in this window pass through here. When you need to handle some messages before MFC, you often add code here.
What I call here is the left mouse button click. As for how to add this virtual function, there are many searches on the Internet, so I won’t post it here.
BOOL Your dialog class name::PreTranslateMessage(MSG* pMsg) { // TODO: Add specialized code here and/or call the base class 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; //The purpose of this section is to obtain the ID of the mouse click control. The class name of the control will be obtained through the ID, because the keyboard mainly acts on //Text edit box, so you only need to find the Edit class CWnd* pWnd = GetFocus(); nID = pWnd->GetDlgCtrlID(); wchar_t CClassName[255] = { 0 }; GetClassNameW(pWnd->GetSafeHwnd(), CClassName, 255);//Get the class name of the control, mainly Edit, Button, Static, etc. 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( & amp;rect); if (rect.PtInRect(pMsg->pt) & amp; & amp; m_NestSaveParm.IsOpenKeyboard) { //Get the rectangular area of the button CRectrect; GetDlgItem(nID)->GetWindowRect(rect); //dialog form size CRect rectDlg; GetWindowRect(rectDlg);//Get the size of the form //Keyboard window size CRectrectKey; KeyBoard->GetWindowRect(rectKey); //The following is where the keyboard is set. if (rect.right + rectKey.Width() > rectDlg.Width()) { //New keyboard KeyBoard->SetWindowPos(NULL, rect.left - rectKey.Width(), rect.top, 0, 0, SWP_NOSIZE); KeyBoard->ShowWindow(SW_NORMAL); targetID = nID; } else { //New keyboard KeyBoard->SetWindowPos(NULL, rect.right, rect.top, 0, 0, SWP_NOSIZE); KeyBoard->ShowWindow(SW_NORMAL); targetID = nID; } return TRUE; } } } return CDialogEx::PreTranslateMessage(pMsg); } void Your dialog class name::SetEditNum(int nID, CString text) { SetDlgItemText(nID, text); }
Then the basic process is roughly completed. The only thing left is to add the keyboard header file to the dialog box you need and initialize the keyboard.
//In the header file of the dialog box you call: CKeyBoard* KeyBoard; void SetEditNum(int nID, CString text); int targetID; //Initialize in the dialog box you called KeyBoard = NULL; KeyBoard = new CKeyBoard(); KeyBoard->Create(IDD_KEYBOARD, this); targetID = 0;
This is the idea, I hope it will be helpful to you.