www.pudn.com > NumPanel.rar > np_orig.cpp


//====================================================================== 
// NumPanel - An IM window 
// 
// Written for the book Programming Windows CE 
// Copyright (C) 2003 Douglas Boling 
//====================================================================== 
#include                  // For all that Windows stuff 
#define COBJMACROS 
#include                      // SIP includes 
#include                    // Keyboard flag includes 
 
#include "NumPanel.h"                // Includes for this window 
extern "C" HINSTANCE hInst; 
// 
// Local variables for number panel  
// 
TCHAR g_tcBtnChar[] = { 
        TEXT('1'), TEXT('2'), TEXT('3'), TEXT('-'), TEXT('*'), 
        TEXT('4'), TEXT('5'), TEXT('6'), TEXT('+'), TEXT('/'), 
        TEXT('7'), TEXT('8'), TEXT('9'), TEXT('0'), TEXT('='), 
}; 
UINT g_BtnVChars[] = { 
        '1', '2', '3', VK_HYPHEN, VK_MULTIPLY,  
        '4', '5', '6', VK_ADD, VK_SLASH, 
        '7', '8', '9', '0', VK_EQUAL, 
}; 
 
// Message dispatch table for SipWindowProc 
const struct decodeUINT SipMessages[] = { 
    WM_CREATE, DoCreateSip, 
    WM_PAINT, DoPaintSip, 
    MYMSG_METHCALL, DoSetSipInfo, 
    WM_LBUTTONDOWN, DoMouseSip, 
    WM_MOUSEMOVE, DoMouseSip, 
    WM_LBUTTONUP, DoMouseSip, 
    WM_LBUTTONDBLCLK, DoMouseSip, 
    WM_DESTROY, DoDestroySip, 
}; 
//---------------------------------------------------------------------- 
// CreateIMWindow - Create the input method window. 
// 
HWND CreateIMWindow (HWND hwndParent) { 
    WNDCLASS wc; 
    RECT rect; 
    HWND hwnd; 
    // Register sip window class. 
    memset (&wc, 0, sizeof (wc)); 
    wc.style = CS_DBLCLKS; 
    wc.lpfnWndProc = NPWndProc;               // Callback function 
    wc.hInstance = hInst;                     // Owner handle 
    wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); 
    wc.lpszClassName = MYSIPCLS;              // Window class name 
    if (RegisterClass (&wc) == 0) return 0; 
 
    // Create SIP window.   
    GetClientRect (hwndParent, &rect); 
    hwnd = CreateWindowEx (0, MYSIPCLS, TEXT(""),  
                  WS_VISIBLE | WS_CHILD | WS_BORDER, rect.left,  
                  rect.top, rect.right - rect.left,  
                  rect.bottom - rect.top, hwndParent, (HMENU)100,  
                  hInst, 0); 
    if (!IsWindow (hwnd)) 
        return 0; 
    return hwnd; 
} 
//---------------------------------------------------------------------- 
// DestroyIMWindow - Destroy the input method window. 
// 
int DestroyIMWindow (HWND hwnd) { 
    // Clean up since we're about to be unloaded. 
    DestroyWindow (hwnd); 
    UnregisterClass (MYSIPCLS, hInst); 
    return 0; 
} 
 
