|
|
/**************************************************************************\
* Module Name: sftkbdt1.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * Soft keyboard support for Traditional Chinese * * History: * 02-Jan-1996 wkwok - ported from Win95 \**************************************************************************/ #include "precomp.h"
#pragma hdrstop
#include "softkbd.h"
CONST BYTE bSKT1VirtKey[SKT1_TOTAL_KEY_NUM] = { // Virtual Key for Letter Buttons
// ` 1 2 3 4 5 6 7 8 9 0
VK_OEM_3, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // - = \\ line 1 letter above
VK_OEM_MINUS, VK_OEM_EQUAL, VK_OEM_BSLASH, // q w e r t y u i o p
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', // [ ] line 2 letter above
VK_OEM_LBRACKET, VK_OEM_RBRACKET, // a s d f g h j k l
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', // ; ' line 3 letter above
VK_OEM_SEMICLN, VK_OEM_QUOTE, // z x c v b n m
'Z', 'X', 'C', 'V', 'B', 'N', 'M', // , . / line 4 letter above
VK_OEM_COMMA, VK_OEM_PERIOD, VK_OEM_SLASH, // <- tab caps enter
VK_BACK, VK_TAB, VK_CAPITAL, VK_RETURN, // shift1 shift2 ctrl1 ctrl2
VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, // alt1 alt2 esc space special key above
VK_MENU, VK_MENU, VK_ESCAPE, VK_SPACE };
LOGFONT lfSKT1Font;
/**********************************************************************/ /* GetSKT1TextMetric */ /**********************************************************************/
void GetSKT1TextMetric( LPTEXTMETRIC lptm) { HDC hDC; HFONT hOldFont; SIZE szDbcs; const WCHAR wcDbcs = 0x4e11;
hDC = GetDC((HWND)NULL);
// get the 9 pixels font
RtlZeroMemory(&lfSKT1Font, sizeof lfSKT1Font); lfSKT1Font.lfHeight = -12; lfSKT1Font.lfWeight = FW_NORMAL;
lfSKT1Font.lfCharSet = CHINESEBIG5_CHARSET;
lfSKT1Font.lfOutPrecision = OUT_TT_ONLY_PRECIS; lfSKT1Font.lfClipPrecision = CLIP_DEFAULT_PRECIS; lfSKT1Font.lfQuality = PROOF_QUALITY; lfSKT1Font.lfPitchAndFamily = FIXED_PITCH|FF_MODERN;
hOldFont = (HFONT)SelectObject(hDC, CreateFontIndirect(&lfSKT1Font));
GetTextMetrics(hDC, lptm);
/*
* NT5: Dirty hack for "Lucida Console" which was "font linked" on NT5, and * GetTextMetrics API does not return correct text metrics. */ if (GetTextExtentPoint32(hDC, &wcDbcs, 1, &szDbcs) && lptm->tmMaxCharWidth < szDbcs.cx) { TAGMSG2(DBGTAG_IMM, "GetSKT1TextMetric: tmMaxCharWidth(%d) is smaller than real width(%d).", lptm->tmMaxCharWidth, szDbcs.cx); lptm->tmMaxCharWidth = szDbcs.cx; }
DeleteObject(SelectObject(hDC, hOldFont));
ReleaseDC((HWND)NULL, hDC);
return; }
/**********************************************************************/ /* InitSKT1ButtonPos */ /**********************************************************************/ void InitSKT1ButtonPos( LPSKT1CTXT lpSKT1Ctxt) { TEXTMETRIC tm; int nButtonWidthUnit, nButtonHeightUnit; int i, nLetterButtonStart, nLetterButtonEnd, xStartPos, yStartPos;
GetSKT1TextMetric(&tm);
nButtonWidthUnit = tm.tmMaxCharWidth + SKT1_LABEL_BMP_X - SKT1_XOVERLAP;
#define INIT_WIDTH(name, width) \
lpSKT1Ctxt->nButtonWidth[SKT1_ ## name ## _TYPE] = (width)
INIT_WIDTH(LETTER, nButtonWidthUnit * SKT1_LETTER_WIDTH_TIMES / 2); INIT_WIDTH(BACKSPACE, nButtonWidthUnit * SKT1_BACKSPACE_WIDTH_TIMES / 2 + 1); INIT_WIDTH(TAB, nButtonWidthUnit * SKT1_TAB_WIDTH_TIMES / 2 + (SKT1_XIN + 1) / 2); INIT_WIDTH(CAPS, nButtonWidthUnit * SKT1_CAPS_WIDTH_TIMES / 2 + SKT1_XIN); INIT_WIDTH(ENTER, nButtonWidthUnit * SKT1_ENTER_WIDTH_TIMES / 2 + (SKT1_XIN + 1) / 2); INIT_WIDTH(SHIFT, nButtonWidthUnit * SKT1_SHIFT_WIDTH_TIMES / 2 + SKT1_XIN + (SKT1_XIN + 1) / 2); INIT_WIDTH(CTRL, nButtonWidthUnit * SKT1_CTRL_WIDTH_TIMES / 2 + (SKT1_XIN + 1) / 2); INIT_WIDTH(ALT, nButtonWidthUnit * SKT1_ALT_WIDTH_TIMES / 2 + (SKT1_XIN + 1) / 2); INIT_WIDTH(ESC, nButtonWidthUnit * SKT1_ESC_WIDTH_TIMES / 2 + SKT1_XIN / 2); INIT_WIDTH(SPACE, nButtonWidthUnit * SKT1_SPACE_WIDTH_TIMES / 2 + SKT1_XIN * 5);
#undef INIT_WIDTH
nButtonHeightUnit = tm.tmHeight + SKT1_LABEL_BMP_Y; lpSKT1Ctxt->nButtonHeight[0] = nButtonHeightUnit; lpSKT1Ctxt->nButtonHeight[1] = nButtonHeightUnit * 2 + SKT1_YIN; // enter
// init first row attribute
xStartPos = gptRaiseEdge.x + SKT1_XOUT + (SKT1_XIN + 1) / 2; yStartPos = gptRaiseEdge.y + SKT1_YOUT + (SKT1_YIN + 1) / 2;
nLetterButtonStart = 0; nLetterButtonEnd = nLetterButtonStart + SKT1_ROW1_LETTER_NUM;
for (i = nLetterButtonStart; i < nLetterButtonEnd; i++) { lpSKT1Ctxt->ptButtonPos[i].x = xStartPos; lpSKT1Ctxt->ptButtonPos[i].y = yStartPos; xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + SKT1_XIN); } // backspace
lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].x = xStartPos; lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].y = yStartPos;
// init second row attribute
xStartPos = gptRaiseEdge.x + SKT1_XOUT + (SKT1_XIN + 1) / 2; yStartPos += (nButtonHeightUnit + SKT1_YIN); // tab
lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].x = xStartPos; lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].y = yStartPos; xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_TAB_TYPE] + SKT1_XIN); // letter
nLetterButtonStart = nLetterButtonEnd; nLetterButtonEnd = nLetterButtonStart + SKT1_ROW2_LETTER_NUM; for (i = nLetterButtonStart; i < nLetterButtonEnd; i++) { lpSKT1Ctxt->ptButtonPos[i].x = xStartPos; lpSKT1Ctxt->ptButtonPos[i].y = yStartPos; xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + SKT1_XIN); } // enter
lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].x = xStartPos; lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].y = yStartPos;
// init third row
xStartPos = gptRaiseEdge.x + SKT1_XOUT + (SKT1_XIN + 1) / 2; yStartPos += (nButtonHeightUnit + SKT1_YIN); // caps
lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].x = xStartPos; lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].y = yStartPos; xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_CAPS_TYPE] + SKT1_XIN); // letter
nLetterButtonStart = nLetterButtonEnd; nLetterButtonEnd = nLetterButtonStart + SKT1_ROW3_LETTER_NUM; for (i = nLetterButtonStart; i < nLetterButtonEnd; i++) { lpSKT1Ctxt->ptButtonPos[i].x = xStartPos; lpSKT1Ctxt->ptButtonPos[i].y = yStartPos; xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + SKT1_XIN); }
// init fourth row
xStartPos = gptRaiseEdge.x + SKT1_XOUT + (SKT1_XIN + 1) / 2; yStartPos += (nButtonHeightUnit + SKT1_YIN); // shift 1
lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].x = xStartPos; lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].y = yStartPos; xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE] + SKT1_XIN); // letter
nLetterButtonStart = nLetterButtonEnd; nLetterButtonEnd = nLetterButtonStart + SKT1_ROW4_LETTER_NUM; for (i = nLetterButtonStart; i < nLetterButtonEnd; i++) { lpSKT1Ctxt->ptButtonPos[i].x = xStartPos; lpSKT1Ctxt->ptButtonPos[i].y = yStartPos; xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + SKT1_XIN); } // shift 2
lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].x = xStartPos; lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].y = yStartPos;
// init fifth row
xStartPos = gptRaiseEdge.x + SKT1_XOUT + (SKT1_XIN + 1) / 2; yStartPos += (nButtonHeightUnit + SKT1_YIN); // ctrl 1
lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].x = xStartPos; lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].y = yStartPos; xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE] + SKT1_XIN); // esc
lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].x = xStartPos; lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].y = yStartPos; xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE] + SKT1_XIN); // alt 1
lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].x = xStartPos; lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].y = yStartPos; xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE] + SKT1_XIN); // space
lpSKT1Ctxt->ptButtonPos[SKT1_SPACE_INDEX].x = xStartPos; lpSKT1Ctxt->ptButtonPos[SKT1_SPACE_INDEX].y = yStartPos; xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE] + SKT1_XIN); // alt 2 .. skip blank
lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].x = xStartPos; lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].y = yStartPos; xStartPos += (lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE] + SKT1_XIN) + (lpSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE] + SKT1_XIN); // ctrl 2
lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].x = xStartPos; lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].y = yStartPos;
return; }
/**********************************************************************/ /* SKT1DrawConvexRect */ /* draw a convex rectangle */ /* (x,y) x+nWidth+1 */ /* +-----1------+ */ /* |+----2-----|| */ /* || || */ /* || 3| */ /* || || */ /* |V || <---- Rectangle */ /* |<----------+| */ /* y+nHeight+1 +------------+ */ /* 1 - black */ /* 2 - while */ /* 3 - dark gray */ /**********************************************************************/ void SKT1DrawConvexRect( HDC hDC, int x, int y, int nWidth, int nHeight) { // extend the context rect size
x -= (SKT1_XIN + 1) / 2; y -= (SKT1_YIN + 1) / 2; nWidth += (SKT1_XIN + 1); nHeight += (SKT1_XIN + 1);
// 1
SelectObject(hDC, GetStockObject(BLACK_PEN)); SelectObject(hDC, GetStockObject(LTGRAY_BRUSH)); Rectangle(hDC, x, y, x + nWidth, y + nHeight); PatBlt(hDC, x, y, 1, 1, PATCOPY); PatBlt(hDC, x + nWidth, y, -1, 1, PATCOPY); PatBlt(hDC, x, y + nHeight, 1, -1, PATCOPY); PatBlt(hDC, x + nWidth, y + nHeight, -1, -1, PATCOPY);
x++; y++; nWidth -= 2; nHeight -= 2;
// 2
PatBlt(hDC, x, y + nHeight, 1, -nHeight, WHITENESS); PatBlt(hDC, x, y, nWidth , 1, WHITENESS); // 3
SelectObject(hDC, GetStockObject(GRAY_BRUSH)); PatBlt(hDC, x, y + nHeight, nWidth, -1, PATCOPY); PatBlt(hDC, x + nWidth, y + nHeight, -1, -nHeight, PATCOPY);
return; }
/**********************************************************************/ /* SKT1DrawBitmap */ /**********************************************************************/ void SKT1DrawBitmap( HDC hDC, int x, int y, int nWidth, int nHeight, LPCWSTR lpszBitmap) { HDC hMemDC; HBITMAP hBitmap, hOldBmp;
hBitmap = (HBITMAP)LoadBitmap(ghInst, lpszBitmap);
hMemDC = CreateCompatibleDC(hDC);
hOldBmp = (HBITMAP)SelectObject(hMemDC, hBitmap);
BitBlt(hDC, x, y, nWidth, nHeight, hMemDC, 0 , 0, SRCCOPY);
SelectObject(hMemDC, hOldBmp);
DeleteObject(hBitmap);
DeleteDC(hMemDC);
return; }
/**********************************************************************/ /* SKT1DrawLabel */ /**********************************************************************/ void SKT1DrawLabel( HDC hDC, LPSKT1CTXT lpSKT1Ctxt, LPCWSTR lpszLabel) { HDC hMemDC; HBITMAP hBitmap, hOldBmp; int i;
hBitmap = LoadBitmap(ghInst, lpszLabel); hMemDC = CreateCompatibleDC(hDC); hOldBmp = (HBITMAP)SelectObject(hMemDC, hBitmap);
for (i = 0; i < SKT1_LETTER_KEY_NUM; i++) { BitBlt(hDC, lpSKT1Ctxt->ptButtonPos[i].x, lpSKT1Ctxt->ptButtonPos[i].y, SKT1_LABEL_BMP_X, SKT1_LABEL_BMP_Y, hMemDC, i * SKT1_LABEL_BMP_X, 0, SRCCOPY); }
SelectObject(hMemDC, hOldBmp); DeleteDC(hMemDC); DeleteObject(hBitmap);
return; }
/**********************************************************************/ /* InitSKT1Bitmap */ /**********************************************************************/ void InitSKT1Bitmap( HWND hSKWnd, LPSKT1CTXT lpSKT1Ctxt) { HDC hDC, hMemDC; RECT rcClient; int i;
hDC = GetDC(hSKWnd); hMemDC = CreateCompatibleDC(hDC); GetClientRect(hSKWnd, &rcClient); lpSKT1Ctxt->hSKBitmap = CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); ReleaseDC(hSKWnd, hDC); SelectObject(hMemDC, lpSKT1Ctxt->hSKBitmap);
// draw SK rectangle
SelectObject(hMemDC, GetStockObject(NULL_PEN)); SelectObject(hMemDC, GetStockObject(LTGRAY_BRUSH)); Rectangle(hMemDC, rcClient.left, rcClient.top, rcClient.right + 1, rcClient.bottom + 1);
DrawEdge(hMemDC, &rcClient, BDR_RAISED, BF_RECT);
// draw the button from the last line
// ctrl 1 -> line 5 special key
SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE], lpSKT1Ctxt->nButtonHeight[0]); SKT1DrawBitmap(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].x + lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE] / 2 - SKT1_CTRL_BMP_X / 2, lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].y + lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_CTRL_BMP_Y / 2, SKT1_CTRL_BMP_X, SKT1_CTRL_BMP_Y, MAKEINTRESOURCEW(CTRL_T1));
// ctrl 2
SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].x, lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].y, lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE], lpSKT1Ctxt->nButtonHeight[0]); SKT1DrawBitmap(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].x + lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE] / 2 - SKT1_CTRL_BMP_X / 2, lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].y + lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_CTRL_BMP_Y / 2, SKT1_CTRL_BMP_X, SKT1_CTRL_BMP_Y, MAKEINTRESOURCEW(CTRL_T1));
// esc
SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE], lpSKT1Ctxt->nButtonHeight[0]); SKT1DrawBitmap(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].x + lpSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE] / 2 - SKT1_ESC_BMP_X / 2, lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].y + lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_ESC_BMP_Y / 2, SKT1_ESC_BMP_X, SKT1_ESC_BMP_Y, MAKEINTRESOURCEW(ESC_T1));
// alt 1
SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE], lpSKT1Ctxt->nButtonHeight[0]); SKT1DrawBitmap(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].x + lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE] / 2 - SKT1_ALT_BMP_X / 2, lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].y + lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_ALT_BMP_Y / 2, SKT1_ALT_BMP_X, SKT1_ALT_BMP_Y, MAKEINTRESOURCEW(ALT_T1));
// alt 2
SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].x, lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].y, lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE], lpSKT1Ctxt->nButtonHeight[0]); SKT1DrawBitmap(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].x + lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE] / 2 - SKT1_ALT_BMP_X / 2, lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].y + lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_ALT_BMP_Y / 2, SKT1_ALT_BMP_X, SKT1_ALT_BMP_Y, MAKEINTRESOURCEW(ALT_T1));
// space
SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_SPACE_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_SPACE_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE], lpSKT1Ctxt->nButtonHeight[0]);
// line 4
// shift 1
SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE], lpSKT1Ctxt->nButtonHeight[0]); SKT1DrawBitmap(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].x + lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE] / 2 - SKT1_SHIFT_BMP_X / 2, lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].y + lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_SHIFT_BMP_Y / 2, SKT1_SHIFT_BMP_X, SKT1_SHIFT_BMP_Y, MAKEINTRESOURCEW(SHIFT_T1));
// shift 2
SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].x, lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].y, lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE], lpSKT1Ctxt->nButtonHeight[0]); SKT1DrawBitmap(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].x + lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE] / 2 - SKT1_SHIFT_BMP_X / 2, lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].y + lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_SHIFT_BMP_Y / 2, SKT1_SHIFT_BMP_X, SKT1_SHIFT_BMP_Y, MAKEINTRESOURCEW(SHIFT_T1));
// line 3
// caps
SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_CAPS_TYPE], lpSKT1Ctxt->nButtonHeight[0]); SKT1DrawBitmap(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].x + lpSKT1Ctxt->nButtonWidth[SKT1_CAPS_TYPE] / 2 - SKT1_CAPS_BMP_X / 2, lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].y + lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_CAPS_BMP_Y / 2, SKT1_CAPS_BMP_X, SKT1_CAPS_BMP_Y, MAKEINTRESOURCEW(CAPS_T1));
// line 2
// tab
SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_TAB_TYPE], lpSKT1Ctxt->nButtonHeight[0]); SKT1DrawBitmap(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].x + lpSKT1Ctxt->nButtonWidth[SKT1_TAB_TYPE] / 2 - SKT1_TAB_BMP_X / 2, lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].y + lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_TAB_BMP_Y / 2, SKT1_TAB_BMP_X, SKT1_TAB_BMP_Y, MAKEINTRESOURCEW(TAB_T1));
// enter
SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_ENTER_TYPE], lpSKT1Ctxt->nButtonHeight[1]); SKT1DrawBitmap(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].x + lpSKT1Ctxt->nButtonWidth[SKT1_ENTER_TYPE] / 2 - SKT1_ENTER_BMP_X / 2, lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].y + lpSKT1Ctxt->nButtonHeight[1] / 2 - SKT1_ENTER_BMP_Y / 2, SKT1_ENTER_BMP_X, SKT1_ENTER_BMP_Y, MAKEINTRESOURCEW(ENTER_T1));
// line 1
// backspace
SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_BACKSPACE_TYPE], lpSKT1Ctxt->nButtonHeight[0]); SKT1DrawBitmap(hMemDC, lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].x + lpSKT1Ctxt->nButtonWidth[SKT1_BACKSPACE_TYPE] / 2 - SKT1_BACKSPACE_BMP_X / 2, lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].y + lpSKT1Ctxt->nButtonHeight[0] / 2 - SKT1_BACKSPACE_BMP_Y / 2, SKT1_BACKSPACE_BMP_X, SKT1_BACKSPACE_BMP_Y, MAKEINTRESOURCEW(BACK_T1));
// draw letter buttons
for (i = SKT1_LETTER_KEY_NUM - 1; i >= 0 ; i--) { SKT1DrawConvexRect(hMemDC, lpSKT1Ctxt->ptButtonPos[i].x, lpSKT1Ctxt->ptButtonPos[i].y, lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE], lpSKT1Ctxt->nButtonHeight[0]); }
// draw latter label
SKT1DrawLabel(hMemDC, lpSKT1Ctxt, MAKEINTRESOURCEW(LABEL_T1));
DeleteDC(hMemDC);
return; }
/**********************************************************************/ /* CreateT1Window */ /**********************************************************************/ LRESULT CreateT1Window( HWND hSKWnd) { HGLOBAL hSKT1Ctxt; LPSKT1CTXT lpSKT1Ctxt;
hSKT1Ctxt = GlobalAlloc(GHND, sizeof(SKT1CTXT)); if (!hSKT1Ctxt) { return (-1); }
lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt); if (!lpSKT1Ctxt) { GlobalFree(hSKT1Ctxt); return (-1); }
SetWindowLongPtr(hSKWnd, SKT1_CONTEXT, (LONG_PTR)hSKT1Ctxt);
lpSKT1Ctxt->uKeyIndex = SKT1_TOTAL_INDEX; lpSKT1Ctxt->ptSkOffset.x = SKT1_NOT_DRAG; lpSKT1Ctxt->ptSkOffset.y = SKT1_NOT_DRAG; lpSKT1Ctxt->lfCharSet = CHINESEBIG5_CHARSET;
InitSKT1ButtonPos(lpSKT1Ctxt);
InitSKT1Bitmap(hSKWnd, lpSKT1Ctxt);
GlobalUnlock(hSKT1Ctxt);
return (0L); }
/**********************************************************************/ /* SKT1DrawDragBorder() */ /**********************************************************************/ void SKT1DrawDragBorder( HWND hWnd, // window of IME is dragged
LPPOINT lpptCursor, // the cursor position
LPPOINT lpptOffset) // the offset form cursor to window org
{ HDC hDC; int cxBorder, cyBorder; int x, y; RECT rcWnd;
cxBorder = GetSystemMetrics(SM_CXBORDER); // width of border
cyBorder = GetSystemMetrics(SM_CYBORDER); // height of border
x = lpptCursor->x - lpptOffset->x; y = lpptCursor->y - lpptOffset->y;
// check for the max boundary of the display
GetWindowRect(hWnd, &rcWnd);
// draw the moving track
hDC = CreateDC(L"DISPLAY", NULL, NULL, NULL); SelectObject(hDC, GetStockObject(GRAY_BRUSH));
// ->
PatBlt(hDC, x, y, rcWnd.right - rcWnd.left - cxBorder, cyBorder, PATINVERT); // v
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); // v
PatBlt(hDC, x + rcWnd.right - rcWnd.left, y, - cxBorder, rcWnd.bottom - rcWnd.top - cyBorder, PATINVERT);
DeleteDC(hDC); return; }
/**********************************************************************/ /* DestroyT1Window */ /**********************************************************************/ void DestroyT1Window( HWND hSKWnd) { HGLOBAL hSKT1Ctxt; LPSKT1CTXT lpSKT1Ctxt; HWND hUIWnd;
hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT); if (!hSKT1Ctxt) { return; }
lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt); if (!lpSKT1Ctxt) { return; }
if (lpSKT1Ctxt->ptSkOffset.x != SKT1_NOT_DRAG && lpSKT1Ctxt->ptSkOffset.y != SKT1_NOT_DRAG) { SKT1DrawDragBorder(hSKWnd, &lpSKT1Ctxt->ptSkCursor, &lpSKT1Ctxt->ptSkOffset); }
DeleteObject(lpSKT1Ctxt->hSKBitmap);
GlobalUnlock(hSKT1Ctxt); GlobalFree(hSKT1Ctxt);
hUIWnd = GetWindow(hSKWnd, GW_OWNER); if (!hUIWnd) { return; }
SendMessage(hUIWnd, WM_IME_NOTIFY, IMN_SOFTKBDDESTROYED, 0);
return; }
/**********************************************************************/ /* SKT1InvertButton */ /**********************************************************************/ void SKT1InvertButton( HWND hSKWnd, HDC hPaintDC, LPSKT1CTXT lpSKT1Ctxt, UINT uKeyIndex) { HDC hDC; int nWidth, nHeight;
if (uKeyIndex >= SKT1_TOTAL_INDEX) { return; }
nWidth = 0; if (hPaintDC) { hDC = hPaintDC; } else { hDC = GetDC(hSKWnd); }
if (uKeyIndex < SKT1_LETTER_KEY_NUM) { nWidth = lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE]; } else { switch (uKeyIndex) { case SKT1_BACKSPACE_INDEX: nWidth = lpSKT1Ctxt->nButtonWidth[SKT1_BACKSPACE_TYPE]; break; case SKT1_TAB_INDEX: nWidth = lpSKT1Ctxt->nButtonWidth[SKT1_TAB_TYPE]; break; case SKT1_CAPS_INDEX: nWidth = 0; MessageBeep((UINT) -1); break; case SKT1_ENTER_INDEX: nWidth = lpSKT1Ctxt->nButtonWidth[SKT1_ENTER_TYPE]; break; case SKT1_SHIFT_INDEX: case SKT1_SHIFT_INDEX + 1: case SKT1_CTRL_INDEX: case SKT1_CTRL_INDEX + 1: case SKT1_ALT_INDEX: case SKT1_ALT_INDEX + 1: nWidth = 0; MessageBeep((UINT) -1); break; case SKT1_ESC_INDEX: nWidth = lpSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE]; break; case SKT1_SPACE_INDEX: nWidth = lpSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE]; break; default: break; } }
if (uKeyIndex == SKT1_ENTER_INDEX) { nHeight = lpSKT1Ctxt->nButtonHeight[1]; } else { nHeight = lpSKT1Ctxt->nButtonHeight[0]; }
if (nWidth) { // do not reverse border
PatBlt(hDC, lpSKT1Ctxt->ptButtonPos[uKeyIndex].x - 1, lpSKT1Ctxt->ptButtonPos[uKeyIndex].y - 1, nWidth + 2, nHeight + 2, DSTINVERT); }
if (!hPaintDC) { ReleaseDC(hSKWnd, hDC); }
return; }
/**********************************************************************/ /* UpdateSKT1Window */ /**********************************************************************/ void UpdateSKT1Window( HDC hDC, HWND hSKWnd) { HGLOBAL hSKT1Ctxt; LPSKT1CTXT lpSKT1Ctxt; HDC hMemDC; RECT rcClient;
hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT); if (!hSKT1Ctxt) { return; }
lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt); if (!lpSKT1Ctxt) { return; }
hMemDC = CreateCompatibleDC(hDC);
SelectObject(hMemDC, lpSKT1Ctxt->hSKBitmap);
GetClientRect(hSKWnd, &rcClient);
BitBlt(hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hMemDC, 0, 0, SRCCOPY);
DeleteDC(hMemDC);
if (lpSKT1Ctxt->uKeyIndex < SKT1_TOTAL_INDEX) { SKT1InvertButton(hSKWnd, hDC, lpSKT1Ctxt, lpSKT1Ctxt->uKeyIndex); }
GlobalUnlock(hSKT1Ctxt);
return; }
/**********************************************************************/ /* SKT1MousePosition() */ /**********************************************************************/ UINT SKT1MousePosition( LPSKT1CTXT lpSKT1Ctxt, LPPOINT lpptCursor) { int i;
// check letter button
for (i = 0; i < SKT1_LETTER_KEY_NUM; i++) { if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[i].x, lpSKT1Ctxt->ptButtonPos[i].y, lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE], lpSKT1Ctxt->nButtonHeight[0], lpptCursor)) { return i; } }
// backSapce
if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_BACKSPACE_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_BACKSPACE_TYPE], lpSKT1Ctxt->nButtonHeight[0], lpptCursor)) { return SKT1_BACKSPACE_INDEX; }
// tab
if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_TAB_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_TAB_TYPE], lpSKT1Ctxt->nButtonHeight[0], lpptCursor)) { return SKT1_TAB_INDEX; }
// caps
if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_CAPS_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_CAPS_TYPE], lpSKT1Ctxt->nButtonHeight[0], lpptCursor)) { return SKT1_CAPS_INDEX; }
// enter
if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_ENTER_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_ENTER_TYPE], lpSKT1Ctxt->nButtonHeight[1], lpptCursor)) { return SKT1_ENTER_INDEX; }
// shift 1
if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE], lpSKT1Ctxt->nButtonHeight[0], lpptCursor)) { return SKT1_SHIFT_INDEX; }
// shift 2
if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].x, lpSKT1Ctxt->ptButtonPos[SKT1_SHIFT_INDEX + 1].y, lpSKT1Ctxt->nButtonWidth[SKT1_SHIFT_TYPE], lpSKT1Ctxt->nButtonHeight[0], lpptCursor)) { return SKT1_SHIFT_INDEX; }
// ctrl 1
if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE], lpSKT1Ctxt->nButtonHeight[0], lpptCursor)) { return SKT1_CTRL_INDEX; }
// ctrl 2
if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].x, lpSKT1Ctxt->ptButtonPos[SKT1_CTRL_INDEX + 1].y, lpSKT1Ctxt->nButtonWidth[SKT1_CTRL_TYPE], lpSKT1Ctxt->nButtonHeight[0], lpptCursor)) { return SKT1_CTRL_INDEX; }
// alt 1
if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE], lpSKT1Ctxt->nButtonHeight[0], lpptCursor)) { return SKT1_ALT_INDEX; }
// alt 2
if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].x, lpSKT1Ctxt->ptButtonPos[SKT1_ALT_INDEX + 1].y, lpSKT1Ctxt->nButtonWidth[SKT1_ALT_TYPE], lpSKT1Ctxt->nButtonHeight[0], lpptCursor)) { return SKT1_ALT_INDEX; }
// esc
if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_ESC_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE], lpSKT1Ctxt->nButtonHeight[0], lpptCursor)) { return SKT1_ESC_INDEX; }
// space
if (ImmPtInRect(lpSKT1Ctxt->ptButtonPos[SKT1_SPACE_INDEX].x, lpSKT1Ctxt->ptButtonPos[SKT1_SPACE_INDEX].y, lpSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE], lpSKT1Ctxt->nButtonHeight[0], lpptCursor)) { return SKT1_SPACE_INDEX; }
return SKT1_TOTAL_INDEX; // This means out of range
}
/**********************************************************************/ /* SKT1IsValidButton */ /**********************************************************************/ BOOL SKT1IsValidButton( UINT uKeyIndex, LPSKT1CTXT lpSKT1Ctxt) { BOOL fRet;
if (uKeyIndex < SKT1_LETTER_KEY_NUM) { if (lpSKT1Ctxt->wCodeTable[uKeyIndex]) { return TRUE; } else { return FALSE; } }
// special key
switch (uKeyIndex) { case SKT1_BACKSPACE_INDEX: case SKT1_TAB_INDEX: case SKT1_ENTER_INDEX: case SKT1_ESC_INDEX: case SKT1_SPACE_INDEX: fRet = TRUE; break; default: fRet = FALSE; break; }
return fRet; }
/**********************************************************************/ /* SKT1SetCursor */ /**********************************************************************/ BOOL SKT1SetCursor( HWND hSKWnd, LPARAM lParam) { HGLOBAL hSKT1Ctxt; LPSKT1CTXT lpSKT1Ctxt; UINT uKeyIndex; RECT rcWnd; RECT rcWork; SIZE szWork; extern void GetAllMonitorSize(LPRECT lprc);
hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT); if (!hSKT1Ctxt) { return (FALSE); }
lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt); if (!lpSKT1Ctxt) { return (FALSE); }
if (lpSKT1Ctxt->ptSkOffset.x != SKT1_NOT_DRAG && lpSKT1Ctxt->ptSkOffset.y != SKT1_NOT_DRAG) { // in drag operation
SetCursor(LoadCursor(NULL, IDC_SIZEALL)); goto UnlockSKT1Ctxt; }
GetCursorPos(&lpSKT1Ctxt->ptSkCursor); ScreenToClient(hSKWnd, &lpSKT1Ctxt->ptSkCursor);
uKeyIndex = SKT1MousePosition(lpSKT1Ctxt, &lpSKT1Ctxt->ptSkCursor);
if (uKeyIndex < SKT1_TOTAL_INDEX) { SetCursor(LoadCursor(NULL, IDC_HAND)); } else { SetCursor(LoadCursor(NULL, IDC_SIZEALL)); }
if (HIWORD(lParam) != WM_LBUTTONDOWN) { goto UnlockSKT1Ctxt; }
SetCapture(hSKWnd);
if (lpSKT1Ctxt->uKeyIndex < SKT1_TOTAL_INDEX) { UINT uVirtKey;
uVirtKey = bSKT1VirtKey[lpSKT1Ctxt->uKeyIndex]; keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey], (DWORD)KEYEVENTF_KEYUP, 0); SKT1InvertButton(hSKWnd, NULL, lpSKT1Ctxt, lpSKT1Ctxt->uKeyIndex); lpSKT1Ctxt->uKeyIndex = SKT1_TOTAL_INDEX; }
if (uKeyIndex < SKT1_TOTAL_INDEX) { UINT uVirtKey;
if (SKT1IsValidButton(uKeyIndex, lpSKT1Ctxt)) { uVirtKey = bSKT1VirtKey[uKeyIndex]; keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey], 0, 0); lpSKT1Ctxt->uKeyIndex = uKeyIndex; SKT1InvertButton(hSKWnd, NULL, lpSKT1Ctxt, lpSKT1Ctxt->uKeyIndex); } else { MessageBeep((UINT)-1); } goto UnlockSKT1Ctxt; }
GetAllMonitorSize(&rcWork); szWork.cx = rcWork.right - rcWork.left; szWork.cy = rcWork.bottom - rcWork.top;
GetCursorPos(&lpSKT1Ctxt->ptSkCursor); GetWindowRect(hSKWnd, &rcWnd); lpSKT1Ctxt->ptSkOffset.x = lpSKT1Ctxt->ptSkCursor.x - rcWnd.left; lpSKT1Ctxt->ptSkOffset.y = lpSKT1Ctxt->ptSkCursor.y - rcWnd.top;
SKT1DrawDragBorder(hSKWnd, &lpSKT1Ctxt->ptSkCursor, &lpSKT1Ctxt->ptSkOffset);
UnlockSKT1Ctxt: GlobalUnlock(hSKT1Ctxt);
return (TRUE); }
/**********************************************************************/ /* SKT1MouseMove */ /**********************************************************************/ BOOL SKT1MouseMove( HWND hSKWnd) { HGLOBAL hSKT1Ctxt; LPSKT1CTXT lpSKT1Ctxt;
hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT); if (!hSKT1Ctxt) { return FALSE; }
lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt); if (!lpSKT1Ctxt) { return FALSE; }
if (lpSKT1Ctxt->ptSkOffset.x == SKT1_NOT_DRAG || lpSKT1Ctxt->ptSkOffset.y == SKT1_NOT_DRAG) { GlobalUnlock(hSKT1Ctxt); return FALSE; }
SKT1DrawDragBorder(hSKWnd, &lpSKT1Ctxt->ptSkCursor, &lpSKT1Ctxt->ptSkOffset);
GetCursorPos(&lpSKT1Ctxt->ptSkCursor);
SKT1DrawDragBorder(hSKWnd, &lpSKT1Ctxt->ptSkCursor, &lpSKT1Ctxt->ptSkOffset);
GlobalUnlock(hSKT1Ctxt);
return TRUE; }
/**********************************************************************/ /* SKT1ButtonUp */ /**********************************************************************/ BOOL SKT1ButtonUp( HWND hSKWnd) { HGLOBAL hSKT1Ctxt; LPSKT1CTXT lpSKT1Ctxt; BOOL fRet; POINT pt; HWND hUIWnd; HIMC hIMC; LPINPUTCONTEXT lpIMC;
fRet = FALSE;
if (IsWndEqual(GetCapture(), hSKWnd)) { ReleaseCapture(); }
hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT); if (!hSKT1Ctxt) { return (fRet); }
lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt); if (!lpSKT1Ctxt) { return (fRet); }
if (lpSKT1Ctxt->uKeyIndex < SKT1_TOTAL_INDEX) { UINT uVirtKey;
uVirtKey = bSKT1VirtKey[lpSKT1Ctxt->uKeyIndex]; keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey], (DWORD)KEYEVENTF_KEYUP, 0); SKT1InvertButton(hSKWnd, NULL, lpSKT1Ctxt, lpSKT1Ctxt->uKeyIndex); lpSKT1Ctxt->uKeyIndex = SKT1_TOTAL_INDEX; fRet = TRUE; goto UnlockSKT1Context; }
if (lpSKT1Ctxt->ptSkOffset.x == SKT1_NOT_DRAG || lpSKT1Ctxt->ptSkOffset.y == SKT1_NOT_DRAG) { goto UnlockSKT1Context; }
SKT1DrawDragBorder(hSKWnd, &lpSKT1Ctxt->ptSkCursor, &lpSKT1Ctxt->ptSkOffset);
pt.x = lpSKT1Ctxt->ptSkCursor.x - lpSKT1Ctxt->ptSkOffset.x, pt.y = lpSKT1Ctxt->ptSkCursor.y - lpSKT1Ctxt->ptSkOffset.y,
SetWindowPos(hSKWnd, (HWND)NULL, pt.x, pt.y, 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
lpSKT1Ctxt->ptSkOffset.x = SKT1_NOT_DRAG; lpSKT1Ctxt->ptSkOffset.y = SKT1_NOT_DRAG;
lpSKT1Ctxt->uKeyIndex = SKT1_TOTAL_INDEX;
fRet = TRUE;
hUIWnd = GetWindow(hSKWnd, GW_OWNER);
hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC); if (!hIMC) { goto UnlockSKT1Context; }
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC); if (!lpIMC) { goto UnlockSKT1Context; }
lpIMC->ptSoftKbdPos.x = pt.x; lpIMC->ptSoftKbdPos.y = pt.y; lpIMC->fdwInit |= INIT_SOFTKBDPOS;
ImmUnlockIMC(hIMC);
UnlockSKT1Context: GlobalUnlock(hSKT1Ctxt);
return (fRet); }
/**********************************************************************/ /* SetSKT1Data */ /**********************************************************************/ LRESULT SetSKT1Data( HWND hSKWnd, LPSOFTKBDDATA lpSoftKbdData) { HGLOBAL hSKT1Ctxt; LPSKT1CTXT lpSKT1Ctxt; HDC hDC, hMemDC; HGDIOBJ hOldFont; int i;
hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT); if (!hSKT1Ctxt) { return (1); }
lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt); if (!lpSKT1Ctxt) { return (1); }
hDC = GetDC(hSKWnd); hMemDC = CreateCompatibleDC(hDC); ReleaseDC(hSKWnd, hDC); SelectObject(hMemDC, lpSKT1Ctxt->hSKBitmap);
SetBkColor(hMemDC, RGB(0xC0, 0xC0, 0xC0));
if (lpSKT1Ctxt->lfCharSet != DEFAULT_CHARSET) { LOGFONT lfFont; CopyMemory(&lfFont, &lfSKT1Font, sizeof (LOGFONT)); lfFont.lfCharSet = (BYTE)lpSKT1Ctxt->lfCharSet; hOldFont = (HFONT)SelectObject(hMemDC, CreateFontIndirect(&lfFont)); } else { hOldFont = (HFONT)SelectObject(hMemDC, CreateFontIndirect(&lfSKT1Font)); }
for (i = 0; i < SKT1_LETTER_KEY_NUM; i++) { int cbCount; RECT rcOpaque;
lpSKT1Ctxt->wCodeTable[i] = lpSoftKbdData->wCode[0][bSKT1VirtKey[i]];
cbCount = (lpSKT1Ctxt->wCodeTable[i] == 0) ? 0 : 1;
rcOpaque.left = lpSKT1Ctxt->ptButtonPos[i].x + SKT1_LABEL_BMP_X - SKT1_XOVERLAP; rcOpaque.top = lpSKT1Ctxt->ptButtonPos[i].y + SKT1_LABEL_BMP_Y;
rcOpaque.right = rcOpaque.left + lpSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] - SKT1_LABEL_BMP_X + SKT1_XOVERLAP; rcOpaque.bottom = rcOpaque.top + lpSKT1Ctxt->nButtonHeight[0] - SKT1_LABEL_BMP_Y;
ExtTextOut(hMemDC, rcOpaque.left, rcOpaque.top, ETO_OPAQUE, &rcOpaque, (LPWSTR)&lpSKT1Ctxt->wCodeTable[i], cbCount, NULL); }
DeleteObject(SelectObject(hMemDC, hOldFont));
DeleteDC(hMemDC);
GlobalUnlock(hSKT1Ctxt);
return (0); }
/**********************************************************************/ /* SKWndProcT1 */ /**********************************************************************/ LRESULT CALLBACK SKWndProcT1( HWND hSKWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: return CreateT1Window(hSKWnd); case WM_DESTROY: DestroyT1Window(hSKWnd); break; case WM_PAINT: { HDC hDC; PAINTSTRUCT ps;
hDC = BeginPaint(hSKWnd, &ps); UpdateSKT1Window(hDC, hSKWnd); EndPaint(hSKWnd, &ps); } break; case WM_SETCURSOR: if (!SKT1SetCursor(hSKWnd, lParam)) { return DefWindowProc(hSKWnd, uMsg, wParam, lParam); } break; case WM_MOUSEMOVE: if (!SKT1MouseMove(hSKWnd)) { return DefWindowProc(hSKWnd, uMsg, wParam, lParam); } break; case WM_LBUTTONUP: if (!SKT1ButtonUp(hSKWnd)) { return DefWindowProc(hSKWnd, uMsg, wParam, lParam); } break; case WM_MOUSEACTIVATE: return (MA_NOACTIVATE); case WM_SHOWWINDOW: if (lParam != 0) { } else if ((BOOL)wParam == TRUE) { } else { // we want to hide the soft keyboard on mouse button down
SKT1ButtonUp(hSKWnd); }
return DefWindowProc(hSKWnd, uMsg, wParam, lParam);
case WM_IME_CONTROL: switch (wParam) { case IMC_GETSOFTKBDFONT: { HGLOBAL hSKT1Ctxt; LPSKT1CTXT lpSKT1Ctxt; BYTE lfCharSet;
hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT); if (!hSKT1Ctxt) { return (1); }
lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt); if (!lpSKT1Ctxt) { return (1); }
lfCharSet = (BYTE)lpSKT1Ctxt->lfCharSet;
GlobalUnlock(hSKT1Ctxt);
*(LPLOGFONT)lParam = lfSKT1Font;
if (lfCharSet != DEFAULT_CHARSET) { ((LPLOGFONT)lParam)->lfCharSet = lfCharSet; }
return (0); } break; case IMC_SETSOFTKBDFONT: { // in differet version of Windows
if (lfSKT1Font.lfCharSet != ((LPLOGFONT)lParam)->lfCharSet) { HGLOBAL hSKT1Ctxt; LPSKT1CTXT lpSKT1Ctxt;
hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT); if (!hSKT1Ctxt) { return 1; }
lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt); if (!lpSKT1Ctxt) { return 1; }
lpSKT1Ctxt->lfCharSet = ((LPLOGFONT)lParam)->lfCharSet;
GlobalUnlock(hSKT1Ctxt); } } break; case IMC_GETSOFTKBDPOS: { RECT rcWnd;
GetWindowRect(hSKWnd, &rcWnd);
return MAKELRESULT(rcWnd.left, rcWnd.top); } break; case IMC_SETSOFTKBDPOS: { POINT ptSoftKbdPos; HWND hUIWnd; HIMC hIMC; LPINPUTCONTEXT lpIMC;
ptSoftKbdPos.x = ((LPPOINTS)lParam)->x; ptSoftKbdPos.y = ((LPPOINTS)lParam)->y;
SetWindowPos(hSKWnd, NULL, ptSoftKbdPos.x, ptSoftKbdPos.y, 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
// Here we want to get - the owner or parent window
hUIWnd = GetParent(hSKWnd);
if (!hUIWnd) { return (1); }
hIMC = (HIMC) GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
if (!hIMC) { return (1); }
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) { return (1); }
lpIMC->ptSoftKbdPos = ptSoftKbdPos;
ImmUnlockIMC(hIMC);
return (0); } break; case IMC_SETSOFTKBDDATA: { LRESULT lRet;
lRet = SetSKT1Data(hSKWnd, (LPSOFTKBDDATA)lParam); if (!lRet) { InvalidateRect(hSKWnd, NULL, FALSE); PostMessage(hSKWnd, WM_PAINT, 0, 0); } return (lRet); } break; case IMC_GETSOFTKBDSUBTYPE: case IMC_SETSOFTKBDSUBTYPE: { HGLOBAL hSKT1Ctxt; LPSKT1CTXT lpSKT1Ctxt; LRESULT lRet;
lRet = -1;
hSKT1Ctxt = (HGLOBAL)GetWindowLongPtr(hSKWnd, SKT1_CONTEXT); if (!hSKT1Ctxt) { return (lRet); }
lpSKT1Ctxt = (LPSKT1CTXT)GlobalLock(hSKT1Ctxt); if (!lpSKT1Ctxt) { return (lRet); }
if (wParam == IMC_GETSOFTKBDSUBTYPE) { lRet = lpSKT1Ctxt->uSubType; } else if (wParam == IMC_SETSOFTKBDSUBTYPE) { lRet = lpSKT1Ctxt->uSubType; lpSKT1Ctxt->uSubType = (UINT)lParam; } else { lRet = -1; }
GlobalUnlock(hSKT1Ctxt); return (lRet); } break; default: break; } break; default: return DefWindowProc(hSKWnd, uMsg, wParam, lParam); }
return (0L); }
|