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.
 
 
 
 
 
 

1195 lines
36 KiB

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