Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1464 lines
48 KiB

/**************************************************************************\
* 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);
}