//====================================================================== 
// NPWndProc - Window procedure for SIP  
// 
LRESULT CALLBACK NPWndProc (HWND hWnd, UINT wMsg, WPARAM wParam,  
                            LPARAM lParam) { 
    INT  i; 
    // Call routine to handle control message. 
    for (i = 0; i < dim(SipMessages); i++) { 
        if (wMsg == SipMessages[i].Code) 
            return (*SipMessages[i].Fxn)(hWnd, wMsg, wParam, lParam); 
    } 
    return DefWindowProc (hWnd, wMsg, wParam, lParam); 
} 
//---------------------------------------------------------------------- 
// DoCreateSip - Process WM_CREATE message for window. 
// 
LRESULT CALLBACK DoCreateSip (HWND hWnd, UINT wMsg, WPARAM wParam,  
                              LPARAM lParam) { 
    LPSIPWNDSTRUCT pWndData; 
    // Allocate a data structure for the sip keyboard window.     
    pWndData = (LPSIPWNDSTRUCT)LocalAlloc (LPTR, sizeof (SIPWNDSTRUCT)); 
    if (!pWndData) { 
        DestroyWindow (hWnd); 
        return 0; 
    } 
    memset (pWndData, 0, sizeof (SIPWNDSTRUCT)); 
    GetWindowRect (GetParent (hWnd), &pWndData->rectDocked); 
    pWndData->rectLast.left = -1; 
    SetWindowLong (hWnd, GWL_USERDATA, (INT)pWndData); 
    return 0; 
} 
//---------------------------------------------------------------------- 
// DoSetSipInfo - Process set information user message for window. 
// 
LRESULT CALLBACK DoSetSipInfo (HWND hWnd, UINT wMsg, WPARAM wParam,  
                               LPARAM lParam) { 
    LPSIPWNDSTRUCT pWndData; 
    RECT rect; 
     
    pWndData = (LPSIPWNDSTRUCT)GetWindowLong (hWnd, GWL_USERDATA); 
    switch (wParam) { 
    // Called when RegisterCallback method called 
    case MSGCODE_REGCALLBACK: 
        pWndData->pIMCallback = (IIMCallback *)lParam; 
        break; 
    // Called when GetInfo method called 
    case MSGCODE_GETINFO: 
        pWndData->imi = *(IMINFO *)lParam; 
        break; 
    // Called when ReceiveSipInfo method called 
    case MSGCODE_SETINFO: 
        GetClientRect (GetParent(hWnd), &rect); 
        MoveWindow (hWnd, 0, 0, rect.right - rect.left, 
                    rect.bottom - rect.top, TRUE); 
        break; 
    // Called when RegisterCallback2 method called 
    case MSGCODE_REGCALLBACK2: 
        pWndData->pIMCallback2 = (IIMCallback2 *)lParam; 
        break; 
    } 
    return 0; 
} 
//---------------------------------------------------------------------- 
// DoPaintSip - Process WM_PAINT message for window. 
// 
LRESULT CALLBACK DoPaintSip (HWND hWnd, UINT wMsg, WPARAM wParam,  
                             LPARAM lParam) { 
    HDC hdc; 
    HBRUSH hOld; 
    PAINTSTRUCT ps; 
    RECT rect, rectBtn; 
    INT i, j, k, x, y, cx, cy, cxBtn, cyBtn; 
    LPSIPWNDSTRUCT pWndData; 
 
    pWndData = (LPSIPWNDSTRUCT)GetWindowLong (hWnd, GWL_USERDATA); 
 
    hdc = BeginPaint (hWnd, &ps); 
    GetClientRect (hWnd, &rect); 
 
    cx = (rect.right - rect.left - 3 - GRIPWIDTH) / CXBTNS; 
    cy = (rect.bottom - rect.top - 3) / CYBTNS; 
    cxBtn = cx - 3; 
    cyBtn = cy - 3; 
 
    // Select a brush for the gripper. 
    hOld = (HBRUSH)SelectObject (hdc, GetStockObject (GRAY_BRUSH)); 
    Rectangle (hdc, rect.left, rect.top, rect.left + GRIPWIDTH,  
               rect.bottom); 
    SelectObject (hdc, hOld); 
 
    k = 0; 
    y = 3; 
    for (i = 0; i < CYBTNS; i++) { 
        x = 3 + GRIPWIDTH; 
        for (j = 0; j < CXBTNS; j++) { 
            SetRect (&rectBtn, x, y, x + cxBtn, y + cyBtn); 
            DrawButton (hdc, &rectBtn, &g_tcBtnChar[k],  
                        pWndData->dwBtnDnFlags & (1 << k)); 
            k++; 
            x += cx; 
        } 
        y += cy; 
    } 
    EndPaint (hWnd, &ps); 
    return 0; 
} 
//---------------------------------------------------------------------- 
// ComputeFloatRect - Compute the location and size of the drag rect. 
// 
int ComputeFloatRect (HWND hwnd, LPSIPWNDSTRUCT pWndData, POINT pt, 
                      RECT *prectOut) { 
 
    pt.x -= pWndData->ptMovBasis.x; 
    pt.y -= pWndData->ptMovBasis.y; 
    prectOut->right = FLOATWIDTH; 
    prectOut->bottom = FLOATHEIGHT; 
    prectOut->left = pt.x; 
    prectOut->top = pt.y; 
    prectOut->right += pt.x; 
    prectOut->bottom += pt.y; 
    return 0; 
} 
//---------------------------------------------------------------------- 
// DrawFloatRect - Draw a drag rectangle by XORing the desktop. 
// 
int DrawFloatRect (HWND hWnd, RECT rect) { 
    HDC hdc; 
    HBRUSH hbrOld; 
    HPEN hpenOld; 
    int nOldMode; 
    // Get the DC. Set ROP, brush, and pen. 
    hdc = GetDC (NULL); 
    nOldMode = SetROP2 (hdc, R2_NOT); 
    hbrOld = (HBRUSH)SelectObject (hdc, GetStockObject (NULL_BRUSH)); 
    hpenOld = (HPEN)SelectObject (hdc, GetStockObject (BLACK_PEN)); 
 
    Rectangle (hdc, rect.left, rect.top, rect.right, rect.bottom); 
    SelectObject (hdc, hbrOld); 
    SelectObject (hdc, hpenOld); 
    SetROP2 (hdc, nOldMode); 
    ReleaseDC (NULL, hdc); 
    return 0; 
} 
//---------------------------------------------------------------------- 
// HandleGripper - Handles mouse messages over gripper bar 
// 
LRESULT HandleGripper (HWND hWnd, LPSIPWNDSTRUCT pWndData, UINT wMsg,  
                       LPARAM lParam) { 
    POINT pt; 
    RECT rectFloat; 
 
    pt.x = (short)LOWORD(lParam); 
    pt.y = (short)HIWORD(lParam); 
 
    switch (wMsg) { 
    case WM_LBUTTONDOWN: 
        if (pt.x > GRIPWIDTH+3) 
            return 0; 
        SetCapture (hWnd); 
        pWndData->fMoving = TRUE; 
        pWndData->ptMovBasis = pt; 
        ClientToScreen (hWnd, &pt); 
        pWndData->ptMovStart = pt; 
        ShowWindow (GetParent(hWnd), SW_HIDE); 
        break; 
 
    case WM_MOUSEMOVE: 
        if (!pWndData->fMoving) 
            return 0; 
        ClientToScreen (hWnd, &pt); 
        ComputeFloatRect (hWnd, pWndData, pt, &rectFloat); 
        // Erase old drag rectangle. 
        if (pWndData->rectLast.left != -1) 
            DrawFloatRect (hWnd, pWndData->rectLast); 
        // Draw new drag rectangle. 
        DrawFloatRect (hWnd, rectFloat); 
        pWndData->rectLast = rectFloat; 
        break; 
    case WM_LBUTTONUP: 
        if (!pWndData->fMoving) 
            return 0; 
        // Free up dragging stuff. 
        ReleaseCapture(); 
        pWndData->fMoving = FALSE; 
        ClientToScreen (hWnd, &pt); 
        // Erase last drag rectangle. 
        ComputeFloatRect (hWnd, pWndData, pt, &rectFloat); 
        if (pWndData->rectLast.left != -1) 
            DrawFloatRect (hWnd, pWndData->rectLast); 
        pWndData->rectLast.left = -1; 
        ShowWindow (GetParent(hWnd), SW_SHOW); 
        // Don't move SIP if really small move. 
        if ((abs (pWndData->ptMovStart.x - pt.x) < 3) && 
            (abs (pWndData->ptMovStart.y - pt.y) < 3)) 
            break; 
        // Tell the Input Manager about the move. 
        pWndData->imi.rcSipRect = rectFloat; 
        pWndData->imi.fdwFlags &= ~SIPF_DOCKED; 
        pWndData->imi.fdwFlags |= SIPF_ON; 
        pWndData->pIMCallback->SetImInfo(&pWndData->imi); 
        break; 
 
    case WM_LBUTTONDBLCLK: 
        if (pt.x > GRIPWIDTH+3) 
            return 0; 
        ReleaseCapture(); 
        pWndData->fMoving = FALSE; 
        // Embedded SIP manager doesn't use SIPF_DOCKED so only use on PPC. 
#if defined(WIN32_PLATFORM_PSPC) 
        pWndData->imi.fdwFlags |= (SIPF_DOCKED | SIPF_ON); 
#endif 
        pWndData->imi.rcSipRect = pWndData->rectDocked; 
        pWndData->pIMCallback->SetImInfo(&pWndData->imi); 
        break; 
    } 
    pWndData->dwBtnDnFlags = 0;   // If we moved, no buttons down. 
    return 1; 
} 
//---------------------------------------------------------------------- 
// DoMouseSip - Process mouse button messages for window. WM_LBUTTONDOWN 
// 
LRESULT CALLBACK DoMouseSip (HWND hWnd, UINT wMsg, WPARAM wParam,  
                             LPARAM lParam) { 
    RECT rect; 
    INT i, x, y, cx, cy; 
    UINT nChar, unShiftFlags = 0; 
    DWORD BtnDnFlags; 
    LPSIPWNDSTRUCT pWndData; 
    pWndData = (LPSIPWNDSTRUCT)GetWindowLong (hWnd, GWL_USERDATA); 
 
    // See if moving gripper or gripper tap. 
    if (HandleGripper (hWnd, pWndData, wMsg, lParam))  
        return 0; 
 
    // Compute the button grid. 
    GetClientRect (hWnd, &rect); 
    cx = (rect.right - rect.left - 3 - GRIPWIDTH) / CXBTNS; 
    cy = (rect.bottom - rect.top - 3) / CYBTNS; 
    x = ((LOWORD (lParam)-3-GRIPWIDTH) / cx); 
    y = ((HIWORD (lParam)-3) / cy); 
    i = (y * CXBTNS) + x;    // i now contains btn index. 
 
    // Do small amount of message-specific processing. 
    switch (wMsg) { 
    case WM_LBUTTONDOWN: 
        SetCapture (hWnd); 
        // Fall through to WM_MOUSEMOVE case. 
    case WM_MOUSEMOVE: 
        BtnDnFlags = 1 << i; 
        break; 
    case WM_LBUTTONDBLCLK: 
    case WM_LBUTTONUP: 
        if (pWndData->dwBtnDnFlags) 
            ReleaseCapture(); 
        BtnDnFlags = 0; 
        nChar = g_tcBtnChar[i]; 
        pWndData->pIMCallback->SendCharEvents(g_BtnVChars[i], 
                              KeyStateDownFlag, 1, &nShiftFlags, &nChar); 
        break; 
    }  
    // Decide how to repaint wnd. If only 1 btn changed, just  
    // invalidate that rect. Otherwise, invalidate entire wnd. 
    if ((wMsg == WM_MOUSEMOVE) && (BtnDnFlags !=pWndData->dwBtnDnFlags)) 
        InvalidateRect (hWnd, NULL, FALSE); 
    else { 
        i = 3+GRIPWIDTH;   // Compensate for the gripper on left side. 
        SetRect (&rect, x*cx+i, y*cy, (x+1)*cx+i, (y+1)*cy); 
        InvalidateRect (hWnd, &rect, FALSE); 
    } 
    pWndData->dwBtnDnFlags = BtnDnFlags; 
    return 0; 
} 
//---------------------------------------------------------------------- 
// DoDestroySip - Process WM_DESTROY message for window. 
// 
LRESULT CALLBACK DoDestroySip (HWND hWnd, UINT wMsg, WPARAM wParam,  
                               LPARAM lParam) { 
    LPSIPWNDSTRUCT pWndData; 
     
    pWndData = (LPSIPWNDSTRUCT)GetWindowLong (hWnd, GWL_USERDATA); 
    LocalFree (pWndData); 
    return 0; 
} 
//--------------------------------------------------------------------- 
// DrawButton - Draws a button 
// 
INT DrawButton (HDC hdc, RECT *prect, LPTSTR pChar, BOOL fPressed) { 
 
    if (!fPressed) { 
        SelectObject (hdc, GetStockObject (BLACK_PEN)); 
        SelectObject (hdc, GetStockObject (WHITE_BRUSH)); 
        SetBkColor (hdc, RGB (255, 255, 255)); 
        SetTextColor (hdc, RGB (0, 0, 0)); 
    } else { 
        SelectObject (hdc, GetStockObject (BLACK_BRUSH)); 
        SelectObject (hdc, GetStockObject (WHITE_PEN)); 
        SetTextColor (hdc, RGB (255, 255, 255)); 
        SetBkColor (hdc, RGB (0, 0, 0)); 
    } 
    Rectangle (hdc, prect->left, prect->top, prect->right,  
               prect->bottom); 
    Rectangle (hdc, prect->left+1, prect->top+1, prect->right+1,  
               prect->bottom+1); 
    DrawText (hdc, pChar, 1, prect, DT_CENTER|DT_VCENTER|DT_SINGLELINE); 
    return 0; 
}