/**************************************************************************\ * Module Name: sftkbdc1.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * Softkeyboard support for Simplified Chinese * * History: * 03-Jan-1996 wkwok Ported from Win95 \**************************************************************************/ #include "precomp.h" #pragma hdrstop #include "softkbd.h" // Virtual Key for Letter Buttons CONST BYTE SKC1VirtKey[BUTTON_NUM_C1] = { VK_OEM_3, '1', '2', '3', '4', '5', '6','7', '8', '9', '0', VK_OEM_MINUS, VK_OEM_EQUAL, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', VK_OEM_LBRACKET, VK_OEM_RBRACKET, VK_OEM_BSLASH, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', VK_OEM_SEMICLN, VK_OEM_QUOTE, 'Z', 'X', 'C', 'V', 'B', 'N', 'M', VK_OEM_COMMA, VK_OEM_PERIOD, VK_OEM_SLASH, VK_BACK, VK_TAB, VK_CAPITAL, VK_RETURN, VK_SHIFT, VK_INSERT, VK_DELETE, VK_SPACE, VK_ESCAPE }; POINT gptButtonPos[BUTTON_NUM_C1]; // button point array, in the client area BOOL gfSoftKbdC1Init = FALSE; // init flag /**********************************************************************\ * InitSKC1ButtonPos -- init gptButtonPos * \**********************************************************************/ VOID InitSKC1ButtonPos() { int i, x, y; // init the first row y = 0; for (i=0, x=X_ROW_LETTER_C1; i < COL_LETTER_C1; i++, x += W_LETTER_BTN_C1) { gptButtonPos[i].x = x; gptButtonPos[i].y = y; } gptButtonPos[BACKSP_TYPE_C1].x = x; gptButtonPos[BACKSP_TYPE_C1].y = y; // init the second row y += H_LETTER_BTN_C1; x = 0; gptButtonPos[TAB_TYPE_C1].x = x; gptButtonPos[TAB_TYPE_C1].y = y; for (i=0, x=X_ROW2_LETTER_C1; i < COL2_LETTER_C1; i++, x += W_LETTER_BTN_C1) { gptButtonPos[i + COL_LETTER_C1].x = x; gptButtonPos[i + COL_LETTER_C1].y = y; } // init the third row y += H_LETTER_BTN_C1; x = 0; gptButtonPos[CAPS_TYPE_C1].x = x; gptButtonPos[CAPS_TYPE_C1].y = y; for (i=0, x=X_ROW3_LETTER_C1; i < COL3_LETTER_C1; i++, x += W_LETTER_BTN_C1) { gptButtonPos[i + COL_LETTER_C1 + COL2_LETTER_C1].x = x; gptButtonPos[i + COL_LETTER_C1 + COL2_LETTER_C1].y = y; } gptButtonPos[ENTER_TYPE_C1].x = x; gptButtonPos[ENTER_TYPE_C1].y = y; // init the forth row y += H_LETTER_BTN_C1; x = 0; gptButtonPos[SHIFT_TYPE_C1].x = x; gptButtonPos[SHIFT_TYPE_C1].y = y; for (i=0, x=X_ROW4_LETTER_C1; i < COL4_LETTER_C1; i++, x += W_LETTER_BTN_C1) { gptButtonPos[i + COL_LETTER_C1 + COL2_LETTER_C1 + COL3_LETTER_C1].x = x; gptButtonPos[i + COL_LETTER_C1 + COL2_LETTER_C1 + COL3_LETTER_C1].y = y; } // init the bottom row y += H_LETTER_BTN_C1; x = 0; gptButtonPos[INS_TYPE_C1].x = x; gptButtonPos[INS_TYPE_C1].y = y; x = X_DEL_C1; gptButtonPos[DEL_TYPE_C1].x = x; gptButtonPos[DEL_TYPE_C1].y = y; x += W_DEL_C1 + 2 * BORDER_C1; gptButtonPos[SPACE_TYPE_C1].x = x; gptButtonPos[SPACE_TYPE_C1].y = y; x = X_ESC_C1; gptButtonPos[ESC_TYPE_C1].x = x; gptButtonPos[ESC_TYPE_C1].y = y; return; } /**********************************************************************\ * SKC1DrawConvexRect --- draw button * * (x1,y1) x2-1 * +----3------>^ * |+----3-----||y1+1 * || || * 33 1 42 * || || * |V || * |<----4-----+| * y2-1 ------2------+ * (x2,y2) * * 1 - light gray * 2 - black * 3 - white * 4 - dark gray * \**********************************************************************/ VOID SKC1DrawConvexRect( HDC hDC, int x, int y, int nWidth, int nHeight) { // paint background SelectObject(hDC, GetStockObject(LTGRAY_BRUSH)); SelectObject(hDC, GetStockObject(BLACK_PEN)); Rectangle(hDC, x, y, x + nWidth, y + nHeight); // paint white border SelectObject(hDC, GetStockObject(WHITE_BRUSH)); PatBlt(hDC, x, y + nHeight - 1, BORDER_C1, -nHeight + 1, PATCOPY); PatBlt(hDC, x, y, nWidth - 1 , BORDER_C1, PATCOPY); // paint dark gray border SelectObject(hDC, GetStockObject(GRAY_BRUSH)); PatBlt(hDC, x + 1, y + nHeight -1, nWidth - BORDER_C1, -1, PATCOPY); PatBlt(hDC, x + nWidth - 1, y + nHeight - 1, -1, -nHeight + BORDER_C1, PATCOPY); return; } /**********************************************************************\ * SKC1InvertButton --- Invert Button * \**********************************************************************/ VOID SKC1InvertButton( HDC hDC, int uKeyIndex) { int nWidth, nHeight; if (uKeyIndex < 0) return; if (uKeyIndex < LETTER_NUM_C1) { nWidth = W_LETTER_BTN_C1; nHeight = H_LETTER_BTN_C1; } else { switch (uKeyIndex) { case BACKSP_TYPE_C1: nWidth = W_BACKSP_C1 + 2 * BORDER_C1; nHeight = H_LETTER_BTN_C1; break; case TAB_TYPE_C1: nWidth = W_TAB_C1 + 2 * BORDER_C1; nHeight = H_LETTER_BTN_C1; break; case CAPS_TYPE_C1: nWidth = W_CAPS_C1 + 2 * BORDER_C1; nHeight = H_LETTER_BTN_C1; break; case ENTER_TYPE_C1: nWidth = W_ENTER_C1 + 2 * BORDER_C1; nHeight = H_LETTER_BTN_C1; break; case SHIFT_TYPE_C1: nWidth = W_SHIFT_C1 + 2 * BORDER_C1; nHeight = H_LETTER_BTN_C1; break; case INS_TYPE_C1: nWidth = W_INS_C1 + 2 * BORDER_C1; nHeight = H_BOTTOM_BTN_C1; break; case DEL_TYPE_C1: nWidth = W_DEL_C1 + 2 * BORDER_C1; nHeight = H_BOTTOM_BTN_C1; break; case SPACE_TYPE_C1: nWidth = W_SPACE_C1 + 2 * BORDER_C1; nHeight = H_BOTTOM_BTN_C1; break; case ESC_TYPE_C1: nWidth = W_ESC_C1 + 2 * BORDER_C1; nHeight = H_BOTTOM_BTN_C1; break; } } BitBlt(hDC, gptButtonPos[uKeyIndex].x, gptButtonPos[uKeyIndex].y, nWidth, nHeight, hDC, gptButtonPos[uKeyIndex].x , gptButtonPos[uKeyIndex].y, DSTINVERT); return; } /**********************************************************************\ * SKC1DrawBitmap --- Draw bitmap within rectangle * \**********************************************************************/ VOID SKC1DrawBitmap( HDC hDC, int x, int y, int nWidth, int nHeight, LPWSTR lpszBitmap) { HDC hMemDC; HBITMAP hBitmap, hOldBmp; hBitmap = LoadBitmap(ghInst, lpszBitmap); hMemDC = CreateCompatibleDC(hDC); hOldBmp = SelectObject(hMemDC, hBitmap); BitBlt(hDC, x, y, nWidth, nHeight, hMemDC, 0 , 0, SRCCOPY); SelectObject(hMemDC, hOldBmp); DeleteDC(hMemDC); DeleteObject(hBitmap); return; } /**********************************************************************\ * SKC1DrawLabel -- Draw the label of button * \**********************************************************************/ VOID SKC1DrawLabel( HDC hDC, LPWSTR lpszLabel) { HDC hMemDC; HBITMAP hBitmap, hOldBmp; int i, x; hBitmap = LoadBitmap(ghInst, lpszLabel); hMemDC = CreateCompatibleDC(hDC); hOldBmp = SelectObject(hMemDC, hBitmap); for (i=x=0; i < LETTER_NUM_C1; i++, x += SIZELABEL_C1){ BitBlt(hDC, gptButtonPos[i].x + X_LABEL_C1, gptButtonPos[i].y + Y_LABEL_C1, SIZELABEL_C1, SIZELABEL_C1, hMemDC, x , 0, SRCCOPY); } SelectObject(hMemDC, hOldBmp); DeleteDC(hMemDC); DeleteObject(hBitmap); return; } /**********************************************************************\ * InitSKC1Bitmap -- init bitmap * \**********************************************************************/ VOID InitSKC1Bitmap( HDC hDC, RECT rcClient) { int i; // draw softkbd rectangle SelectObject(hDC, GetStockObject(LTGRAY_BRUSH)); SelectObject(hDC, GetStockObject(NULL_PEN)); Rectangle(hDC, rcClient.left, rcClient.top, rcClient.right + 1, rcClient.bottom + 1); // draw letter buttons for (i = 0; i < LETTER_NUM_C1; i++) { SKC1DrawConvexRect(hDC, gptButtonPos[i].x, gptButtonPos[i].y, W_LETTER_BTN_C1, H_LETTER_BTN_C1); } // draw letter label SKC1DrawLabel(hDC, MAKEINTRESOURCEW(LABEL_C1)); // draw other buttons SKC1DrawConvexRect(hDC, gptButtonPos[BACKSP_TYPE_C1].x, gptButtonPos[BACKSP_TYPE_C1].y, W_BACKSP_C1 + 2 * BORDER_C1, H_LETTER_BTN_C1); SKC1DrawBitmap(hDC, gptButtonPos[BACKSP_TYPE_C1].x + BORDER_C1, gptButtonPos[BACKSP_TYPE_C1].y + BORDER_C1, W_BACKSP_C1, H_BACKSP_C1, MAKEINTRESOURCEW(BACKSP_C1)); SKC1DrawConvexRect(hDC, gptButtonPos[TAB_TYPE_C1].x, gptButtonPos[TAB_TYPE_C1].y, W_TAB_C1 + 2 * BORDER_C1, H_LETTER_BTN_C1); SKC1DrawBitmap(hDC, gptButtonPos[TAB_TYPE_C1].x + BORDER_C1, gptButtonPos[TAB_TYPE_C1].y + BORDER_C1, W_TAB_C1, H_TAB_C1, MAKEINTRESOURCEW(TAB_C1)); SKC1DrawConvexRect(hDC, gptButtonPos[CAPS_TYPE_C1].x, gptButtonPos[CAPS_TYPE_C1].y, W_CAPS_C1 + 2 * BORDER_C1, H_LETTER_BTN_C1); SKC1DrawBitmap(hDC, gptButtonPos[CAPS_TYPE_C1].x + BORDER_C1, gptButtonPos[CAPS_TYPE_C1].y + BORDER_C1, W_CAPS_C1, H_CAPS_C1, MAKEINTRESOURCEW(CAPS_C1)); SKC1DrawConvexRect(hDC, gptButtonPos[ENTER_TYPE_C1].x, gptButtonPos[ENTER_TYPE_C1].y, W_ENTER_C1 + 2 * BORDER_C1, H_LETTER_BTN_C1); SKC1DrawBitmap(hDC, gptButtonPos[ENTER_TYPE_C1].x + BORDER_C1, gptButtonPos[ENTER_TYPE_C1].y + BORDER_C1, W_ENTER_C1, H_ENTER_C1, MAKEINTRESOURCEW(ENTER_C1)); SKC1DrawConvexRect(hDC, gptButtonPos[SHIFT_TYPE_C1].x, gptButtonPos[SHIFT_TYPE_C1].y, W_SHIFT_C1 + 2 * BORDER_C1, H_LETTER_BTN_C1); SKC1DrawBitmap(hDC, gptButtonPos[SHIFT_TYPE_C1].x + BORDER_C1, gptButtonPos[SHIFT_TYPE_C1].y + BORDER_C1, W_SHIFT_C1, H_SHIFT_C1, MAKEINTRESOURCEW(SHIFT_C1)); SKC1DrawConvexRect(hDC, gptButtonPos[INS_TYPE_C1].x, gptButtonPos[INS_TYPE_C1].y, W_INS_C1 + 2 * BORDER_C1, H_BOTTOM_BTN_C1); SKC1DrawBitmap(hDC, gptButtonPos[INS_TYPE_C1].x + BORDER_C1, gptButtonPos[INS_TYPE_C1].y + BORDER_C1, W_INS_C1, H_INS_C1, MAKEINTRESOURCEW(INS_C1)); SKC1DrawConvexRect(hDC, gptButtonPos[DEL_TYPE_C1].x, gptButtonPos[DEL_TYPE_C1].y, W_DEL_C1 + 2 * BORDER_C1, H_BOTTOM_BTN_C1); SKC1DrawBitmap(hDC, gptButtonPos[DEL_TYPE_C1].x + BORDER_C1, gptButtonPos[DEL_TYPE_C1].y + BORDER_C1, W_DEL_C1, H_DEL_C1, MAKEINTRESOURCEW(DEL_C1)); SKC1DrawConvexRect(hDC, gptButtonPos[SPACE_TYPE_C1].x, gptButtonPos[SPACE_TYPE_C1].y, W_SPACE_C1 + 2 * BORDER_C1, H_BOTTOM_BTN_C1); SKC1DrawConvexRect(hDC, gptButtonPos[ESC_TYPE_C1].x, gptButtonPos[ESC_TYPE_C1].y, W_ESC_C1 + 2 * BORDER_C1, H_BOTTOM_BTN_C1); SKC1DrawBitmap(hDC, gptButtonPos[ESC_TYPE_C1].x + BORDER_C1, gptButtonPos[ESC_TYPE_C1].y + BORDER_C1, W_ESC_C1, H_ESC_C1, MAKEINTRESOURCEW(ESC_C1)); return; } /**********************************************************************\ * CreateC1Window * * Init softkeyboard gloabl variabls, context and bitmap * \**********************************************************************/ LRESULT CreateC1Window( HWND hSKWnd) { HGLOBAL hSKC1Ctxt; PSKC1CTXT pSKC1Ctxt; // alloc and lock hSKC1CTxt hSKC1Ctxt = GlobalAlloc(GHND, sizeof(SKC1CTXT)); if (!hSKC1Ctxt) { return (-1L); } pSKC1Ctxt = (PSKC1CTXT)GlobalLock(hSKC1Ctxt); if (!pSKC1Ctxt) { GlobalFree(hSKC1Ctxt); return (-1L); } // save handle in SKC1_CONTEXT SetWindowLongPtr(hSKWnd, SKC1_CONTEXT, (LONG_PTR)hSKC1Ctxt); // init global varialbles if (!gfSoftKbdC1Init){ InitSKC1ButtonPos(); gfSoftKbdC1Init = TRUE; } // no index and default char set pSKC1Ctxt->uKeyIndex = -1; pSKC1Ctxt->lfCharSet = GB2312_CHARSET; // init softkeyboard { HDC hDC, hMemDC; HBITMAP hBitmap, hOldBmp; RECT rcClient; GetClientRect(hSKWnd, &rcClient); hDC = GetDC(hSKWnd); hMemDC = CreateCompatibleDC(hDC); hBitmap = CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); ReleaseDC(hSKWnd, hDC); hOldBmp = SelectObject(hMemDC, hBitmap); InitSKC1Bitmap(hMemDC, rcClient); SelectObject(hMemDC, hOldBmp); pSKC1Ctxt->hSoftkbd = hBitmap; // save hBitmap in SKC1CTXT DeleteDC(hMemDC); } // unlock hSKC1CTxt GlobalUnlock(hSKC1Ctxt); return (0L); } /**********************************************************************\ * DestroyC1Window * * Destroy softkeyboard context and bitmap * \**********************************************************************/ VOID DestroyC1Window( HWND hSKWnd) { HGLOBAL hSKC1Ctxt; PSKC1CTXT pSKC1Ctxt; HWND hUIWnd; // Get and Lock hSKC1Ctxt hSKC1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKC1_CONTEXT); if (!hSKC1Ctxt) return; pSKC1Ctxt = (PSKC1CTXT)GlobalLock(hSKC1Ctxt); if (!pSKC1Ctxt) return; if (pSKC1Ctxt->uState & FLAG_DRAG_C1) { SKC1DrawDragBorder(hSKWnd, &pSKC1Ctxt->ptSkCursor, &pSKC1Ctxt->ptSkOffset); } DeleteObject(pSKC1Ctxt->hSoftkbd); // delete hBitmap // Unlock and Free hSKC1Ctxt GlobalUnlock(hSKC1Ctxt); GlobalFree(hSKC1Ctxt); // send message to parent window hUIWnd = GetWindow(hSKWnd, GW_OWNER); if (hUIWnd) { SendMessage(hUIWnd, WM_IME_NOTIFY, IMN_SOFTKBDDESTROYED, 0);\ } return; } /**********************************************************************\ * ShowSKC1Window -- Show softkeyboard * \**********************************************************************/ VOID ShowSKC1Window( HDC hDC, HWND hSKWnd) { HGLOBAL hSKC1Ctxt; PSKC1CTXT pSKC1Ctxt; // Get and Lock hSKC1Ctxt hSKC1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKC1_CONTEXT); if (!hSKC1Ctxt) return; pSKC1Ctxt = (PSKC1CTXT)GlobalLock(hSKC1Ctxt); if (!pSKC1Ctxt) return; // create mem dc to show softkeyboard { HDC hMemDC; HBITMAP hOldBmp; RECT rcClient; hMemDC = CreateCompatibleDC(hDC); hOldBmp = SelectObject(hMemDC, pSKC1Ctxt->hSoftkbd); GetClientRect(hSKWnd, &rcClient); BitBlt(hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hMemDC, 0, 0, SRCCOPY); SelectObject(hMemDC, hOldBmp); DeleteDC(hMemDC); } // Unlock hSKC1Ctxt GlobalUnlock(hSKC1Ctxt); return; } /**********************************************************************\ * UpdateSKC1Window -- update softkeyboard * \**********************************************************************/ BOOL UpdateSKC1Window( HWND hSKWnd, LPSOFTKBDDATA lpSoftKbdData) { HGLOBAL hSKC1Ctxt; PSKC1CTXT pSKC1Ctxt; LOGFONT lfFont; HFONT hOldFont, hFont; HDC hDC, hMemDC; HBITMAP hOldBmp; int i; // check the lpSoftKbdData if (lpSoftKbdData->uCount!=2) return FALSE; // Get and Lock hSKC1Ctxt hSKC1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKC1_CONTEXT); if (!hSKC1Ctxt) return FALSE; pSKC1Ctxt = (PSKC1CTXT)GlobalLock(hSKC1Ctxt); if (!pSKC1Ctxt) return FALSE; // create font hDC = GetDC(hSKWnd); hMemDC = CreateCompatibleDC(hDC); hOldBmp = SelectObject(hMemDC, pSKC1Ctxt->hSoftkbd); GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lfFont), &lfFont); lfFont.lfHeight = -SIZEFONT_C1; if (pSKC1Ctxt->lfCharSet != DEFAULT_CHARSET) { lfFont.lfCharSet = (BYTE)pSKC1Ctxt->lfCharSet; } hFont = CreateFontIndirect(&lfFont); hOldFont = SelectObject(hMemDC, hFont); // update shift/non-shift chars for (i=0; i < LETTER_NUM_C1; i++) { pSKC1Ctxt->wNonShiftCode[i] = lpSoftKbdData->wCode[0][SKC1VirtKey[i]]; pSKC1Ctxt->wShiftCode[i] = lpSoftKbdData->wCode[1][SKC1VirtKey[i]]; } SetBkColor(hMemDC, 0x00BFBFBF); // set text bk color ?? for (i=0; i < LETTER_NUM_C1; i++) { int nchar; RECT rc; // draw shift char. rc.left = gptButtonPos[i].x + X_SHIFT_CHAR_C1; rc.top = gptButtonPos[i].y + Y_SHIFT_CHAR_C1; rc.right = rc.left + SIZEFONT_C1; rc.bottom = rc.top + SIZEFONT_C1; nchar = (pSKC1Ctxt->wShiftCode[i] == 0) ? 0 : 1; #if (WINVER >= 0x0400) DrawTextEx(hMemDC, (LPWSTR)&pSKC1Ctxt->wShiftCode[i], nchar, &rc, DT_CENTER, NULL); #else ExtTextOut(hMemDC, rc.left, rc.top, ETO_OPAQUE, &rc, (LPWSTR)&pSKC1Ctxt->wShiftCode[i], nchar, NULL); #endif // draw non-shift char. rc.left = gptButtonPos[i].x + X_NONSHIFT_CHAR_C1; rc.top = gptButtonPos[i].y + Y_NONSHIFT_CHAR_C1; rc.right = rc.left + SIZEFONT_C1; rc.bottom = rc.top + SIZEFONT_C1; nchar = (pSKC1Ctxt->wNonShiftCode[i] == 0) ? 0 : 1; #if (WINVER >= 0x0400) DrawTextEx(hMemDC, (LPWSTR)&pSKC1Ctxt->wNonShiftCode[i], nchar, &rc, DT_CENTER, NULL); #else ExtTextOut(hMemDC, rc.left, rc.top, ETO_OPAQUE, &rc, (LPWSTR)&pSKC1Ctxt->wNonShiftCode[i], nchar, NULL); #endif } // init states if (pSKC1Ctxt->uState & FLAG_SHIFT_C1){ SKC1InvertButton(hMemDC, SHIFT_TYPE_C1); } pSKC1Ctxt->uState = 0; SelectObject(hMemDC, hOldBmp); SelectObject(hMemDC, hOldFont); DeleteDC(hMemDC); DeleteObject(hFont); ReleaseDC(hSKWnd,hDC); // Unlock hSKC1Ctxt GlobalUnlock(hSKC1Ctxt); return TRUE; } /**********************************************************************\ * SKC1DrawDragBorder() -- Draw Drag Border * \**********************************************************************/ VOID SKC1DrawDragBorder( HWND hWnd, // window is dragged LPPOINT lpptCursor, // the cursor position LPPOINT lpptOffset) // the offset form cursor to window org { HDC hDC; RECT rcWnd, rcWorkArea; int cxBorder, cyBorder; int x, y; extern void GetAllMonitorSize(LPRECT lprc); // get rectangle of work area GetAllMonitorSize(&rcWorkArea); cxBorder = GetSystemMetrics(SM_CXBORDER); // width of border cyBorder = GetSystemMetrics(SM_CYBORDER); // height of border // create DISPLAY dc to draw track hDC = CreateDC(L"DISPLAY", NULL, NULL, NULL); SelectObject(hDC, GetStockObject(GRAY_BRUSH)); // start point (left,top) x = lpptCursor->x - lpptOffset->x; y = lpptCursor->y - lpptOffset->y; // check for the min boundary of the display if (x < rcWorkArea.left) { x = rcWorkArea.left; } if (y < rcWorkArea.top) { y = rcWorkArea.top; } // check for the max boundary of the display GetWindowRect(hWnd, &rcWnd); if (x + rcWnd.right - rcWnd.left > rcWorkArea.right) { x = rcWorkArea.right - (rcWnd.right - rcWnd.left); } if (y + rcWnd.bottom - rcWnd.top > rcWorkArea.bottom) { y = rcWorkArea.bottom - (rcWnd.bottom - rcWnd.top); } // adjust Offset lpptOffset->x = lpptCursor->x - x; lpptOffset->y = lpptCursor->y - y; // draw rectangle PatBlt(hDC, x, y, rcWnd.right - rcWnd.left - cxBorder, cyBorder, PATINVERT); PatBlt(hDC, x, y + cyBorder, cxBorder, rcWnd.bottom - rcWnd.top - cyBorder, PATINVERT); PatBlt(hDC, x + cxBorder, y + rcWnd.bottom - rcWnd.top, rcWnd.right - rcWnd.left - cxBorder, -cyBorder, PATINVERT); PatBlt(hDC, x + rcWnd.right - rcWnd.left, y, - cxBorder, rcWnd.bottom - rcWnd.top - cyBorder, PATINVERT); // delete DISPLAY DC DeleteDC(hDC); return; } /**********************************************************************\ * SKC1MousePosition() -- judge the cursor position * \**********************************************************************/ #define CHECK_RECT(name) \ if (ImmPtInRect(gptButtonPos[name ## _TYPE_C1].x, \ gptButtonPos[name ## _TYPE_C1].y, \ W_ ## name ## _C1 + 2 * BORDER_C1, \ H_ ## name ## _C1 + 2 * BORDER_C1, \ lpptCursor)) { \ return name ## _TYPE_C1; \ } INT SKC1MousePosition( LPPOINT lpptCursor) { int i; // letter buttons for (i = 0; i < LETTER_NUM_C1; i++){ if (ImmPtInRect(gptButtonPos[i].x, gptButtonPos[i].y, W_LETTER_BTN_C1, H_LETTER_BTN_C1, lpptCursor)) { return i; } } CHECK_RECT(BACKSP); CHECK_RECT(TAB); CHECK_RECT(CAPS); CHECK_RECT(ENTER); CHECK_RECT(SHIFT); CHECK_RECT(ESC); CHECK_RECT(SPACE); CHECK_RECT(INS); CHECK_RECT(DEL); return -1; } #undef CHECK_RECT /**********************************************************************\ * SKC1ButtonDown * \**********************************************************************/ VOID SKC1ButtonDown( HWND hSKWnd, PSKC1CTXT pSKC1Ctxt) { // capture the mouse activity SetCapture(hSKWnd); // in drag area if (pSKC1Ctxt->uKeyIndex == -1) { pSKC1Ctxt->uState |= FLAG_DRAG_C1; SKC1DrawDragBorder(hSKWnd, &pSKC1Ctxt->ptSkCursor, &pSKC1Ctxt->ptSkOffset); } else { UINT uVirtKey = 0xff; BOOL bRet = FALSE; if (pSKC1Ctxt->uKeyIndex == SHIFT_TYPE_C1) { if (!(pSKC1Ctxt->uState & FLAG_SHIFT_C1)) { bRet = TRUE; } } else if (pSKC1Ctxt->uKeyIndex < LETTER_NUM_C1) { if (pSKC1Ctxt->uState & FLAG_SHIFT_C1) { uVirtKey = pSKC1Ctxt->wShiftCode[pSKC1Ctxt->uKeyIndex]; } else { uVirtKey = pSKC1Ctxt->wNonShiftCode[pSKC1Ctxt->uKeyIndex]; } if (uVirtKey) { bRet = TRUE; } else { MessageBeep(0xFFFFFFFF); pSKC1Ctxt->uKeyIndex = -1; } } else { bRet = TRUE; } if (bRet) { HDC hDC, hMemDC; HBITMAP hOldBmp; hDC = GetDC(hSKWnd); hMemDC = CreateCompatibleDC(hDC); hOldBmp = SelectObject(hMemDC, pSKC1Ctxt->hSoftkbd); SKC1InvertButton(hDC, pSKC1Ctxt->uKeyIndex); SKC1InvertButton(hMemDC, pSKC1Ctxt->uKeyIndex); SelectObject(hMemDC, hOldBmp); DeleteDC(hMemDC); ReleaseDC(hSKWnd,hDC); } if(uVirtKey) { pSKC1Ctxt->uState |= FLAG_FOCUS_C1; } } return; } /**********************************************************************\ * SKC1SetCursor * \**********************************************************************/ BOOL SKC1SetCursor( HWND hSKWnd, LPARAM lParam) { HGLOBAL hSKC1Ctxt; PSKC1CTXT pSKC1Ctxt; POINT ptSkCursor, ptSkOffset; int uKeyIndex; // Get and lock hSKC1Ctxt hSKC1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKC1_CONTEXT); if (!hSKC1Ctxt) { return (FALSE); } pSKC1Ctxt = (PSKC1CTXT)GlobalLock(hSKC1Ctxt); if (!pSKC1Ctxt) { return (FALSE); } if (pSKC1Ctxt->uState & FLAG_DRAG_C1){ // in drag operation SetCursor(LoadCursor(NULL, IDC_SIZEALL)); GlobalUnlock(hSKC1Ctxt); return (TRUE); } GetCursorPos(&ptSkCursor); ptSkOffset = ptSkCursor; ScreenToClient(hSKWnd, &ptSkOffset); uKeyIndex = SKC1MousePosition(&ptSkOffset); if (uKeyIndex != -1) { SetCursor(LoadCursor(NULL, IDC_HAND)); } else { SetCursor(LoadCursor(NULL, IDC_SIZEALL)); } if (HIWORD(lParam) != WM_LBUTTONDOWN){ // unlock hSKC1Ctxt GlobalUnlock(hSKC1Ctxt); return (TRUE); } pSKC1Ctxt->ptSkCursor = ptSkCursor; pSKC1Ctxt->ptSkOffset = ptSkOffset; pSKC1Ctxt->uKeyIndex = uKeyIndex; SKC1ButtonDown(hSKWnd, pSKC1Ctxt); // unlock hSKC1Ctxt GlobalUnlock(hSKC1Ctxt); return (TRUE); } /**********************************************************************\ * SKC1MouseMove * \**********************************************************************/ BOOL SKC1MouseMove( HWND hSKWnd, WPARAM wParam, LPARAM lParam) { HGLOBAL hSKC1Ctxt; PSKC1CTXT pSKC1Ctxt; UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); // get and lock hSKC1Ctxt hSKC1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKC1_CONTEXT); if (!hSKC1Ctxt) { return (FALSE); } pSKC1Ctxt = (PSKC1CTXT)GlobalLock(hSKC1Ctxt); if (!pSKC1Ctxt) { return (FALSE); } if (pSKC1Ctxt->uState & FLAG_DRAG_C1) { SKC1DrawDragBorder(hSKWnd, &pSKC1Ctxt->ptSkCursor, &pSKC1Ctxt->ptSkOffset); GetCursorPos(&pSKC1Ctxt->ptSkCursor); SKC1DrawDragBorder(hSKWnd, &pSKC1Ctxt->ptSkCursor, &pSKC1Ctxt->ptSkOffset); } else if (pSKC1Ctxt->uKeyIndex != -1) { HDC hDC, hMemDC; HBITMAP hOldBmp; POINT ptSkOffset; int uKeyIndex; GetCursorPos(&ptSkOffset); ScreenToClient(hSKWnd, &ptSkOffset); uKeyIndex = SKC1MousePosition(&ptSkOffset); hDC = GetDC(hSKWnd); hMemDC = CreateCompatibleDC(hDC); hOldBmp = SelectObject(hMemDC, pSKC1Ctxt->hSoftkbd); if (((pSKC1Ctxt->uState & FLAG_FOCUS_C1) && (uKeyIndex != pSKC1Ctxt->uKeyIndex)) || (!(pSKC1Ctxt->uState & FLAG_FOCUS_C1) && (uKeyIndex == pSKC1Ctxt->uKeyIndex))) { if ((pSKC1Ctxt->uKeyIndex != SHIFT_TYPE_C1) || !(pSKC1Ctxt->uState & FLAG_SHIFT_C1)) { SKC1InvertButton(hDC, pSKC1Ctxt->uKeyIndex); SKC1InvertButton(hMemDC, pSKC1Ctxt->uKeyIndex); } pSKC1Ctxt->uState ^= FLAG_FOCUS_C1; } SelectObject(hMemDC, hOldBmp); DeleteDC(hMemDC); ReleaseDC(hSKWnd,hDC); } // unlock hSKC1Ctxt GlobalUnlock(hSKC1Ctxt); return (TRUE); } /**********************************************************************\ * SKC1ButtonUp * \**********************************************************************/ BOOL SKC1ButtonUp( HWND hSKWnd, WPARAM wParam, LPARAM lParam) { HGLOBAL hSKC1Ctxt; PSKC1CTXT pSKC1Ctxt; POINT pt; UINT uVirtKey; BOOL bRet = FALSE; UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); // Get and lock hSKC1Ctxt hSKC1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKC1_CONTEXT); if (!hSKC1Ctxt) { return (bRet); } pSKC1Ctxt = (PSKC1CTXT)GlobalLock(hSKC1Ctxt); if (!pSKC1Ctxt) { return (bRet); } ReleaseCapture(); if (pSKC1Ctxt->uState & FLAG_DRAG_C1) { pSKC1Ctxt->uState &= ~(FLAG_DRAG_C1); SKC1DrawDragBorder(hSKWnd, &pSKC1Ctxt->ptSkCursor, &pSKC1Ctxt->ptSkOffset); pt.x = pSKC1Ctxt->ptSkCursor.x - pSKC1Ctxt->ptSkOffset.x; pt.y = pSKC1Ctxt->ptSkCursor.y - pSKC1Ctxt->ptSkOffset.y; SetWindowPos(hSKWnd, (HWND)NULL, pt.x, pt.y, 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER); // update IMC bRet = TRUE; { HWND hUIWnd; HIMC hImc; PINPUTCONTEXT pInputContext; hUIWnd = GetWindow(hSKWnd, GW_OWNER); hImc = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC); if (hImc) { pInputContext = ImmLockIMC(hImc); if (pInputContext) { pInputContext->ptSoftKbdPos = pt; pInputContext->fdwInit |= INIT_SOFTKBDPOS; ImmUnlockIMC(hImc); } } } } else if (pSKC1Ctxt->uKeyIndex != -1) { if (pSKC1Ctxt->uState & FLAG_FOCUS_C1) { if (pSKC1Ctxt->uKeyIndex == SHIFT_TYPE_C1) { if (pSKC1Ctxt->uState & FLAG_SHIFT_C1) { bRet = TRUE; } else { pSKC1Ctxt->uState |= FLAG_SHIFT_C1; } } else if ((pSKC1Ctxt->uKeyIndex < LETTER_NUM_C1) && (pSKC1Ctxt->uState & FLAG_SHIFT_C1)) { keybd_event((BYTE)VK_SHIFT, (BYTE)guScanCode[VK_SHIFT], 0, 0); uVirtKey = SKC1VirtKey[pSKC1Ctxt->uKeyIndex]; keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey], 0, 0); keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey], (DWORD)KEYEVENTF_KEYUP, 0); keybd_event((BYTE)VK_SHIFT, (BYTE)guScanCode[VK_SHIFT], (DWORD)KEYEVENTF_KEYUP, 0); bRet = TRUE; } else { uVirtKey = SKC1VirtKey[pSKC1Ctxt->uKeyIndex]; keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey], 0, 0); keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey], (DWORD)KEYEVENTF_KEYUP, 0); bRet = TRUE; } if (bRet){ HDC hDC, hMemDC; HBITMAP hOldBmp; hDC = GetDC(hSKWnd); hMemDC = CreateCompatibleDC(hDC); hOldBmp = SelectObject(hMemDC, pSKC1Ctxt->hSoftkbd); SKC1InvertButton(hDC, pSKC1Ctxt->uKeyIndex); SKC1InvertButton(hMemDC, pSKC1Ctxt->uKeyIndex); if ((pSKC1Ctxt->uKeyIndex != SHIFT_TYPE_C1) && (pSKC1Ctxt->uKeyIndex < LETTER_NUM_C1) && (pSKC1Ctxt->uState & FLAG_SHIFT_C1)) { SKC1InvertButton(hDC, SHIFT_TYPE_C1); SKC1InvertButton(hMemDC, SHIFT_TYPE_C1); } if ((pSKC1Ctxt->uKeyIndex < LETTER_NUM_C1) || (pSKC1Ctxt->uKeyIndex == SHIFT_TYPE_C1)) { pSKC1Ctxt->uState &= ~(FLAG_SHIFT_C1); } SelectObject(hMemDC, hOldBmp); DeleteDC(hMemDC); ReleaseDC(hSKWnd,hDC); } pSKC1Ctxt->uState &= ~ (FLAG_FOCUS_C1); } pSKC1Ctxt->uKeyIndex = -1; } // unlock hSKC1Ctxt GlobalUnlock(hSKC1Ctxt); return (bRet); } /**********************************************************************\ * SKWndProcC1 -- softkeyboard window procedure * \**********************************************************************/ LRESULT SKWndProcC1( HWND hSKWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRet = 0L; switch (uMsg) { case WM_CREATE: lRet = CreateC1Window(hSKWnd); break; case WM_DESTROY: DestroyC1Window(hSKWnd); break; case WM_PAINT: { HDC hDC; PAINTSTRUCT ps; hDC = BeginPaint(hSKWnd, &ps); ShowSKC1Window(hDC, hSKWnd); EndPaint(hSKWnd, &ps); } break; case WM_MOUSEACTIVATE: lRet = MA_NOACTIVATE; break; case WM_SETCURSOR: if (!SKC1SetCursor(hSKWnd, lParam)) { lRet = DefWindowProc(hSKWnd, uMsg, wParam, lParam); } break; case WM_MOUSEMOVE: if (!SKC1MouseMove(hSKWnd, wParam, lParam)) { lRet = DefWindowProc(hSKWnd, uMsg, wParam, lParam); } break; case WM_LBUTTONUP: if (!SKC1ButtonUp(hSKWnd, wParam, lParam)) { lRet = DefWindowProc(hSKWnd, uMsg, wParam, lParam); } break; case WM_IME_CONTROL: switch (wParam) { case IMC_GETSOFTKBDFONT: { HDC hDC; LOGFONT lfFont; hDC = GetDC(hSKWnd); GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lfFont), &lfFont); ReleaseDC(hSKWnd, hDC); *(LPLOGFONT)lParam = lfFont; } break; case IMC_SETSOFTKBDFONT: { LOGFONT lfFont; GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lfFont), &lfFont); // in differet version of Windows if (lfFont.lfCharSet != ((LPLOGFONT)lParam)->lfCharSet) { HGLOBAL hSKC1Ctxt; LPSKC1CTXT lpSKC1Ctxt; hSKC1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKC1_CONTEXT); if (!hSKC1Ctxt) { return 1; } lpSKC1Ctxt = (LPSKC1CTXT)GlobalLock(hSKC1Ctxt); if (!lpSKC1Ctxt) { return 1; } lpSKC1Ctxt->lfCharSet = ((LPLOGFONT)lParam)->lfCharSet; GlobalUnlock(hSKC1Ctxt); } } break; case IMC_GETSOFTKBDPOS: { RECT rcWnd; GetWindowRect(hSKWnd, &rcWnd); return MAKELRESULT(rcWnd.left, rcWnd.top); } break; case IMC_SETSOFTKBDPOS: { SetWindowPos(hSKWnd, NULL, ((LPPOINTS)lParam)->x, ((LPPOINTS)lParam)->y, 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER); return (0); } break; case IMC_SETSOFTKBDDATA: if (UpdateSKC1Window(hSKWnd, (LPSOFTKBDDATA)lParam)) { InvalidateRect(hSKWnd, NULL, FALSE); } else lRet = -1L; break; case IMC_GETSOFTKBDSUBTYPE: case IMC_SETSOFTKBDSUBTYPE: { HGLOBAL hSKC1Ctxt; PSKC1CTXT pSKC1Ctxt; lRet = -1L; hSKC1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKC1_CONTEXT); if (!hSKC1Ctxt) break; pSKC1Ctxt = (PSKC1CTXT)GlobalLock(hSKC1Ctxt); if (!pSKC1Ctxt) break; if (wParam == IMC_GETSOFTKBDSUBTYPE) { lRet = pSKC1Ctxt->uSubtype; } else { lRet = pSKC1Ctxt->uSubtype; pSKC1Ctxt->uSubtype = (UINT)lParam; } GlobalUnlock(hSKC1Ctxt); } break; } break; default: lRet = DefWindowProc(hSKWnd, uMsg, wParam, lParam); } return (lRet); }