在Pocket PC应用程序中,SIP提供的数字键盘不仅尺寸小,而且不易直接访问。此外,在输入数据之前能够进行一些计算总是有益的。针对这些问题,开发了数字键盘对话框,以帮助在Pocket PC应用程序中输入数字数据。
本文附带的示例应用程序使用两种不同的方法实现数字键盘:窗口控件和无窗口控件。
第一种方法使用常规的Windows控件,如按钮和静态标签来绘制键盘。与常规应用程序中可以找到的静态对话框资源不同,所有控件都是从一个动态创建的对话框资源中创建的。类CDialogTemplate
(见示例项目)是基于FlipCode的Dialog Template
代码,由Max McGuire编写。
第二种方法(上图所示)不使用窗口控件,而是使用从CSubWnd
派生的控件。这些控件位于一个CSubWndContainer
中,它是MFC的CWnd
,负责将所有传入的(和相关的)Windows消息分派到包含的CSubWnd
对象。每个CSubWnd
派生的控件负责绘制自己的矩形并处理点击事件。以下是CSubWndContainer
如何分派绘制请求的:
void CSubWndContainer::OnPaint() {
CPaintDC dc(this);
CSubWndCont::iterator pos, end = m_cont.end();
HFONT hFontOld;
hFontOld = (HFONT)::SelectObject(dc, m_hFont);
// Paint all sub windows
for (pos = m_cont.begin(); pos != end; ++pos) {
if (dc.RectVisible(&(*pos)->GetRect())) {
(*pos)->Paint(dc);
}
}
::SelectObject(dc, hFontOld);
}
为了简化点击处理(并减少虚拟函数的数量),所有与点击相关的Windows消息都分派到一个CSubWnd
函数:
void CSubWndContainer::OnLButtonDown(UINT nFlags, CPoint point) {
m_pSubWnd = SubWndFromPoint(point);
if (m_pSubWnd) {
m_pSubWnd->Click(CLICK_DOWN, point);
}
}
void CSubWndContainer::OnLButtonUp(UINT nFlags, CPoint point) {
if (m_pSubWnd) {
m_pSubWnd->Click(CLICK_UP, point);
}
}
void CSubWndContainer::OnLButtonDblClk(UINT nFlags, CPoint point) {
m_pSubWnd = SubWndFromPoint(point);
if (m_pSubWnd) {
m_pSubWnd->Click(CLICK_DOWN | CLICK_DOUBLE, point);
}
}
示例代码使用了两个CSubWnd
派生类:CSubStatic
用于实现最顶部的静态控件,CSubButton
实现所有键盘按钮。注意这个类如何绕过Windows内置的双击处理:
void CSubButton::Click(DWORD dwClick, POINT pt) {
bool bOn = (dwClick & CLICK_DOWN);
ASSERT(m_pWnd);
// Make a double click work right
if (dwClick & CLICK_DOUBLE) {
Click(CLICK_UP, pt);
}
if (m_rc.PtInRect(pt)) {
// Inside this button
if (IsActive() && !bOn) {
CWnd* pParent = m_pWnd->GetParent();
if (pParent) {
pParent->SendMessage(WM_COMMAND, m_nID, (LPARAM)m_pWnd->GetSafeHwnd());
}
}
Activate(bOn);
} else {
// Outside this button
if (IsActive()) {
Activate(false);
}
}
}
数字键盘的实现相当直接。正在编辑的值始终是一个可以转换为int
或CURRENCY
的double
。它以客户端选择的格式显示:
enum Format {
fmtInteger, // An integer
fmtNumber, // Locale number
fmtCurrency // Locale currency
};
要使用此类,请创建一个CNumPadDlg
实例,使用适当的构造函数参数:
CNumPadDlg(enum Format format, BOOL bTemplate, CWnd* pParent = NULL);
在调用对象的DoModal
函数之前,使用以下方法之一设置键盘值:
void SetIntValue(int nVal);
void SetDblValue(double dblVal);
void SetCurValue(CURRENCY cyVal);
int GetIntValue();
double GetDblValue();
CURRENCY GetCurValue();