https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6783061894743604dd057…
commit 6783061894743604dd057858f5ae3b1d38f238f7
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Sat Nov 25 18:56:33 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Sat Nov 25 18:56:33 2023 +0900
[IMM32] Implement Soft Keyboard Type C1 (#6036)
Follow-up to #6021. This PR will finish ImmCreateSoftKeyboard implementation.
- Add c1key.h to define C1 internal codes.
- The tests are done, using FreeCJ2004 on Chinese/Taiwanese system.
FreeCJ2004:
https://web.archive.org/web/20061208204431/http://input.foruto.com/download…
CORE-19268
---
dll/win32/imm32/c1keys.h | 64 +++
dll/win32/imm32/softkbd.c | 1029 ++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 1027 insertions(+), 66 deletions(-)
diff --git a/dll/win32/imm32/c1keys.h b/dll/win32/imm32/c1keys.h
new file mode 100644
index 00000000000..34f1ea3049e
--- /dev/null
+++ b/dll/win32/imm32/c1keys.h
@@ -0,0 +1,64 @@
+/*
+ * PROJECT: ReactOS IMM32
+ * LICENSE: LGPL-2.1-or-later (
https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE: Defining internal codes (C1K_...) of IME Soft Keyboard Type C1
+ * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
+ */
+
+/* DEFINE_C1K(c1k_code, virtual_key_code, c1k_code_name, virtual_key_name, is_special)
*/
+DEFINE_C1K( 0, 0xC0, C1K_OEM_3, VK_OEM_3, FALSE)
+DEFINE_C1K( 1, 0x31, C1K_1, VK_1, FALSE)
+DEFINE_C1K( 2, 0x32, C1K_2, VK_2, FALSE)
+DEFINE_C1K( 3, 0x33, C1K_3, VK_3, FALSE)
+DEFINE_C1K( 4, 0x34, C1K_4, VK_4, FALSE)
+DEFINE_C1K( 5, 0x35, C1K_5, VK_5, FALSE)
+DEFINE_C1K( 6, 0x36, C1K_6, VK_6, FALSE)
+DEFINE_C1K( 7, 0x37, C1K_7, VK_7, FALSE)
+DEFINE_C1K( 8, 0x38, C1K_8, VK_8, FALSE)
+DEFINE_C1K( 9, 0x39, C1K_9, VK_9, FALSE)
+DEFINE_C1K(10, 0x30, C1K_0, VK_0, FALSE)
+DEFINE_C1K(11, 0xBD, C1K_OEM_MINUS, VK_OEM_MINUS, FALSE)
+DEFINE_C1K(12, 0xBB, C1K_OEM_PLUS, VK_OEM_PLUS, FALSE)
+DEFINE_C1K(13, 0x51, C1K_Q, VK_Q, FALSE)
+DEFINE_C1K(14, 0x57, C1K_W, VK_W, FALSE)
+DEFINE_C1K(15, 0x45, C1K_E, VK_E, FALSE)
+DEFINE_C1K(16, 0x52, C1K_R, VK_R, FALSE)
+DEFINE_C1K(17, 0x54, C1K_T, VK_T, FALSE)
+DEFINE_C1K(18, 0x59, C1K_Y, VK_Y, FALSE)
+DEFINE_C1K(19, 0x55, C1K_U, VK_U, FALSE)
+DEFINE_C1K(20, 0x49, C1K_I, VK_I, FALSE)
+DEFINE_C1K(21, 0x4F, C1K_O, VK_O, FALSE)
+DEFINE_C1K(22, 0x50, C1K_P, VK_P, FALSE)
+DEFINE_C1K(23, 0xDB, C1K_OEM_4, VK_OEM_4, FALSE)
+DEFINE_C1K(24, 0xDD, C1K_OEM_6, VK_OEM_6, FALSE)
+DEFINE_C1K(25, 0xDC, C1K_OEM_5, VK_OEM_5, FALSE)
+DEFINE_C1K(26, 0x41, C1K_A, VK_A, FALSE)
+DEFINE_C1K(27, 0x53, C1K_S, VK_S, FALSE)
+DEFINE_C1K(28, 0x44, C1K_D, VK_D, FALSE)
+DEFINE_C1K(29, 0x46, C1K_F, VK_F, FALSE)
+DEFINE_C1K(30, 0x47, C1K_G, VK_G, FALSE)
+DEFINE_C1K(31, 0x48, C1K_H, VK_H, FALSE)
+DEFINE_C1K(32, 0x4A, C1K_J, VK_J, FALSE)
+DEFINE_C1K(33, 0x4B, C1K_K, VK_K, FALSE)
+DEFINE_C1K(34, 0x4C, C1K_L, VK_L, FALSE)
+DEFINE_C1K(35, 0xBA, C1K_OEM_1, VK_OEM_1, FALSE)
+DEFINE_C1K(36, 0xDE, C1K_OEM_7, VK_OEM_7, FALSE)
+DEFINE_C1K(37, 0x5A, C1K_Z, VK_Z, FALSE)
+DEFINE_C1K(38, 0x58, C1K_X, VK_X, FALSE)
+DEFINE_C1K(39, 0x43, C1K_C, VK_C, FALSE)
+DEFINE_C1K(40, 0x56, C1K_V, VK_V, FALSE)
+DEFINE_C1K(41, 0x42, C1K_B, VK_B, FALSE)
+DEFINE_C1K(42, 0x4E, C1K_N, VK_N, FALSE)
+DEFINE_C1K(43, 0x4D, C1K_M, VK_M, FALSE)
+DEFINE_C1K(44, 0xBC, C1K_OEM_COMMA, VK_OEM_COMMA, FALSE)
+DEFINE_C1K(45, 0xBE, C1K_OEM_DOT, VK_OEM_PERIOD, FALSE)
+DEFINE_C1K(46, 0xBF, C1K_OEM_2, VK_OEM_2, FALSE)
+DEFINE_C1K(47, 0x08, C1K_BACKSPACE, VK_BACK, TRUE)
+DEFINE_C1K(48, 0x09, C1K_TAB, VK_TAB, TRUE)
+DEFINE_C1K(49, 0x14, C1K_CAPS, VK_CAPITAL, TRUE)
+DEFINE_C1K(50, 0x0D, C1K_ENTER, VK_RETURN, TRUE)
+DEFINE_C1K(51, 0x10, C1K_SHIFT, VK_SHIFT, TRUE)
+DEFINE_C1K(52, 0x2D, C1K_INSERT, VK_INSERT, TRUE)
+DEFINE_C1K(53, 0x2E, C1K_DELETE, VK_DELETE, TRUE)
+DEFINE_C1K(54, 0x20, C1K_SPACE, VK_SPACE, TRUE)
+DEFINE_C1K(55, 0x1B, C1K_ESCAPE, VK_ESCAPE, TRUE)
diff --git a/dll/win32/imm32/softkbd.c b/dll/win32/imm32/softkbd.c
index 8cf17248760..522ff99185c 100644
--- a/dll/win32/imm32/softkbd.c
+++ b/dll/win32/imm32/softkbd.c
@@ -32,6 +32,23 @@ Imm32PtInRect(
return (x <= ppt->x) && (ppt->x < x + cx) && (y <=
ppt->y) && (ppt->y < y + cy);
}
+static void
+Imm32DrawBitmap(
+ _In_ HDC hdc,
+ _In_ INT x,
+ _In_ INT y,
+ _In_ INT width,
+ _In_ INT height,
+ _In_ INT nBitmapID)
+{
+ HBITMAP hBitmap = LoadBitmapW(ghImm32Inst, MAKEINTRESOURCEW(nBitmapID));
+ HDC hMemDC = CreateCompatibleDC(hdc);
+ HGDIOBJ hbmOld = SelectObject(hMemDC, hBitmap);
+ BitBlt(hdc, x, y, width, height, hMemDC, 0, 0, SRCCOPY);
+ DeleteObject(SelectObject(hMemDC, hbmOld));
+ DeleteDC(hMemDC);
+}
+
static inline INT
Imm32Clamp(
_In_ INT x,
@@ -320,24 +337,6 @@ T1_DrawConvexRect(
PatBlt(hDC, x0 + dx - 1, y + dy - 3, -1, 2 - dy, PATCOPY);
}
-static void
-T1_DrawBitmap(
- _In_ HDC hDC,
- _In_ INT x,
- _In_ INT y,
- _In_ INT cx,
- _In_ INT cy,
- _In_ INT nBitmapID)
-{
- HBITMAP hBitmap = LoadBitmapW(ghImm32Inst, MAKEINTRESOURCEW(nBitmapID));
- HDC hMemDC = CreateCompatibleDC(hDC);
- HGDIOBJ hbmOld = SelectObject(hMemDC, hBitmap);
- BitBlt(hDC, x, y, cx, cy, hMemDC, 0, 0, SRCCOPY);
- SelectObject(hMemDC, hbmOld);
- DeleteObject(hBitmap);
- DeleteDC(hMemDC);
-}
-
static void
T1_DrawLabels(
_In_ HDC hDC,
@@ -386,46 +385,46 @@ T1_InitBitmap(
T1_DrawConvexRect(hMemDC,
T1_KEYPOS(T1K_L_CTRL).x, T1_KEYPOS(T1K_L_CTRL).y,
pT1->cxWidth53or54, pT1->cyDefHeight);
- T1_DrawBitmap(hMemDC,
- pT1->cxWidth53or54 / 2 + T1_KEYPOS(T1K_L_CTRL).x - 8,
- pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_L_CTRL).y - 4,
- 16, 9, IDB_T1_CTRL);
+ Imm32DrawBitmap(hMemDC,
+ pT1->cxWidth53or54 / 2 + T1_KEYPOS(T1K_L_CTRL).x - 8,
+ pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_L_CTRL).y - 4,
+ 16, 9, IDB_T1_CTRL);
/* 54 --> Right [Ctrl] */
T1_DrawConvexRect(hMemDC,
T1_KEYPOS(T1K_R_CTRL).x, T1_KEYPOS(T1K_R_CTRL).y,
pT1->cxWidth53or54, pT1->cyDefHeight);
- T1_DrawBitmap(hMemDC,
- pT1->cxWidth53or54 / 2 + T1_KEYPOS(T1K_R_CTRL).x - 8,
- pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_R_CTRL).y - 4,
- 16, 9, IDB_T1_CTRL);
+ Imm32DrawBitmap(hMemDC,
+ pT1->cxWidth53or54 / 2 + T1_KEYPOS(T1K_R_CTRL).x - 8,
+ pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_R_CTRL).y - 4,
+ 16, 9, IDB_T1_CTRL);
/* 57 --> [Esc] */
T1_DrawConvexRect(hMemDC,
T1_KEYPOS(T1K_ESCAPE).x, T1_KEYPOS(T1K_ESCAPE).y,
pT1->cxWidth57, pT1->cyDefHeight);
- T1_DrawBitmap(hMemDC,
- pT1->cxWidth57 / 2 + T1_KEYPOS(T1K_ESCAPE).x - 9,
- pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_ESCAPE).y - 4,
- 18, 9, IDB_T1_ESCAPE);
+ Imm32DrawBitmap(hMemDC,
+ pT1->cxWidth57 / 2 + T1_KEYPOS(T1K_ESCAPE).x - 9,
+ pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_ESCAPE).y - 4,
+ 18, 9, IDB_T1_ESCAPE);
/* 55 --> Left [Alt] */
T1_DrawConvexRect(hMemDC,
T1_KEYPOS(T1K_L_ALT).x, T1_KEYPOS(T1K_L_ALT).y,
pT1->cxWidth55or56, pT1->cyDefHeight);
- T1_DrawBitmap(hMemDC,
- pT1->cxWidth55or56 / 2 + T1_KEYPOS(T1K_L_ALT).x - 8,
- pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_L_ALT).y - 4,
- 16, 9, IDB_T1_ALT);
+ Imm32DrawBitmap(hMemDC,
+ pT1->cxWidth55or56 / 2 + T1_KEYPOS(T1K_L_ALT).x - 8,
+ pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_L_ALT).y - 4,
+ 16, 9, IDB_T1_ALT);
/* 56 --> Right [Alt] */
T1_DrawConvexRect(hMemDC,
T1_KEYPOS(T1K_R_ALT).x, T1_KEYPOS(T1K_R_ALT).y,
pT1->cxWidth55or56, pT1->cyDefHeight);
- T1_DrawBitmap(hMemDC,
- pT1->cxWidth55or56 / 2 + T1_KEYPOS(T1K_R_ALT).x - 8,
- pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_R_ALT).y - 4,
- 16, 9, IDB_T1_ALT);
+ Imm32DrawBitmap(hMemDC,
+ pT1->cxWidth55or56 / 2 + T1_KEYPOS(T1K_R_ALT).x - 8,
+ pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_R_ALT).y - 4,
+ 16, 9, IDB_T1_ALT);
/* 58 --> [Space] */
T1_DrawConvexRect(hMemDC,
@@ -436,55 +435,55 @@ T1_InitBitmap(
T1_DrawConvexRect(hMemDC,
T1_KEYPOS(T1K_L_SHIFT).x, T1_KEYPOS(T1K_L_SHIFT).y,
pT1->cxWidth51or52, pT1->cyDefHeight);
- T1_DrawBitmap(hMemDC,
- pT1->cxWidth51or52 / 2 + T1_KEYPOS(T1K_L_SHIFT).x - 11,
- pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_L_SHIFT).y - 4,
- 23, 9, IDB_T1_SHIFT);
+ Imm32DrawBitmap(hMemDC,
+ pT1->cxWidth51or52 / 2 + T1_KEYPOS(T1K_L_SHIFT).x - 11,
+ pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_L_SHIFT).y - 4,
+ 23, 9, IDB_T1_SHIFT);
/* 52 --> Right [Shift] */
T1_DrawConvexRect(hMemDC,
T1_KEYPOS(T1K_R_SHIFT).x, T1_KEYPOS(T1K_R_SHIFT).y,
pT1->cxWidth51or52, pT1->cyDefHeight);
- T1_DrawBitmap(hMemDC,
- pT1->cxWidth51or52 / 2 + T1_KEYPOS(T1K_R_SHIFT).x - 11,
- pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_R_SHIFT).y - 4,
- 23, 9, IDB_T1_SHIFT);
+ Imm32DrawBitmap(hMemDC,
+ pT1->cxWidth51or52 / 2 + T1_KEYPOS(T1K_R_SHIFT).x - 11,
+ pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_R_SHIFT).y - 4,
+ 23, 9, IDB_T1_SHIFT);
/* 49 --> [Caps] */
T1_DrawConvexRect(hMemDC,
T1_KEYPOS(T1K_CAPS).x, T1_KEYPOS(T1K_CAPS).y,
pT1->cxWidth49, pT1->cyDefHeight);
- T1_DrawBitmap(hMemDC,
- pT1->cxWidth49 / 2 + T1_KEYPOS(T1K_CAPS).x - 11,
- pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_CAPS).y - 4,
- 22, 9, IDB_T1_CAPS);
+ Imm32DrawBitmap(hMemDC,
+ pT1->cxWidth49 / 2 + T1_KEYPOS(T1K_CAPS).x - 11,
+ pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_CAPS).y - 4,
+ 22, 9, IDB_T1_CAPS);
/* 48 --> [Tab] */
T1_DrawConvexRect(hMemDC,
T1_KEYPOS(T1K_TAB).x, T1_KEYPOS(T1K_TAB).y,
pT1->cxWidth48, pT1->cyDefHeight);
- T1_DrawBitmap(hMemDC,
- pT1->cxWidth48 / 2 + T1_KEYPOS(T1K_TAB).x - 8,
- pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_TAB).y - 4,
- 16, 9, IDB_T1_TAB);
+ Imm32DrawBitmap(hMemDC,
+ pT1->cxWidth48 / 2 + T1_KEYPOS(T1K_TAB).x - 8,
+ pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_TAB).y - 4,
+ 16, 9, IDB_T1_TAB);
/* 50 --> [Enter] */
T1_DrawConvexRect(hMemDC,
T1_KEYPOS(T1K_ENTER).x, T1_KEYPOS(T1K_ENTER).y,
pT1->cxWidth50, pT1->cyHeight50);
- T1_DrawBitmap(hMemDC,
- pT1->cxWidth50 / 2 + T1_KEYPOS(T1K_ENTER).x - 13,
- pT1->cyHeight50 / 2 + T1_KEYPOS(T1K_ENTER).y - 4,
- 26, 9, IDB_T1_ENTER);
+ Imm32DrawBitmap(hMemDC,
+ pT1->cxWidth50 / 2 + T1_KEYPOS(T1K_ENTER).x - 13,
+ pT1->cyHeight50 / 2 + T1_KEYPOS(T1K_ENTER).y - 4,
+ 26, 9, IDB_T1_ENTER);
/* 47 --> [BackSpace] */
T1_DrawConvexRect(hMemDC,
T1_KEYPOS(T1K_BACKSPACE).x, T1_KEYPOS(T1K_BACKSPACE).y,
pT1->cxWidth47, pT1->cyDefHeight);
- T1_DrawBitmap(hMemDC,
- pT1->cxWidth47 / 2 + T1_KEYPOS(T1K_BACKSPACE).x - 8,
- pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_BACKSPACE).y - 4,
- 16, 9, IDB_T1_BACKSPACE);
+ Imm32DrawBitmap(hMemDC,
+ pT1->cxWidth47 / 2 + T1_KEYPOS(T1K_BACKSPACE).x - 8,
+ pT1->cyDefHeight / 2 + T1_KEYPOS(T1K_BACKSPACE).y - 4,
+ 16, 9, IDB_T1_BACKSPACE);
/* Regular keys */
for (iKey = 0; iKey < T1K_BACKSPACE; ++iKey)
@@ -842,7 +841,7 @@ T1_OnButtonUp(
iPressed = pT1->PressedKey;
if (iPressed >= T1K_NONE)
{
- if (pT1->pt1.x != -1 && pT1->pt1.y != -1 )
+ if (pT1->pt1.x != -1 && pT1->pt1.y != -1)
{
T1_DrawDragBorder(hWnd, &pT1->pt0, &pT1->pt1);
x = pT1->pt0.x - pT1->pt1.x;
@@ -1123,6 +1122,865 @@ T1_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
#define C1_CLASSNAMEW L"SoftKBDClsC1"
+#define C1K_MAX 56
+
+#undef DEFINE_C1K
+#define DEFINE_C1K(c1k_code, virtual_key_code, c1k_code_name, virtual_key_name,
is_special) \
+ c1k_code_name = c1k_code,
+
+/* Define C1 internal codes (C1K_...) */
+typedef enum C1KEY
+{
+#include "c1keys.h"
+} C1KEY;
+
+#undef DEFINE_C1K
+#define DEFINE_C1K(c1k_code, virtual_key_code, c1k_code_name, virtual_key_name,
is_special) \
+ virtual_key_code,
+
+/* Mapping: C1K --> Virtual Key */
+const BYTE gC1K2VK[C1K_MAX] =
+{
+#include "c1keys.h"
+};
+
+typedef struct C1WINDOW
+{
+ WCHAR Data[2][47];
+ DWORD dwFlags;
+ HBITMAP hbmKeyboard;
+ LPARAM SubType;
+ INT iPressedKey;
+ POINT pt1, pt2;
+ DWORD CharSet;
+} C1WINDOW, *PC1WINDOW;
+
+/* The flags for C1WINDOW.dwFlags */
+#define FLAG_SHIFT_PRESSED 1
+#define FLAG_DRAGGING 2
+#define FLAG_PRESSED 4
+
+static BOOL gbC1ButtonInit = FALSE;
+static POINT gptC1ButtonPos[C1K_MAX];
+
+static void C1_InitButtonPos(void)
+{
+ LONG x = 0, y = 0;
+ INT iKey;
+
+ /* 1st row */
+ for (iKey = C1K_OEM_3; iKey < C1K_Q; ++iKey)
+ {
+ gptC1ButtonPos[iKey].x = x;
+ gptC1ButtonPos[iKey].y = y;
+ x += 24;
+ }
+ gptC1ButtonPos[C1K_BACKSPACE].x = x;
+ gptC1ButtonPos[C1K_BACKSPACE].y = y;
+
+ /* 2nd row */
+ y = 28;
+ gptC1ButtonPos[C1K_TAB].x = 0;
+ gptC1ButtonPos[C1K_TAB].y = y;
+ x = 36;
+ for (; iKey < C1K_A; ++iKey)
+ {
+ gptC1ButtonPos[iKey].x = x;
+ gptC1ButtonPos[iKey].y = y;
+ x += 24;
+ }
+
+ /* 3rd row */
+ y = 56;
+ gptC1ButtonPos[C1K_CAPS].x = 0;
+ gptC1ButtonPos[C1K_CAPS].y = y;
+ x = 42;
+ for (; iKey < C1K_Z; ++iKey)
+ {
+ gptC1ButtonPos[iKey].x = x;
+ gptC1ButtonPos[iKey].y = y;
+ x += 24;
+ }
+ gptC1ButtonPos[C1K_ENTER].x = x;
+ gptC1ButtonPos[C1K_ENTER].y = y;
+
+ /* 4th row */
+ y = 84;
+ gptC1ButtonPos[C1K_SHIFT].x = 0;
+ gptC1ButtonPos[C1K_SHIFT].y = y;
+ x = 60;
+ for (; iKey < C1K_BACKSPACE; ++iKey)
+ {
+ gptC1ButtonPos[iKey].x = x;
+ gptC1ButtonPos[iKey].y = y;
+ x += 24;
+ }
+
+ /* 5th row */
+ y = 112;
+ gptC1ButtonPos[C1K_INSERT].x = 0;
+ gptC1ButtonPos[C1K_INSERT].y = y;
+ gptC1ButtonPos[C1K_DELETE].x = 58;
+ gptC1ButtonPos[C1K_DELETE].y = y;
+ gptC1ButtonPos[C1K_SPACE].x = 96;
+ gptC1ButtonPos[C1K_SPACE].y = y;
+ gptC1ButtonPos[C1K_ESCAPE].x = 310;
+ gptC1ButtonPos[C1K_ESCAPE].y = y;
+}
+
+static void
+C1_DrawConvexRect(
+ _In_ HDC hDC,
+ _In_ INT x,
+ _In_ INT y,
+ _In_ INT width,
+ _In_ INT height)
+{
+ HGDIOBJ hLtGrayBrush = GetStockObject(LTGRAY_BRUSH);
+ HGDIOBJ hBlackPen = GetStockObject(BLACK_PEN);
+ HGDIOBJ hWhiteBrush = GetStockObject(WHITE_BRUSH);
+ HGDIOBJ hGrayBrush = GetStockObject(GRAY_BRUSH);
+ INT y2 = y + height - 1;
+
+ /* Draw face */
+ SelectObject(hDC, hLtGrayBrush);
+ SelectObject(hDC, hBlackPen);
+ Rectangle(hDC, x, y, x + width, y + height);
+
+ /* Draw light edge */
+ SelectObject(hDC, hWhiteBrush);
+ PatBlt(hDC, x, y2, 2, 1 - height, PATCOPY);
+ PatBlt(hDC, x, y, width - 1, 2, PATCOPY);
+
+ /* Draw dark edge */
+ SelectObject(hDC, hGrayBrush);
+ PatBlt(hDC, x + 1, y2, width - 2, -1, PATCOPY);
+ PatBlt(hDC, x + width - 1, y2, -1, 2 - height, PATCOPY);
+}
+
+static void
+C1_InvertButton(
+ _In_ HDC hDC,
+ _In_ INT iKey)
+{
+ INT width = 24, height = 28;
+
+ if (iKey < 0)
+ return;
+
+ switch (iKey)
+ {
+ case C1K_BACKSPACE: case C1K_TAB:
+ width = 36;
+ break;
+ case C1K_CAPS: case C1K_ENTER:
+ width = 42;
+ break;
+ case C1K_SHIFT:
+ width = 60;
+ break;
+ case C1K_INSERT: case C1K_DELETE: case C1K_ESCAPE:
+ width = 38;
+ height = 24;
+ break;
+ case C1K_SPACE:
+ width = 172;
+ height = 24;
+ break;
+ default:
+ break;
+ }
+
+ BitBlt(hDC, gptC1ButtonPos[iKey].x, gptC1ButtonPos[iKey].y, width, height,
+ hDC, gptC1ButtonPos[iKey].x, gptC1ButtonPos[iKey].y, DSTINVERT);
+}
+
+static void
+C1_DrawLabel(
+ _In_ HDC hDC,
+ _In_ INT nBitmapID)
+{
+ HBITMAP hBitmap;
+ HGDIOBJ hbmOld;
+ HDC hMemDC;
+ INT iKey;
+
+ hBitmap = LoadBitmapW(ghImm32Inst, MAKEINTRESOURCEW(nBitmapID));
+ hMemDC = CreateCompatibleDC(hDC);
+ hbmOld = SelectObject(hMemDC, hBitmap);
+ for (iKey = C1K_OEM_3; iKey < C1K_BACKSPACE; ++iKey)
+ {
+ BitBlt(hDC, gptC1ButtonPos[iKey].x + 2, gptC1ButtonPos[iKey].y + 2, 8, 8,
+ hMemDC, iKey * 8, 0, SRCCOPY);
+ }
+ DeleteObject(SelectObject(hMemDC, hbmOld));
+ DeleteDC(hMemDC);
+}
+
+static void
+C1_InitBitmap(
+ _In_ HDC hDC,
+ _In_ INT x,
+ _In_ INT y,
+ _In_ INT width,
+ _In_ INT height)
+{
+ HGDIOBJ hLtGrayBrush = GetStockObject(LTGRAY_BRUSH);
+ HGDIOBJ hNullPen = GetStockObject(NULL_PEN);
+ INT iKey;
+
+ /* Draw keyboard frame */
+ SelectObject(hDC, hLtGrayBrush);
+ SelectObject(hDC, hNullPen);
+ Rectangle(hDC, x, y, width + 1, height + 1);
+
+ for (iKey = C1K_OEM_3; iKey < C1K_BACKSPACE; ++iKey)
+ {
+ C1_DrawConvexRect(hDC, gptC1ButtonPos[iKey].x, gptC1ButtonPos[iKey].y, 24, 28);
+ }
+
+ C1_DrawLabel(hDC, IDB_C1_CHARS);
+
+ C1_DrawConvexRect(hDC, gptC1ButtonPos[C1K_BACKSPACE].x,
gptC1ButtonPos[C1K_BACKSPACE].y, 36, 28);
+ Imm32DrawBitmap(hDC, gptC1ButtonPos[C1K_BACKSPACE].x + 2,
gptC1ButtonPos[C1K_BACKSPACE].y + 2, 32, 24, IDB_C1_BACKSPACE);
+
+ C1_DrawConvexRect(hDC, gptC1ButtonPos[C1K_TAB].x, gptC1ButtonPos[C1K_TAB].y, 36,
28);
+ Imm32DrawBitmap(hDC, gptC1ButtonPos[C1K_TAB].x + 2, gptC1ButtonPos[C1K_TAB].y + 2,
32, 24, IDB_C1_TAB);
+
+ C1_DrawConvexRect(hDC, gptC1ButtonPos[C1K_CAPS].x, gptC1ButtonPos[C1K_CAPS].y, 42,
28);
+ Imm32DrawBitmap(hDC, gptC1ButtonPos[C1K_CAPS].x + 2, gptC1ButtonPos[C1K_CAPS].y + 2,
38, 24, IDB_C1_CAPS);
+
+ C1_DrawConvexRect(hDC, gptC1ButtonPos[C1K_ENTER].x, gptC1ButtonPos[C1K_ENTER].y, 42,
28);
+ Imm32DrawBitmap(hDC, gptC1ButtonPos[C1K_ENTER].x + 2, gptC1ButtonPos[C1K_ENTER].y +
2, 38, 24, IDB_C1_ENTER);
+
+ C1_DrawConvexRect(hDC, gptC1ButtonPos[C1K_SHIFT].x, gptC1ButtonPos[C1K_SHIFT].y, 60,
28);
+ Imm32DrawBitmap(hDC, gptC1ButtonPos[C1K_SHIFT].x + 2, gptC1ButtonPos[C1K_SHIFT].y +
2, 56, 24, IDB_C1_SHIFT);
+
+ C1_DrawConvexRect(hDC, gptC1ButtonPos[C1K_INSERT].x, gptC1ButtonPos[C1K_INSERT].y,
38, 24);
+ Imm32DrawBitmap(hDC, gptC1ButtonPos[C1K_INSERT].x + 2, gptC1ButtonPos[C1K_INSERT].y +
2, 34, 20, IDB_C1_INS);
+
+ C1_DrawConvexRect(hDC, gptC1ButtonPos[C1K_DELETE].x, gptC1ButtonPos[C1K_DELETE].y,
38, 24);
+ Imm32DrawBitmap(hDC, gptC1ButtonPos[C1K_DELETE].x + 2, gptC1ButtonPos[C1K_DELETE].y +
2, 34, 20, IDB_C1_DEL);
+
+ C1_DrawConvexRect(hDC, gptC1ButtonPos[C1K_SPACE].x, gptC1ButtonPos[C1K_SPACE].y, 172,
24);
+
+ C1_DrawConvexRect(hDC, gptC1ButtonPos[C1K_ESCAPE].x, gptC1ButtonPos[C1K_ESCAPE].y ,
38, 24);
+ Imm32DrawBitmap(hDC, gptC1ButtonPos[C1K_ESCAPE].x + 2, gptC1ButtonPos[C1K_ESCAPE].y +
2, 34, 20, IDB_C1_ESCAPE);
+}
+
+static INT
+C1_OnCreate(
+ _In_ HWND hWnd)
+{
+ HGLOBAL hGlobal;
+ PC1WINDOW pC1;
+ HDC hDC, hMemDC;
+ RECT rc;
+ HGDIOBJ hbmOld;
+ HBITMAP hbmKeyboard;
+
+ hGlobal = GlobalAlloc(GHND, sizeof(C1WINDOW));
+ if (!hGlobal)
+ return -1;
+
+ pC1 = (PC1WINDOW)GlobalLock(hGlobal);
+ if (!pC1)
+ {
+ GlobalFree(hGlobal);
+ return -1;
+ }
+ SetWindowLongPtrW(hWnd, 0, (LONG_PTR)hGlobal);
+
+ if (!gbC1ButtonInit)
+ {
+ C1_InitButtonPos();
+ gbC1ButtonInit = TRUE;
+ }
+
+ pC1->iPressedKey = -1;
+ pC1->CharSet = GB2312_CHARSET;
+
+ GetClientRect(hWnd, &rc);
+
+ hDC = GetDC(hWnd);
+ hMemDC = CreateCompatibleDC(hDC);
+ hbmKeyboard = CreateCompatibleBitmap(hDC, rc.right - rc.left, rc.bottom - rc.top);
+ ReleaseDC(hWnd, hDC);
+
+ hbmOld = SelectObject(hMemDC, hbmKeyboard);
+ C1_InitBitmap(hMemDC, rc.left, rc.top, rc.right, rc.bottom);
+ SelectObject(hMemDC, hbmOld);
+ pC1->hbmKeyboard = hbmKeyboard;
+ DeleteDC(hMemDC);
+
+ GlobalUnlock(hGlobal);
+ return 0;
+}
+
+static void
+C1_OnDraw(
+ _In_ HDC hDC,
+ _In_ HWND hWnd)
+{
+ HGLOBAL hGlobal;
+ PC1WINDOW pC1;
+ HDC hMemDC;
+ RECT rc;
+ HGDIOBJ hbmOld;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pC1 = (PC1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pC1)
+ return;
+
+ GetClientRect(hWnd, &rc);
+
+ hMemDC = CreateCompatibleDC(hDC);
+ hbmOld = SelectObject(hMemDC, pC1->hbmKeyboard);
+ BitBlt(hDC, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hMemDC, 0, 0, SRCCOPY);
+ SelectObject(hMemDC, hbmOld);
+ DeleteDC(hMemDC);
+
+ GlobalUnlock(hGlobal);
+}
+
+static BOOL
+C1_SetData(
+ _In_ HWND hWnd,
+ _In_ const SOFTKBDDATA *pData)
+{
+ HGLOBAL hGlobal;
+ PC1WINDOW pC1;
+ HDC hDC, hMemDC;
+ INT iKey;
+ BOOL bDisabled;
+ HBITMAP hbmKeyboard;
+ HGDIOBJ hbmOld, hFontOld;
+ HFONT hFont;
+ RECT rc;
+ LOGFONTW lf;
+
+ if (pData->uCount != 2)
+ return 0;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pC1 = (PC1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pC1)
+ return FALSE;
+
+ hDC = GetDC(hWnd);
+ hMemDC = CreateCompatibleDC(hDC);
+
+ hbmKeyboard = pC1->hbmKeyboard;
+ hbmOld = SelectObject(hMemDC, hbmKeyboard);
+
+ GetObjectW(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
+ lf.lfHeight = -12;
+ if (pC1->CharSet != DEFAULT_CHARSET)
+ lf.lfCharSet = (BYTE)pC1->CharSet;
+
+ hFont = CreateFontIndirectW(&lf);
+ hFontOld = SelectObject(hMemDC, hFont);
+ for (iKey = C1K_OEM_3; iKey < C1K_BACKSPACE; ++iKey)
+ {
+ pC1->Data[1][iKey] = pData->wCode[0][(BYTE)gC1K2VK[iKey]];
+ pC1->Data[0][iKey] = pData->wCode[1][(BYTE)gC1K2VK[iKey]];
+ }
+
+ SetBkColor(hMemDC, RGB(191, 191, 191));
+ for (iKey = C1K_OEM_3; iKey < C1K_BACKSPACE; ++iKey)
+ {
+ /* Upper right */
+ rc.right = gptC1ButtonPos[iKey].x + 24 - 2;
+ rc.top = gptC1ButtonPos[iKey].y + 2;
+ rc.left = rc.right - 14;
+ rc.bottom = rc.top + 14;
+ bDisabled = (pC1->Data[0][iKey] == 0);
+ DrawTextW(hMemDC, &pC1->Data[0][iKey], !bDisabled, &rc,
+ DT_RIGHT | DT_TOP | DT_SINGLELINE);
+
+ /* Lower left */
+ rc.left = gptC1ButtonPos[iKey].x + 2;
+ rc.bottom = gptC1ButtonPos[iKey].y + 28 - 2;
+ rc.right = rc.left + 14;
+ rc.top = rc.bottom - 14;
+ bDisabled = (pC1->Data[1][iKey] == 0);
+ DrawTextW(hMemDC, &pC1->Data[1][iKey], !bDisabled, &rc,
+ DT_LEFT | DT_BOTTOM | DT_SINGLELINE);
+ }
+
+ if (pC1->dwFlags & FLAG_SHIFT_PRESSED)
+ C1_InvertButton(hMemDC, C1K_SHIFT);
+
+ pC1->dwFlags = 0;
+
+ SelectObject(hMemDC, hbmOld);
+ DeleteObject(SelectObject(hMemDC, hFontOld));
+
+ DeleteDC(hMemDC);
+ ReleaseDC(hWnd, hDC);
+
+ GlobalUnlock(hGlobal);
+ return TRUE;
+}
+
+static void
+C1_DrawDragBorder(
+ _In_ HWND hWnd,
+ _In_ LPPOINT ppt1,
+ _Inout_ LPPOINT ppt2)
+{
+ HGDIOBJ hGrayBrush = GetStockObject(GRAY_BRUSH);
+ INT x, y;
+ RECT rc, rcWork;
+ INT cxBorder = GetSystemMetrics(SM_CXBORDER), cyBorder =
GetSystemMetrics(SM_CYBORDER);
+ HDC hDisplayDC;
+
+ Imm32GetAllMonitorSize(&rcWork);
+ hDisplayDC = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
+
+ SelectObject(hDisplayDC, hGrayBrush);
+ x = ppt1->x - ppt2->x;
+ y = ppt1->y - ppt2->y;
+ if (x < rcWork.left)
+ x = rcWork.left;
+ if (y < rcWork.top)
+ y = rcWork.top;
+
+ GetWindowRect(hWnd, &rc);
+
+ if (rc.right - rc.left + x > rcWork.right)
+ x = rc.left + rcWork.right - rc.right;
+ if (y + rc.bottom - rc.top > rcWork.bottom)
+ y = rc.top + rcWork.bottom - rc.bottom;
+
+ ppt2->x = ppt1->x - x;
+ ppt2->y = ppt1->y - y;
+
+ PatBlt(hDisplayDC, x, y, rc.right - rc.left - cxBorder, cyBorder, PATINVERT);
+ PatBlt(hDisplayDC, x, y + cyBorder, cxBorder, rc.bottom - rc.top - cyBorder,
PATINVERT);
+ PatBlt(hDisplayDC, x + cxBorder, y + rc.bottom - rc.top, rc.right - rc.left -
cxBorder, -cyBorder, PATINVERT);
+ PatBlt(hDisplayDC, x + rc.right - rc.left, y, -cxBorder, rc.bottom - rc.top -
cyBorder, PATINVERT);
+
+ DeleteDC(hDisplayDC);
+}
+
+static INT
+C1_HitTest(
+ _In_ const POINT *ppt)
+{
+ INT iKey;
+
+ for (iKey = C1K_OEM_3; iKey < C1K_BACKSPACE; ++iKey)
+ {
+ if (Imm32PtInRect(ppt, gptC1ButtonPos[iKey].x, gptC1ButtonPos[iKey].y, 24, 28))
+ return iKey;
+ }
+
+ if (Imm32PtInRect(ppt, gptC1ButtonPos[C1K_BACKSPACE].x,
gptC1ButtonPos[C1K_BACKSPACE].y, 36, 28))
+ return C1K_BACKSPACE;
+ if (Imm32PtInRect(ppt, gptC1ButtonPos[C1K_TAB].x, gptC1ButtonPos[C1K_TAB].y, 36,
28))
+ return C1K_TAB;
+ if (Imm32PtInRect(ppt, gptC1ButtonPos[C1K_CAPS].x, gptC1ButtonPos[C1K_CAPS].y, 42,
28))
+ return C1K_CAPS;
+ if (Imm32PtInRect(ppt, gptC1ButtonPos[C1K_ENTER].x, gptC1ButtonPos[C1K_ENTER].y, 42,
28))
+ return C1K_ENTER;
+ if (Imm32PtInRect(ppt, gptC1ButtonPos[C1K_SHIFT].x, gptC1ButtonPos[C1K_SHIFT].y, 60,
28))
+ return C1K_SHIFT;
+ if (Imm32PtInRect(ppt, gptC1ButtonPos[C1K_ESCAPE].x, gptC1ButtonPos[C1K_ESCAPE].y,
38, 24))
+ return C1K_ESCAPE;
+ if (Imm32PtInRect(ppt, gptC1ButtonPos[C1K_SPACE].x, gptC1ButtonPos[C1K_SPACE].y, 172,
24))
+ return C1K_SPACE;
+ if (Imm32PtInRect(ppt, gptC1ButtonPos[C1K_INSERT].x, gptC1ButtonPos[C1K_INSERT].y,
38, 24))
+ return C1K_INSERT;
+ if (Imm32PtInRect(ppt, gptC1ButtonPos[C1K_DELETE].x, gptC1ButtonPos[C1K_DELETE].y,
38, 24))
+ return C1K_DELETE;
+
+ return -1;
+}
+
+static void
+C1_OnButtonDown(
+ _In_ HWND hWnd,
+ _Inout_ PC1WINDOW pC1)
+{
+ INT iPressedKey;
+ HDC hMemDC;
+ WCHAR wch = 0xFF;
+ HGDIOBJ hbmOld;
+ HDC hDC;
+
+ SetCapture(hWnd);
+
+ iPressedKey = pC1->iPressedKey;
+ if (iPressedKey == -1)
+ {
+ pC1->dwFlags |= FLAG_DRAGGING;
+ C1_DrawDragBorder(hWnd, &pC1->pt1, &pC1->pt2);
+ return;
+ }
+
+ if (iPressedKey < C1K_BACKSPACE)
+ {
+ wch = pC1->Data[!(pC1->dwFlags & 1)][iPressedKey];
+ if (!wch)
+ {
+ MessageBeep(0xFFFFFFFF);
+ pC1->iPressedKey = -1;
+ return;
+ }
+ }
+
+ if ((iPressedKey != C1K_SHIFT) || !(pC1->dwFlags & FLAG_SHIFT_PRESSED))
+ {
+ hDC = GetDC(hWnd);
+ hMemDC = CreateCompatibleDC(hDC);
+ hbmOld = SelectObject(hMemDC, pC1->hbmKeyboard);
+ C1_InvertButton(hDC, pC1->iPressedKey);
+ C1_InvertButton(hMemDC, pC1->iPressedKey);
+ SelectObject(hMemDC, hbmOld);
+ DeleteDC(hMemDC);
+ ReleaseDC(hWnd, hDC);
+ }
+
+ pC1->dwFlags |= FLAG_PRESSED;
+}
+
+static BOOL
+C1_OnSetCursor(
+ _In_ HWND hWnd,
+ _In_ LPARAM lParam)
+{
+ HGLOBAL hGlobal;
+ PC1WINDOW pC1;
+ HCURSOR hCursor;
+ INT iKey;
+ POINT pt1, pt2;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pC1 = (PC1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pC1)
+ return FALSE;
+
+ if (pC1->dwFlags & FLAG_DRAGGING)
+ {
+ hCursor = LoadCursorW(0, (LPCWSTR)IDC_SIZEALL);
+ SetCursor(hCursor);
+ GlobalUnlock(hGlobal);
+ return TRUE;
+ }
+
+ GetCursorPos(&pt1);
+ pt2 = pt1;
+ ScreenToClient(hWnd, &pt2);
+
+ iKey = C1_HitTest(&pt2);
+ if (iKey == -1)
+ hCursor = LoadCursorW(0, (LPCWSTR)IDC_SIZEALL);
+ else
+ hCursor = LoadCursorW(0, (LPCWSTR)IDC_HAND);
+ SetCursor(hCursor);
+
+ if (HIWORD(lParam) == WM_LBUTTONDOWN)
+ {
+ pC1->pt1 = pt1;
+ pC1->pt2 = pt2;
+ pC1->iPressedKey = iKey;
+ C1_OnButtonDown(hWnd, pC1);
+ }
+
+ GlobalUnlock(hGlobal);
+ return TRUE;
+}
+
+static BOOL
+C1_OnMouseMove(
+ _In_ HWND hWnd,
+ _In_ WPARAM wParam,
+ _In_ LPARAM lParam)
+{
+ HGLOBAL hGlobal;
+ PC1WINDOW pC1;
+ HDC hMemDC;
+ DWORD dwFlags;
+ INT iPressedKey;
+ POINT pt;
+ HGDIOBJ hbmOld;
+ HDC hDC;
+ INT iKey;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pC1 = (PC1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pC1)
+ return FALSE;
+
+ if (pC1->dwFlags & FLAG_DRAGGING)
+ {
+ C1_DrawDragBorder(hWnd, &pC1->pt1, &pC1->pt2);
+ GetCursorPos(&pC1->pt1);
+ C1_DrawDragBorder(hWnd, &pC1->pt1, &pC1->pt2);
+ GlobalUnlock(hGlobal);
+ return TRUE;
+ }
+
+ if (pC1->iPressedKey != -1)
+ {
+ GetCursorPos(&pt);
+ ScreenToClient(hWnd, &pt);
+ iKey = C1_HitTest(&pt);
+
+ hDC = GetDC(hWnd);
+ hMemDC = CreateCompatibleDC(hDC);
+ hbmOld = SelectObject(hMemDC, pC1->hbmKeyboard);
+ dwFlags = pC1->dwFlags;
+
+ iPressedKey = pC1->iPressedKey;
+ if (!!(dwFlags & FLAG_PRESSED) == (iKey != iPressedKey))
+ {
+ if (iPressedKey != C1K_SHIFT || !(dwFlags & FLAG_SHIFT_PRESSED))
+ {
+ C1_InvertButton(hDC, iPressedKey);
+ C1_InvertButton(hMemDC, pC1->iPressedKey);
+ }
+
+ pC1->dwFlags ^= FLAG_PRESSED;
+ }
+
+ SelectObject(hMemDC, hbmOld);
+ DeleteDC(hMemDC);
+ ReleaseDC(hWnd, hDC);
+ }
+
+ GlobalUnlock(hGlobal);
+ return TRUE;
+}
+
+static BOOL
+C1_OnButtonUp(
+ _In_ HWND hWnd,
+ _In_ WPARAM wParam,
+ _In_ LPARAM lParam)
+{
+ HGLOBAL hGlobal;
+ PC1WINDOW pC1;
+ BOOL ret = FALSE;
+ INT x, y, iKey;
+ HDC hDC, hMemDC;
+ HGDIOBJ hbmOld;
+ HIMC hIMC;
+ HWND hwndOwner;
+ LPINPUTCONTEXT pIC;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pC1 = (PC1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pC1)
+ return FALSE;
+
+ ReleaseCapture();
+
+ if (pC1->dwFlags & FLAG_DRAGGING)
+ {
+ pC1->dwFlags &= ~FLAG_DRAGGING;
+ C1_DrawDragBorder(hWnd, &pC1->pt1, &pC1->pt2);
+ x = pC1->pt1.x - pC1->pt2.x;
+ y = pC1->pt1.y - pC1->pt2.y;
+ SetWindowPos(hWnd, 0, x, y, 0, 0, 0x15u);
+ ret = TRUE;
+
+ hwndOwner = GetWindow(hWnd, GW_OWNER);
+ hIMC = (HIMC)GetWindowLongPtrW(hwndOwner, 0);
+ if (hIMC)
+ {
+ pIC = ImmLockIMC(hIMC);
+ if (pIC)
+ {
+ pIC->fdwInit |= INIT_SOFTKBDPOS;
+ pIC->ptSoftKbdPos.x = x;
+ pIC->ptSoftKbdPos.y = y;
+ ImmUnlockIMC(hIMC);
+ }
+ }
+
+ GlobalUnlock(hGlobal);
+ return ret;
+ }
+
+ iKey = pC1->iPressedKey;
+ if (iKey == -1)
+ return FALSE;
+
+ if (!(pC1->dwFlags & FLAG_PRESSED))
+ {
+ pC1->iPressedKey = -1;
+ GlobalUnlock(hGlobal);
+ return ret;
+ }
+
+ if (iKey == C1K_SHIFT)
+ {
+ if (!(pC1->dwFlags & FLAG_SHIFT_PRESSED))
+ {
+ pC1->dwFlags |= FLAG_SHIFT_PRESSED;
+ pC1->dwFlags &= ~FLAG_PRESSED;
+ pC1->iPressedKey = -1;
+ GlobalUnlock(hGlobal);
+ return ret;
+ }
+ }
+ else if (iKey < C1K_BACKSPACE && (pC1->dwFlags &
FLAG_SHIFT_PRESSED))
+ {
+ INT iVK = gC1K2VK[pC1->iPressedKey];
+ keybd_event(VK_SHIFT, guScanCode[C1K_SHIFT], 0, 0);
+ keybd_event(iVK, guScanCode[(BYTE)iVK], 0, 0);
+ keybd_event(iVK, guScanCode[(BYTE)iVK], KEYEVENTF_KEYUP, 0);
+ keybd_event(VK_SHIFT, guScanCode[C1K_SHIFT], KEYEVENTF_KEYUP, 0);
+ }
+ else
+ {
+ INT iVK = gC1K2VK[iKey];
+ keybd_event(iVK, guScanCode[iVK], 0, 0);
+ keybd_event(iVK, guScanCode[iVK], KEYEVENTF_KEYUP, 0);
+ }
+
+ ret = TRUE;
+
+ hDC = GetDC(hWnd);
+ hMemDC = CreateCompatibleDC(hDC);
+ hbmOld = SelectObject(hMemDC, pC1->hbmKeyboard);
+
+ C1_InvertButton(hDC, pC1->iPressedKey);
+ C1_InvertButton(hMemDC, pC1->iPressedKey);
+
+ if (pC1->iPressedKey < C1K_BACKSPACE && (pC1->dwFlags &
FLAG_SHIFT_PRESSED))
+ {
+ C1_InvertButton(hDC, C1K_SHIFT);
+ C1_InvertButton(hMemDC, C1K_SHIFT);
+ }
+
+ if (pC1->iPressedKey < C1K_BACKSPACE || pC1->iPressedKey == C1K_SHIFT)
+ pC1->dwFlags &= ~FLAG_SHIFT_PRESSED;
+
+ SelectObject(hMemDC, hbmOld);
+ DeleteDC(hMemDC);
+ ReleaseDC(hWnd, hDC);
+
+ pC1->dwFlags &= ~FLAG_PRESSED;
+ pC1->iPressedKey = -1;
+ GlobalUnlock(hGlobal);
+ return ret;
+}
+
+static void
+C1_OnDestroy(
+ _In_ HWND hWnd)
+{
+ HGLOBAL hGlobal;
+ PC1WINDOW pC1;
+ HWND hwndOwner;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pC1 = (PC1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pC1)
+ return;
+
+ if (pC1->dwFlags & FLAG_DRAGGING)
+ C1_DrawDragBorder(hWnd, &pC1->pt1, &pC1->pt2);
+
+ DeleteObject(pC1->hbmKeyboard);
+ GlobalUnlock(hGlobal);
+ GlobalFree(hGlobal);
+
+ hwndOwner = GetWindow(hWnd, GW_OWNER);
+ if (hwndOwner)
+ SendMessageW(hwndOwner, WM_IME_NOTIFY, IMN_SOFTKBDDESTROYED, 0);
+}
+
+static LRESULT
+C1_OnImeControl(
+ _In_ HWND hWnd,
+ _In_ WPARAM wParam,
+ _In_ LPARAM lParam)
+{
+ HGLOBAL hGlobal;
+ PC1WINDOW pC1;
+ LOGFONTW lf;
+ RECT rc;
+ LRESULT ret = 0;
+ HDC hDC;
+
+ switch (wParam)
+ {
+ case IMC_GETSOFTKBDFONT:
+ {
+ TRACE("IMC_GETSOFTKBDFONT: %p\n", lParam);
+ hDC = GetDC(hWnd);
+ GetObjectW(GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONTW), &lf);
+ ReleaseDC(hWnd, hDC);
+ *(LPLOGFONTW)lParam = lf;
+ break;
+ }
+ case IMC_SETSOFTKBDFONT:
+ {
+ LPLOGFONTW plf = (LPLOGFONTW)lParam;
+ LOGFONTW lf;
+ TRACE("IMC_SETSOFTKBDFONT: %p\n", lParam);
+ GetObjectW(GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONTW), &lf);
+ if (lf.lfCharSet == plf->lfCharSet)
+ return 0;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pC1 = (PC1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pC1)
+ return 1;
+
+ pC1->CharSet = plf->lfCharSet;
+ GlobalUnlock(hGlobal);
+ break;
+ }
+ case IMC_GETSOFTKBDPOS:
+ {
+ TRACE("IMC_GETSOFTKBDPOS\n");
+ GetWindowRect(hWnd, &rc);
+ return MAKELRESULT(rc.left, rc.top);
+ }
+ case IMC_SETSOFTKBDPOS:
+ {
+ POINT pt;
+ POINTSTOPOINT(pt, lParam);
+ TRACE("IMC_SETSOFTKBDPOS: %d, %d\n", pt.x, pt.y);
+ SetWindowPos(hWnd, NULL, pt.x, pt.y, 0, 0,
+ (SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE));
+ break;
+ }
+ case IMC_GETSOFTKBDSUBTYPE:
+ case IMC_SETSOFTKBDSUBTYPE:
+ {
+ TRACE("IMC_GETSOFTKBDSUBTYPE/IMC_SETSOFTKBDSUBTYPE: %p, %p\n",
wParam, lParam);
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pC1 = (PC1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pC1)
+ return -1;
+ ret = pC1->SubType;
+ if (wParam == IMC_SETSOFTKBDSUBTYPE)
+ pC1->SubType = lParam;
+ GlobalUnlock(hGlobal);
+ break;
+ }
+ case IMC_SETSOFTKBDDATA:
+ {
+ TRACE("IMC_SETSOFTKBDDATA: %p\n", lParam);
+ if (C1_SetData(hWnd, (SOFTKBDDATA*)lParam))
+ return -1;
+
+ InvalidateRect(hWnd, 0, 0);
+ }
+ default:
+ break;
+ }
+
+ return ret;
+}
+
static LRESULT CALLBACK
C1_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
@@ -1130,10 +1988,47 @@ C1_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
case WM_CREATE:
{
- FIXME("stub\n");
- return -1;
+ return C1_OnCreate(hWnd);
+ }
+ case WM_DESTROY:
+ {
+ C1_OnDestroy(hWnd);
+ break;
+ }
+ case WM_SETCURSOR:
+ {
+ if (C1_OnSetCursor(hWnd, lParam))
+ break;
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+ }
+ case WM_MOUSEMOVE:
+ {
+ if (C1_OnMouseMove(hWnd, wParam, lParam))
+ break;
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+ }
+ case WM_LBUTTONUP:
+ {
+ if (C1_OnButtonUp(hWnd, wParam, lParam))
+ break;
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+ }
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hDC = BeginPaint(hWnd, &ps);
+ C1_OnDraw(hDC, hWnd);
+ EndPaint(hWnd, &ps);
+ break;
+ }
+ case WM_IME_CONTROL:
+ {
+ return C1_OnImeControl(hWnd, wParam, lParam);
+ }
+ case WM_MOUSEACTIVATE:
+ {
+ return MA_NOACTIVATE;
}
-
default:
{
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
@@ -1218,6 +2113,8 @@ ImmCreateSoftKeyboard(
LPCWSTR pszClass;
RECT rcWorkArea;
+ TRACE("(%u, %p, %d, %d)\n", uType, hwndParent, x, y);
+
if ((uType != SOFTKEYBOARD_TYPE_T1) && (uType != SOFTKEYBOARD_TYPE_C1))
{
ERR("uType: %u\n", uType);