C++小键盘(一)

xiaoxiao2021-02-28  63

实现这样的小键盘。

首先,对话框中有这样的一个带 图标按钮的edit:

实现这样一个带图标按钮的edit的效果,可参考 郭延明 博客中自绘类 CSkinEdit的实现。

我们想实现的效果是:点击icon时弹出小键盘,点击键盘外的别处或者点击键盘上的关闭按钮时,键盘消失。 涉及到三个窗口:edit,edit所在的dlg,小键盘。 处理过程: edit的OnNcLButtonUp中发给 dlg 自定义的键盘消息UM_NUMKEYBOARDABC, dlg中响应自定义消息UM_NUMKEYBOARDABC,调出小键盘。OnNcLButtonUp中的代码: void CSkinEdit::OnNcLButtonUp(UINT nHitTest, CPoint point) { CWnd *pWnd = GetParent(); if ( pWnd != NULL && pWnd->GetSafeHwnd() != NULL ) { CRect rcIcon; CPoint pt; GetCursorPos(&pt); GetIconRect(rcIcon); if (PtInRect(&rcIcon, pt)) { pWnd->PostMessage(WM_COMMAND, GetDlgCtrlID()); if (0 == keyBoardState) ::SendMessage(GetParent()->m_hWnd, UM_NUMKEYBOARDABC, (WPARAM)this, (LPARAM)&CPoint(rcIcon.right - 200, rcIcon.bottom)); else if (1 == keyBoardState) ::SendMessage(GetParent()->m_hWnd, UM_NUMKEYBOARD, (WPARAM)this, (LPARAM)&CPoint(rcIcon.right, rcIcon.bottom)); else if (2 == keyBoardState) ::SendMessage(GetParent()->m_hWnd, UM_NUMCAR, (WPARAM)this, (LPARAM)&CPoint(rcIcon.right, rcIcon.bottom)); } } __super::OnNcLButtonUp(nHitTest, point); }

说明:因为程序中还有别的小键盘,这里是UM_NUMKEYBOARDABC消息对应的小键盘。

在dlg中,对消息的处理的代码(此处调出小键盘):

LRESULT CmyAddDlg::NumABCKeyBoard(WPARAM wParam, LPARAM lParam) { CEdit *pe = (CEdit*)wParam; CPoint pt = *((CPoint*)lParam); NumKeyABC(pe, pt, pabcdlg); return 0; } 下面是小键盘的实现: CmyNumABCDlg.h中 写个CmyNumABCDlg对话框类;还有 void NumKeyABC(CEdit* pEdit, const CPoint& pt, CmyNumABCDlg* pdlg)这个函数。 //参数1:小键盘所属的edit, //参数2:小键盘弹出位置 //参数3:小键盘窗口 void NumKeyABC(CEdit* pEdit, const CPoint& pt, CmyNumABCDlg* pdlg) { if (NULL == pdlg) { pdlg = new CmyNumABCDlg(pEdit); pdlg->Create(IDD_DIALOG_NUMABC, NULL); pdlg->ShowWindow(SW_SHOW); } pdlg->SetEdit(pEdit); pdlg->SetWindowPos(NULL, pt.x, pt.y, 0, 0, SWP_NOSIZE); }

小键盘类: 因为是CmyNumABCDlg对象是在堆分配空间(pdlg = new CmyNumABCDlg(pEdit);),所以一定要在PostNcDestroy中 有 delete this;这句。

关闭窗口是 在 void Destroy()中调DestroyWindow()销毁窗口这句。

实现点击 键盘外的别处时,键盘销毁,是通过响应WM_ACTIVE消息,下面这段代码,其中isDestroyed初始为FALSE:

void CmyNumABCDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) { CSkinDialog::OnActivate(nState, pWndOther, bMinimized); if (FALSE == isDestroyed) { if (WA_INACTIVE == nState) { isDestroyed = TRUE; Destroy(); } } }

下面是响应小键盘按钮,获取按钮文本信息,给edit发的WM_CHAR消息,达到操作edit的效果

BOOL CmyNumABCDlg::OnCommand(WPARAM wParam, LPARAM lParam) { CString str; GetDlgItem(LOWORD(wParam))->GetWindowText(str); UINT ascid = str[0]; if ((ascid >= 48 && ascid <= 57) || (ascid >= 65 && ascid <= 90) || (ascid >= 97 && ascid <= 122)) SendCharMsg(LOWORD(wParam)); switch (LOWORD(wParam)) { case IDC_BTN_KGANG: case IDC_BTN_KBACK: case IDC_BTN_KPOT: case IDC_BTN_KCLOSE: case IDC_BTN_KCHANGE: SendCharMsg(LOWORD(wParam)); default: break; } return CSkinDialog::OnCommand(wParam, lParam); } void CmyNumABCDlg::SendCharMsg(const UINT& uid) { if (NULL == pEdit) return; CString str; GetDlgItem(uid)->GetWindowText(str); UINT ascid = 0; if (str != _T("关闭") && str != _T("←") && str != _T("大写/小写")) { for (int i = 0; i < str.GetLength(); i++) { ascid = str[i]; ::PostMessage(pEdit->GetSafeHwnd(), WM_CHAR, ascid, 0); } } else if (_T("←") == str) { ::PostMessage(pEdit->GetSafeHwnd(), WM_CHAR, 8, 0); } else if (_T("大写/小写") == str) { int add = -32;//原本是小写 UINT ad = 0; CString str; GetDlgItem(1327)->GetWindowText(str); ad = str[0]; if (65 == ad) add = 32; else if (97 == ad) add = -32; CString changed; for (UINT id = 1327; id <= 1351; id++) { changed.Format(_T("%c"),ad+add); GetDlgItem(id)->SetWindowTextW(changed); ad++; } } }

上面的 for (UINT id = 1327; id <= 1351; id++) 对字母 大小写切换为了循环方便,使用的是连续的ID号。

–欢迎指正和补充,谢谢!–

转载请注明原文地址: https://www.6miu.com/read-70796.html

最新回复(0)