Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Pocket PC Numeric Key Pad

0.00/5 (No votes)
3 Sep 2005 2  
An easier way to accept numeric input on the Pocket PC.

Sample Image - ppc_numpad.jpg

Introduction

Numeric input on the Pocket PC has always been a hassle. The numeric keyboard provided by the SIP is too small and not directly accessible. Plus, it's always nice to be able to perform some calculations before entering data.

With these issues in mind, I developed the numeric key pad dialog to help entering numeric data in Pocket PC applications.

Implementation

The sample application I include in this article implements the numeric key pad using two different approaches: window controls and windowless controls.

The first approach uses regular Windows controls such as buttons and static labels to draw the keypad. Instead of a static dialog resource that can be found in regular applications, all controls are created from a dynamically created dialog resource. The class CDialogTemplate (see sample project) is based on FlipCode's Dialog Template code by Max McGuire.

The second approach (depicted on the picture above) doesn't use window controls, but objects that derive from CSubWnd. These objects live on a CSubWndContainer that is an MFC's CWnd and is responsible for dispatching all incoming (and relevant) Windows messages to the contained CSubWnd objects. Each CSubWnd-derived object is responsible for painting its own rectangle and processing clicks. Here's how CSubWndContainer dispatches the paint requests:

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);
}

To make click handling easier (and to reduce the number of virtual functions), all click-related Windows messages are dispatched to a single CSubWnd function:

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);
}

The sample code uses two CSubWnd-derived classes: CSubStatic used to implement the topmost static control and CSubButton that implements all the keypad buttons. Note how this class has to work around the Windows built-in double-click processing:

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);
    }
}

The numeric keypad implementation is quite straightforward. The value being edited is always a double that can be converted to an int or a CURRENCY. It is displayed in a format that the client chooses:

enum Format
{
    fmtInteger,   // An integer
    fmtNumber,    // Locale number
    fmtCurrency   // Locale currency
};

To consume this class, create an instance of CNumPadDlg using the appropriate constructor arguments:

CNumPadDlg(enum Format format, BOOL bTemplate, CWnd* pParent = NULL);

Before calling the object's DoModal function, set the keypad value using one of:

void SetIntValue(int nVal);
void SetDblValue(double dblVal);
void SetCurValue(CURRENCY cyVal);

Retrieve the keypad value using the corresponding get function:

int      GetIntValue();
double   GetDblValue();
CURRENCY GetCurValue();

And that's it!

Final Notes

This code uses Giuseppe Govi's STL implementation. It's a bit minimal but sufficient for most Pocket PC applications (and is compatible with eVC3).

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here