Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1163 lines
31 KiB

/**************************************************************************\
* Module Name: sftkbdt1.c
*
* Copyright (c) Microsoft Corp. 1995-96 All Rights Reserved
*
* Soft keyboard support for Traditional Chinese
*
* History:
* 02-Jan-1996 wkwok - ported from Win95
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
BYTE SKT1VirtKey[SKT1_ALL_KEYS] = { // Virtual Key for Letter Buttons
// 1 2 3 4 5 6
'1', '2', '3', '4', '5', '6',
// 7 8 9 0 -
'7', '8', '9', '0', VK_OEM_MINUS,
// = \\ q w
VK_OEM_EQUAL, VK_OEM_BSLASH, 'Q', 'W',
// e r t y u i
'E', 'R', 'T', 'Y', 'U', 'I',
// o p [ ]
'O', 'P', VK_OEM_LBRACKET, VK_OEM_RBRACKET,
// a s d f g h
'A', 'S', 'D', 'F', 'G', 'H',
// j k l ;
'J', 'K', 'L', VK_OEM_SEMICLN,
// ' z x c v
VK_OEM_QUOTE, 'Z', 'X', 'C', 'V',
// b n m ,
'B', 'N', 'M', VK_OEM_COMMA,
// . /
VK_OEM_PERIOD, VK_OEM_SLASH, VK_ESCAPE,
// ' ' \b
VK_SPACE, VK_BACK
};
WCHAR szEscBmp[] = L"Esc";
WCHAR szBackSpBmp[] = L"BackSp";
/**********************************************************************\
* InitSKT1ButtonPos
*
\**********************************************************************/
VOID InitSKT1ButtonPos(
PSKT1CTXT pSKT1Ctxt)
{
int nButton;
HDC hDC;
TEXTMETRIC tm;
int i, j;
int xInLastRow;
hDC = GetDC((HWND)NULL);
GetTextMetrics(hDC, &tm);
ReleaseDC((HWND)NULL, hDC);
pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] = (tm.tmAveCharWidth + 1) * 2;
pSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE] =
pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] * SKT1_ESC_TIMES;
pSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE] =
pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] * SKT1_SPACE_TIMES;
pSKT1Ctxt->nButtonWidth[SKT1_BACKSP_TYPE] =
pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] * SKT1_BACKSP_TIMES;
pSKT1Ctxt->nButtonHeight = tm.tmHeight;
nButton = 0;
for (i = 0; i < ROW_T1 - 1; i++) {
int xRowStart;
xRowStart = (pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + XIN_T1) *
i / 2 + XOUT_T1 + gptRaiseEdge.x;
for (j = 0; j < COL_T1 - i; j++, nButton++) {
pSKT1Ctxt->ptButtonPos[nButton].x = xRowStart + j *
(pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + XIN_T1);
pSKT1Ctxt->ptButtonPos[nButton].y = YOUT_T1 + gptRaiseEdge.y +
i * (pSKT1Ctxt->nButtonHeight + YIN_T1);
}
}
// special buttons, ESC, SPACE, and BACKSPACE
// calculate the total gap then / 2
xInLastRow = pSKT1Ctxt->ptButtonPos[nButton - 1].x +
pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] -
pSKT1Ctxt->ptButtonPos[0].x -
pSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE] -
pSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE] -
pSKT1Ctxt->nButtonWidth[SKT1_BACKSP_TYPE];
xInLastRow /= 2;
pSKT1Ctxt->ptButtonPos[nButton].x = XOUT_T1 + gptRaiseEdge.x;
pSKT1Ctxt->ptButtonPos[nButton].y =
pSKT1Ctxt->ptButtonPos[nButton - 1].y +
pSKT1Ctxt->nButtonHeight + YIN_T1;
++nButton;
pSKT1Ctxt->ptButtonPos[nButton].x =
pSKT1Ctxt->ptButtonPos[nButton - 1].x +
pSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE] +
xInLastRow;
pSKT1Ctxt->ptButtonPos[nButton].y =
pSKT1Ctxt->ptButtonPos[nButton - 1].y;
++nButton;
pSKT1Ctxt->ptButtonPos[nButton].x =
pSKT1Ctxt->ptButtonPos[nButton - 1].x +
pSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE] +
xInLastRow;
pSKT1Ctxt->ptButtonPos[nButton].y =
pSKT1Ctxt->ptButtonPos[nButton - 1].y;
return;
}
/**********************************************************************\
* SKT1DrawConvexRect --- 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 SKT1DrawConvexRect(
HDC hDC,
int x,
int y,
int nWidth,
int nHeight)
{
SelectObject(hDC, GetStockObject(BLACK_PEN));
SelectObject(hDC, GetStockObject(LTGRAY_BRUSH));
Rectangle(hDC, x, y, x + nWidth, y + nHeight);
x++;
y++;
nWidth -= 2;
nHeight -= 2;
// 1
PatBlt(hDC, x, y + nHeight, 1, -nHeight, WHITENESS);
PatBlt(hDC, x, y, nWidth , 1, WHITENESS);
// 2
SelectObject(hDC, GetStockObject(GRAY_BRUSH));
PatBlt(hDC, x, y + nHeight, nWidth, -1, PATCOPY);
PatBlt(hDC, x + nWidth, y + nHeight - 1, -1, -nHeight, PATCOPY);
#if 0
x++;
y++;
nWidth -= 2;
nHeight -= 2;
// 3
PatBlt(hDC, x + nWidth - 1, y, -nWidth, 1, WHITENESS);
PatBlt(hDC, x, y, 1, nHeight, WHITENESS);
// 4
SelectObject(hDC, GetStockObject(GRAY_BRUSH));
PatBlt(hDC, x + nWidth, y, -1, nHeight, PATCOPY);
PatBlt(hDC, x + nWidth - 1, y + nHeight, -nWidth, -1, PATCOPY);
#endif
return;
}
/**********************************************************************\
* SKT1DrawBitmap --- Draw bitmap within rectangle
*
\**********************************************************************/
VOID SKT1DrawBitmap(
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);
DeleteObject(hBitmap);
DeleteDC(hMemDC);
return;
}
/**********************************************************************\
* InitSKT1Bitmap -- init bitmap
*
\**********************************************************************/
VOID InitSKT1Bitmap(
HWND hSKWnd,
PSKT1CTXT pSKT1Ctxt)
{
HDC hDC, hMemDC;
RECT rcClient;
int i;
hDC = GetDC(hSKWnd);
hMemDC = CreateCompatibleDC(hDC);
GetClientRect(hSKWnd, &rcClient);
pSKT1Ctxt->hSKBitmap = CreateCompatibleBitmap(hDC,
rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top);
ReleaseDC(hSKWnd, hDC);
SelectObject(hMemDC, pSKT1Ctxt->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 letter buttons
for (i = 0; i < SKT1_LETTER_KEYS; i++) {
SKT1DrawConvexRect(hMemDC,
pSKT1Ctxt->ptButtonPos[i].x - 3,
pSKT1Ctxt->ptButtonPos[i].y - 3,
pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + 6,
pSKT1Ctxt->nButtonHeight + 6);
}
#if 0
// draw special buttons
for (; i < SKT1_ALL_KEYS; i++) {
SKT1DrawConvexRect(hMemDC,
pSKT1Ctxt->ptButtonPos[i].x - 3,
pSKT1Ctxt->ptButtonPos[i].y - 3,
pSKT1Ctxt->nButtonWidth[i - SKT1_ESC + 1] + 6,
pSKT1Ctxt->nButtonHeight + 6);
}
#endif
// draw Esc key
SKT1DrawConvexRect(hMemDC,
pSKT1Ctxt->ptButtonPos[SKT1_ESC].x - 3,
pSKT1Ctxt->ptButtonPos[SKT1_ESC].y - 3,
pSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE] + 6,
pSKT1Ctxt->nButtonHeight + 6);
SKT1DrawBitmap(hMemDC,
pSKT1Ctxt->ptButtonPos[SKT1_ESC].x +
pSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE] / 2 - XESC_BMP_T1 / 2,
pSKT1Ctxt->ptButtonPos[SKT1_ESC].y +
pSKT1Ctxt->nButtonHeight / 2 - YESC_BMP_T1 / 2,
XESC_BMP_T1, YESC_BMP_T1,
szEscBmp);
// draw space key
SKT1DrawConvexRect(hMemDC,
pSKT1Ctxt->ptButtonPos[SKT1_SPACE].x - 3,
pSKT1Ctxt->ptButtonPos[SKT1_SPACE].y - 3,
pSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE] + 6,
pSKT1Ctxt->nButtonHeight + 6);
// draw BackSp key
SKT1DrawConvexRect(hMemDC,
pSKT1Ctxt->ptButtonPos[SKT1_BACKSP].x - 3,
pSKT1Ctxt->ptButtonPos[SKT1_BACKSP].y - 3,
pSKT1Ctxt->nButtonWidth[SKT1_BACKSP_TYPE] + 6,
pSKT1Ctxt->nButtonHeight + 6);
SKT1DrawBitmap(hMemDC,
pSKT1Ctxt->ptButtonPos[SKT1_BACKSP].x +
pSKT1Ctxt->nButtonWidth[SKT1_BACKSP_TYPE] / 2 - XBACKSP_BMP_T1 / 2,
pSKT1Ctxt->ptButtonPos[SKT1_BACKSP].y +
pSKT1Ctxt->nButtonHeight / 2 - YBACKSP_BMP_T1 / 2,
XBACKSP_BMP_T1, YBACKSP_BMP_T1,
szBackSpBmp);
DeleteDC(hMemDC);
return;
}
/**********************************************************************\
* CreateT1Window
*
* Init softkeyboard context and bitmap
*
\**********************************************************************/
LRESULT CreateT1Window(
HWND hSKWnd)
{
HGLOBAL hSKT1Ctxt;
PSKT1CTXT pSKT1Ctxt;
hSKT1Ctxt = GlobalAlloc(GHND, sizeof(SKT1CTXT));
if (!hSKT1Ctxt) {
return (-1);
}
pSKT1Ctxt = (PSKT1CTXT)GlobalLock(hSKT1Ctxt);
if (!pSKT1Ctxt) {
GlobalFree(hSKT1Ctxt);
return (-1);
}
SetWindowLong(hSKWnd, SKT1_CONTEXT, (LONG)hSKT1Ctxt);
InitSKT1ButtonPos(pSKT1Ctxt);
InitSKT1Bitmap(hSKWnd, pSKT1Ctxt);
pSKT1Ctxt->ptSkOffset.x = SKT1_NOT_DRAG;
pSKT1Ctxt->ptSkOffset.y = SKT1_NOT_DRAG;
pSKT1Ctxt->uKeyIndex = SKT1_OUT_OF_RANGE;
pSKT1Ctxt->lfCharSet = DEFAULT_CHARSET;
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
*
* Destroy softkeyboard context and bitmap
*
\**********************************************************************/
VOID DestroyT1Window(
HWND hSKWnd)
{
HGLOBAL hSKT1Ctxt;
PSKT1CTXT pSKT1Ctxt;
HWND hUIWnd;
hSKT1Ctxt = (HGLOBAL)GetWindowLong(hSKWnd, SKT1_CONTEXT);
if (!hSKT1Ctxt) {
return;
}
pSKT1Ctxt = (PSKT1CTXT)GlobalLock(hSKT1Ctxt);
if (!pSKT1Ctxt) {
return;
}
if (pSKT1Ctxt->ptSkOffset.x == SKT1_NOT_DRAG) {
} else if (pSKT1Ctxt->ptSkOffset.y == SKT1_NOT_DRAG) {
} else {
SKT1DrawDragBorder(hSKWnd, &pSKT1Ctxt->ptSkCursor,
&pSKT1Ctxt->ptSkOffset);
}
DeleteObject(pSKT1Ctxt->hSKBitmap);
GlobalUnlock(hSKT1Ctxt);
GlobalFree(hSKT1Ctxt);
hUIWnd = GetWindow(hSKWnd, GW_OWNER);
if (!hUIWnd) {
return;
}
SendMessage(hUIWnd, WM_IME_NOTIFY, IMN_SOFTKBDDESTROYED, 0);
return;
}
/**********************************************************************\
* SKT1InvertButton
*
\**********************************************************************/
void PASCAL SKT1InvertButton(
HWND hSKWnd,
HDC hPaintDC,
PSKT1CTXT pSKT1Ctxt,
UINT uKeyIndex)
{
int nWidth;
HDC hDC;
if (uKeyIndex >= SKT1_OUT_OF_RANGE) {
return;
}
nWidth = 0;
if (hPaintDC) {
hDC = hPaintDC;
} else {
hDC = GetDC(hSKWnd);
}
if (uKeyIndex < SKT1_ESC) {
nWidth = pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE];
} else {
switch (uKeyIndex) {
case SKT1_ESC:
nWidth = pSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE];
break;
case SKT1_SPACE:
nWidth = pSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE];
break;
case SKT1_BACKSP:
nWidth = pSKT1Ctxt->nButtonWidth[SKT1_BACKSP_TYPE];
break;
default:
break;
}
}
if (nWidth) {
// do not reverse border
PatBlt(hDC, pSKT1Ctxt->ptButtonPos[uKeyIndex].x - 2,
pSKT1Ctxt->ptButtonPos[uKeyIndex].y - 2,
nWidth + 4, pSKT1Ctxt->nButtonHeight + 4, DSTINVERT);
}
if (!hPaintDC) {
ReleaseDC(hSKWnd, hDC);
}
return;
}
/**********************************************************************\
* UpdateSKT1Window -- update softkeyboard
*
\**********************************************************************/
VOID UpdateSKT1Window(
HDC hDC,
HWND hSKWnd)
{
HGLOBAL hSKT1Ctxt;
PSKT1CTXT pSKT1Ctxt;
HDC hMemDC;
RECT rcClient;
hSKT1Ctxt = (HGLOBAL)GetWindowLong(hSKWnd, SKT1_CONTEXT);
if (!hSKT1Ctxt) {
return;
}
pSKT1Ctxt = (PSKT1CTXT)GlobalLock(hSKT1Ctxt);
if (!pSKT1Ctxt) {
return;
}
hMemDC = CreateCompatibleDC(hDC);
SelectObject(hMemDC, pSKT1Ctxt->hSKBitmap);
GetClientRect(hSKWnd, &rcClient);
BitBlt(hDC, 0, 0, rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top,
hMemDC, 0, 0, SRCCOPY);
DeleteDC(hMemDC);
if (pSKT1Ctxt->uKeyIndex < SKT1_OUT_OF_RANGE) {
SKT1InvertButton(hSKWnd, hDC, pSKT1Ctxt, pSKT1Ctxt->uKeyIndex);
}
GlobalUnlock(hSKT1Ctxt);
return;
}
/**********************************************************************\
* SKT1MousePosition() -- judge the cursor position
*
\**********************************************************************/
UINT SKT1MousePosition(
PSKT1CTXT pSKT1Ctxt,
LPPOINT lpptCursor)
{
int nRem;
int nRow;
if (lpptCursor->y < (YOUT_T1 + gptRaiseEdge.y)) {
return (SKT1_OUT_OF_RANGE);
}
nRem = (lpptCursor->y - YOUT_T1 - gptRaiseEdge.y) %
(pSKT1Ctxt->nButtonHeight + YIN_T1);
// fall in YIN_T1
if (nRem > pSKT1Ctxt->nButtonHeight) {
return (SKT1_OUT_OF_RANGE);
}
nRow = (lpptCursor->y - YOUT_T1 - gptRaiseEdge.y) /
(pSKT1Ctxt->nButtonHeight + YIN_T1);
if (nRow >= ROW_T1) {
return (SKT1_OUT_OF_RANGE);
}
if (nRow < ROW_T1 - 1) { // letter key part
UINT uKeyIndex;
int nCol;
// start index of this row
uKeyIndex = ((COL_T1) + (COL_T1 - nRow + 1)) * nRow / 2;
// x coor don't fall in left margin
if (lpptCursor->x < pSKT1Ctxt->ptButtonPos[uKeyIndex].x) {
return (SKT1_OUT_OF_RANGE);
}
nRem = (lpptCursor->x - pSKT1Ctxt->ptButtonPos[uKeyIndex].x) %
(pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + XIN_T1);
// fall in XIN_T1
if (nRem > pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE]) {
return (SKT1_OUT_OF_RANGE);
}
nCol = (lpptCursor->x - pSKT1Ctxt->ptButtonPos[uKeyIndex].x) /
(pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE] + XIN_T1);
if (nCol >= COL_T1 - nRow) {
return (SKT1_OUT_OF_RANGE);
}
return (uKeyIndex + nCol);
}
if (lpptCursor->x < pSKT1Ctxt->ptButtonPos[SKT1_ESC].x) {
return (SKT1_OUT_OF_RANGE);
}
if (lpptCursor->x <= pSKT1Ctxt->ptButtonPos[SKT1_ESC].x +
pSKT1Ctxt->nButtonWidth[SKT1_ESC_TYPE]) {
return (SKT1_ESC);
}
if (lpptCursor->x < pSKT1Ctxt->ptButtonPos[SKT1_SPACE].x) {
return (SKT1_OUT_OF_RANGE);
}
if (lpptCursor->x <= pSKT1Ctxt->ptButtonPos[SKT1_SPACE].x +
pSKT1Ctxt->nButtonWidth[SKT1_SPACE_TYPE]) {
return (SKT1_SPACE);
}
if (lpptCursor->x < pSKT1Ctxt->ptButtonPos[SKT1_BACKSP].x) {
return (SKT1_OUT_OF_RANGE);
}
if (lpptCursor->x <= pSKT1Ctxt->ptButtonPos[SKT1_BACKSP].x +
pSKT1Ctxt->nButtonWidth[SKT1_BACKSP_TYPE]) {
return (SKT1_BACKSP);
}
return (SKT1_OUT_OF_RANGE);
}
/**********************************************************************\
* SKT1SetCursor
*
\**********************************************************************/
BOOL SKT1SetCursor(
HWND hSKWnd,
LPARAM lParam)
{
HGLOBAL hSKT1Ctxt;
PSKT1CTXT pSKT1Ctxt;
UINT uKeyIndex;
RECT rcWnd;
hSKT1Ctxt = (HGLOBAL)GetWindowLong(hSKWnd, SKT1_CONTEXT);
if (!hSKT1Ctxt) {
return (FALSE);
}
pSKT1Ctxt = (PSKT1CTXT)GlobalLock(hSKT1Ctxt);
if (!pSKT1Ctxt) {
return (FALSE);
}
if (pSKT1Ctxt->ptSkOffset.x == SKT1_NOT_DRAG) {
} else if (pSKT1Ctxt->ptSkOffset.x == SKT1_NOT_DRAG) {
} else {
// in drag operation
SetCursor(LoadCursor(NULL, IDC_SIZEALL));
GlobalUnlock(hSKT1Ctxt);
return (TRUE);
}
GetCursorPos(&pSKT1Ctxt->ptSkCursor);
ScreenToClient(hSKWnd, &pSKT1Ctxt->ptSkCursor);
uKeyIndex = SKT1MousePosition(pSKT1Ctxt, &pSKT1Ctxt->ptSkCursor);
if (uKeyIndex < SKT1_OUT_OF_RANGE) {
SetCursor(LoadCursor(ghInst, gszHandCursor));
} else {
SetCursor(LoadCursor(NULL, IDC_SIZEALL));
}
if (HIWORD(lParam) != WM_LBUTTONDOWN) {
GlobalUnlock(hSKT1Ctxt);
return (TRUE);
}
SetCapture(hSKWnd);
if (pSKT1Ctxt->uKeyIndex < SKT1_OUT_OF_RANGE) {
UINT uVirtKey;
uVirtKey = SKT1VirtKey[pSKT1Ctxt->uKeyIndex];
keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey],
(DWORD)KEYEVENTF_KEYUP, (DWORD)NULL);
SKT1InvertButton(hSKWnd, NULL, pSKT1Ctxt, pSKT1Ctxt->uKeyIndex);
pSKT1Ctxt->uKeyIndex = SKT1_OUT_OF_RANGE;
}
if (uKeyIndex < SKT1_OUT_OF_RANGE) {
UINT uVirtKey;
if (uKeyIndex >= SKT1_LETTER_KEYS) { // key is not a letter key
} else if (!pSKT1Ctxt->wCodeTbl[uKeyIndex]) {
MessageBeep((UINT)-1);
GlobalUnlock(hSKT1Ctxt);
return (TRUE);
}
uVirtKey = SKT1VirtKey[uKeyIndex];
keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey],
(DWORD)NULL, (DWORD)NULL);
pSKT1Ctxt->uKeyIndex = uKeyIndex;
SKT1InvertButton(hSKWnd, NULL, pSKT1Ctxt, pSKT1Ctxt->uKeyIndex);
GlobalUnlock(hSKT1Ctxt);
return (TRUE);
}
gptWorkArea.x = GetSystemMetrics(SM_CXWORKAREA);
if (gptWorkArea.x < UI_MARGIN * 2) {
gptWorkArea.x = UI_MARGIN * 2;
}
gptWorkArea.y = GetSystemMetrics(SM_CYWORKAREA);
if (gptWorkArea.y < UI_MARGIN * 2) {
gptWorkArea.y = UI_MARGIN * 2;
}
GetCursorPos(&pSKT1Ctxt->ptSkCursor);
GetWindowRect(hSKWnd, &rcWnd);
pSKT1Ctxt->ptSkOffset.x = pSKT1Ctxt->ptSkCursor.x - rcWnd.left;
pSKT1Ctxt->ptSkOffset.y = pSKT1Ctxt->ptSkCursor.y - rcWnd.top;
SKT1DrawDragBorder(hSKWnd, &pSKT1Ctxt->ptSkCursor,
&pSKT1Ctxt->ptSkOffset);
GlobalUnlock(hSKT1Ctxt);
return (TRUE);
}
/**********************************************************************\
* SKT1MouseMove
*
\**********************************************************************/
BOOL SKT1MouseMove(
HWND hSKWnd)
{
HGLOBAL hSKT1Ctxt;
PSKT1CTXT pSKT1Ctxt;
hSKT1Ctxt = (HGLOBAL)GetWindowLong(hSKWnd, SKT1_CONTEXT);
if (!hSKT1Ctxt) {
return (FALSE);
}
pSKT1Ctxt = (PSKT1CTXT)GlobalLock(hSKT1Ctxt);
if (!pSKT1Ctxt) {
return (FALSE);
}
if (pSKT1Ctxt->ptSkOffset.x == SKT1_NOT_DRAG) {
GlobalUnlock(hSKT1Ctxt);
return (FALSE);
}
if (pSKT1Ctxt->ptSkOffset.y == SKT1_NOT_DRAG) {
GlobalUnlock(hSKT1Ctxt);
return (FALSE);
}
SKT1DrawDragBorder(hSKWnd, &pSKT1Ctxt->ptSkCursor,
&pSKT1Ctxt->ptSkOffset);
GetCursorPos(&pSKT1Ctxt->ptSkCursor);
SKT1DrawDragBorder(hSKWnd, &pSKT1Ctxt->ptSkCursor,
&pSKT1Ctxt->ptSkOffset);
GlobalUnlock(hSKT1Ctxt);
return (TRUE);
}
/**********************************************************************\
* SKT1ButtonUp
*
\**********************************************************************/
BOOL SKT1ButtonUp(
HWND hSKWnd)
{
HGLOBAL hSKT1Ctxt;
PSKT1CTXT pSKT1Ctxt;
BOOL fRet;
POINT pt;
HWND hUIWnd;
HIMC hImc;
PINPUTCONTEXT pInputContext;
fRet = FALSE;
if (GetCapture() == hSKWnd) {
ReleaseCapture();
}
hSKT1Ctxt = (HGLOBAL)GetWindowLong(hSKWnd, SKT1_CONTEXT);
if (!hSKT1Ctxt) {
return (fRet);
}
pSKT1Ctxt = (PSKT1CTXT)GlobalLock(hSKT1Ctxt);
if (!pSKT1Ctxt) {
return (fRet);
}
if (pSKT1Ctxt->uKeyIndex < SKT1_OUT_OF_RANGE) {
UINT uVirtKey;
uVirtKey = SKT1VirtKey[pSKT1Ctxt->uKeyIndex];
keybd_event((BYTE)uVirtKey, (BYTE)guScanCode[uVirtKey],
(DWORD)KEYEVENTF_KEYUP, (DWORD)NULL);
SKT1InvertButton(hSKWnd, NULL, pSKT1Ctxt, pSKT1Ctxt->uKeyIndex);
pSKT1Ctxt->uKeyIndex = SKT1_OUT_OF_RANGE;
fRet = TRUE;
goto SKT1BuUpUnlockCtxt;
}
if (pSKT1Ctxt->ptSkOffset.x == SKT1_NOT_DRAG) {
goto SKT1BuUpUnlockCtxt;
}
if (pSKT1Ctxt->ptSkOffset.y == SKT1_NOT_DRAG) {
goto SKT1BuUpUnlockCtxt;
}
SKT1DrawDragBorder(hSKWnd, &pSKT1Ctxt->ptSkCursor,
&pSKT1Ctxt->ptSkOffset);
pt.x = pSKT1Ctxt->ptSkCursor.x - pSKT1Ctxt->ptSkOffset.x,
pt.y = pSKT1Ctxt->ptSkCursor.y - pSKT1Ctxt->ptSkOffset.y,
SetWindowPos(hSKWnd, (HWND)NULL, pt.x, pt.y,
0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
pSKT1Ctxt->ptSkOffset.x = SKT1_NOT_DRAG;
pSKT1Ctxt->ptSkOffset.y = SKT1_NOT_DRAG;
pSKT1Ctxt->uKeyIndex = SKT1_OUT_OF_RANGE;
fRet = TRUE;
hUIWnd = GetWindow(hSKWnd, GW_OWNER);
hImc = (HIMC)GetWindowLong(hUIWnd, IMMGWL_IMC);
if (!hImc) {
goto SKT1BuUpUnlockCtxt;
}
pInputContext = ImmLockIMC(hImc);
if (!pInputContext) {
goto SKT1BuUpUnlockCtxt;
}
pInputContext->ptSoftKbdPos.x = pt.x;
pInputContext->ptSoftKbdPos.y = pt.y;
pInputContext->fdwInit |= INIT_SOFTKBDPOS;
ImmUnlockIMC(hImc);
SKT1BuUpUnlockCtxt:
GlobalUnlock(hSKT1Ctxt);
return (fRet);
}
/**********************************************************************\
* UpdateSKT1Bitmap
*
\**********************************************************************/
LRESULT UpdateSKT1Bitmap(
HWND hSKWnd,
LPSOFTKBDDATA lpSoftKbdData)
{
HGLOBAL hSKT1Ctxt;
PSKT1CTXT pSKT1Ctxt;
HDC hDC, hMemDC;
HGDIOBJ hOldFont;
int i;
hSKT1Ctxt = (HGLOBAL)GetWindowLong(hSKWnd, SKT1_CONTEXT);
if (!hSKT1Ctxt) {
return (1);
}
pSKT1Ctxt = (PSKT1CTXT)GlobalLock(hSKT1Ctxt);
if (!pSKT1Ctxt) {
return (1);
}
hDC = GetDC(hSKWnd);
hMemDC = CreateCompatibleDC(hDC);
ReleaseDC(hSKWnd, hDC);
SelectObject(hMemDC, pSKT1Ctxt->hSKBitmap);
SetBkColor(hMemDC, RGB(0xC0, 0xC0, 0xC0));
if (pSKT1Ctxt->lfCharSet != DEFAULT_CHARSET) {
LOGFONT lfFont;
hOldFont = GetCurrentObject(hMemDC, OBJ_FONT);
GetObject(hOldFont, sizeof(lfFont), &lfFont);
lfFont.lfCharSet = pSKT1Ctxt->lfCharSet;
lfFont.lfFaceName[0] = L'\0';
SelectObject(hMemDC, CreateFontIndirect(&lfFont));
}
for (i = 0; i < SKT1_LETTER_KEYS; i++) {
int nchar;
RECT rcOpaque;
pSKT1Ctxt->wCodeTbl[i] = lpSoftKbdData->wCode[0][SKT1VirtKey[i]];
nchar = (pSKT1Ctxt->wCodeTbl[i] == 0) ? 0 : 1;
rcOpaque.left = pSKT1Ctxt->ptButtonPos[i].x;
rcOpaque.top = pSKT1Ctxt->ptButtonPos[i].y;
rcOpaque.right = rcOpaque.left +
pSKT1Ctxt->nButtonWidth[SKT1_LETTER_TYPE];
rcOpaque.bottom = rcOpaque.top + pSKT1Ctxt->nButtonHeight;
ExtTextOut(hMemDC,
pSKT1Ctxt->ptButtonPos[i].x,
pSKT1Ctxt->ptButtonPos[i].y,
ETO_OPAQUE, &rcOpaque,
(LPWSTR)&pSKT1Ctxt->wCodeTbl[i], nchar, NULL);
}
if (pSKT1Ctxt->lfCharSet != DEFAULT_CHARSET) {
DeleteObject(SelectObject(hMemDC, hOldFont));
}
DeleteDC(hMemDC);
GlobalUnlock(hSKT1Ctxt);
return (0);
}
/**********************************************************************\
* SKWndProcT1
*
\**********************************************************************/
LRESULT 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;
PSKT1CTXT pSKT1Ctxt;
BYTE lfCharSet;
HDC hDC;
LOGFONT lfFont;
hSKT1Ctxt = (HGLOBAL)GetWindowLong(hSKWnd, SKT1_CONTEXT);
if (!hSKT1Ctxt) {
return (1);
}
pSKT1Ctxt = (PSKT1CTXT)GlobalLock(hSKT1Ctxt);
if (!pSKT1Ctxt) {
return (1);
}
lfCharSet = (BYTE)pSKT1Ctxt->lfCharSet;
GlobalUnlock(hSKT1Ctxt);
hDC = GetDC(hSKWnd);
GetObject(GetCurrentObject(hDC, OBJ_FONT),
sizeof(lfFont), &lfFont);
ReleaseDC(hSKWnd, hDC);
if (lfCharSet != DEFAULT_CHARSET) {
lfFont.lfCharSet = lfCharSet;
}
*(LPLOGFONT)lParam = lfFont;
return (0);
}
break;
case IMC_SETSOFTKBDFONT:
{
HDC hDC;
LOGFONT lfFont;
hDC = GetDC(hSKWnd);
GetObject(GetCurrentObject(hDC, OBJ_FONT),
sizeof(lfFont), &lfFont);
ReleaseDC(hSKWnd, hDC);
// in differet version of Windows
if (lfFont.lfCharSet != ((LPLOGFONT)lParam)->lfCharSet) {
HGLOBAL hSKT1Ctxt;
PSKT1CTXT pSKT1Ctxt;
hSKT1Ctxt = (HGLOBAL)GetWindowLong(hSKWnd, SKT1_CONTEXT);
if (!hSKT1Ctxt) {
break;
}
pSKT1Ctxt = (PSKT1CTXT)GlobalLock(hSKT1Ctxt);
if (!pSKT1Ctxt) {
break;
}
pSKT1Ctxt->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;
PINPUTCONTEXT pInputContext;
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 = GetWindowLong(hUIWnd, IMMGWL_IMC);
if (!hImc) {
return (1);
}
pInputContext = ImmLockIMC(hImc);
if (!pInputContext) {
return (1);
}
pInputContext->ptSoftKbdPos = ptSoftKbdPos;
ImmUnlockIMC(hImc);
return (0);
}
break;
case IMC_SETSOFTKBDDATA:
{
LRESULT lRet;
lRet = UpdateSKT1Bitmap(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;
PSKT1CTXT pSKT1Ctxt;
LRESULT lRet;
lRet = -1;
hSKT1Ctxt = (HGLOBAL)GetWindowLong(hSKWnd, SKT1_CONTEXT);
if (!hSKT1Ctxt) {
return (lRet);
}
pSKT1Ctxt = (PSKT1CTXT)GlobalLock(hSKT1Ctxt);
if (!pSKT1Ctxt) {
return (lRet);
}
if (wParam == IMC_GETSOFTKBDSUBTYPE) {
lRet = pSKT1Ctxt->uSubtype;
} else if (wParam == IMC_SETSOFTKBDSUBTYPE) {
lRet = pSKT1Ctxt->uSubtype;
pSKT1Ctxt->uSubtype = (UINT)lParam;
} else {
lRet = -1;
}
GlobalUnlock(hSKT1Ctxt);
return (lRet);
}
break;
default:
break;
}
break;
default:
return DefWindowProc(hSKWnd, uMsg, wParam, lParam);
}
return (0L);
}