https://git.reactos.org/?p=reactos.git;a=commitdiff;h=bd0629905963e0002ef77…
commit bd0629905963e0002ef778cd3b26ebcd95185dbb
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Fri Nov 24 23:02:19 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Fri Nov 24 23:02:19 2023 +0900
[IMM32][SDK] Implement IME Soft Keyboard Type T1 (#6021)
- Rename version.rc as imm32.rc.
- Add resource.h and t1keys.h.
- Add some resource bitmaps.
- Modify <immdev.h>.
Test:
Press Ctrl+Alt+comma on FreeCJ2004.
NOTE: There's a visual bug in PatBlt with negative values.
CORE-19268
---
dll/win32/imm32/CMakeLists.txt | 23 +-
dll/win32/imm32/{version.rc => imm32.rc} | 26 +
dll/win32/imm32/res/1033_Bitmap_100.bmp | Bin 0 -> 190 bytes
dll/win32/imm32/res/1033_Bitmap_101.bmp | Bin 0 -> 190 bytes
dll/win32/imm32/res/1033_Bitmap_102.bmp | Bin 0 -> 226 bytes
dll/win32/imm32/res/1033_Bitmap_103.bmp | Bin 0 -> 262 bytes
dll/win32/imm32/res/1033_Bitmap_104.bmp | Bin 0 -> 226 bytes
dll/win32/imm32/res/1033_Bitmap_105.bmp | Bin 0 -> 190 bytes
dll/win32/imm32/res/1033_Bitmap_106.bmp | Bin 0 -> 226 bytes
dll/win32/imm32/res/1033_Bitmap_107.bmp | Bin 0 -> 190 bytes
dll/win32/imm32/res/1033_Bitmap_108.bmp | Bin 0 -> 446 bytes
dll/win32/imm32/res/2052_Bitmap_201.bmp | Bin 0 -> 502 bytes
dll/win32/imm32/res/2052_Bitmap_202.bmp | Bin 0 -> 502 bytes
dll/win32/imm32/res/2052_Bitmap_203.bmp | Bin 0 -> 598 bytes
dll/win32/imm32/res/2052_Bitmap_204.bmp | Bin 0 -> 598 bytes
dll/win32/imm32/res/2052_Bitmap_205.bmp | Bin 0 -> 790 bytes
dll/win32/imm32/res/2052_Bitmap_206.bmp | Bin 0 -> 518 bytes
dll/win32/imm32/res/2052_Bitmap_207.bmp | Bin 0 -> 518 bytes
dll/win32/imm32/res/2052_Bitmap_208.bmp | Bin 0 -> 518 bytes
dll/win32/imm32/res/2052_Bitmap_209.bmp | Bin 0 -> 446 bytes
dll/win32/imm32/resource.h | 19 +
dll/win32/imm32/softkbd.c | 1260 +++++++++++++++++++++++++++---
dll/win32/imm32/t1keys.h | 68 ++
sdk/include/ddk/immdev.h | 16 +-
24 files changed, 1295 insertions(+), 117 deletions(-)
diff --git a/dll/win32/imm32/CMakeLists.txt b/dll/win32/imm32/CMakeLists.txt
index d5b2ea12af4..b765ec172ab 100644
--- a/dll/win32/imm32/CMakeLists.txt
+++ b/dll/win32/imm32/CMakeLists.txt
@@ -22,8 +22,29 @@ list(APPEND SOURCE
${CMAKE_CURRENT_BINARY_DIR}/imm32_stubs.c
${CMAKE_CURRENT_BINARY_DIR}/imm32.def)
-add_library(imm32 MODULE ${SOURCE} version.rc)
+list(APPEND imm32_rc_deps
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/1033_Bitmap_100.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/1033_Bitmap_101.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/1033_Bitmap_102.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/1033_Bitmap_103.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/1033_Bitmap_104.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/1033_Bitmap_105.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/1033_Bitmap_106.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/1033_Bitmap_107.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/1033_Bitmap_108.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/2052_Bitmap_201.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/2052_Bitmap_202.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/2052_Bitmap_203.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/2052_Bitmap_204.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/2052_Bitmap_205.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/2052_Bitmap_206.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/2052_Bitmap_207.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/2052_Bitmap_208.bmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/res/2052_Bitmap_209.bmp)
+
+add_library(imm32 MODULE ${SOURCE} imm32.rc)
set_module_type(imm32 win32dll UNICODE ENTRYPOINT ImmDllInitialize 12)
+set_source_files_properties(imm32.rc PROPERTIES OBJECT_DEPENDS
"${imm32_rc_deps}")
target_link_libraries(imm32 wine win32ksys)
add_importlibs(imm32 advapi32 user32 gdi32 kernel32 ntdll)
add_cd_file(TARGET imm32 DESTINATION reactos/system32 FOR all)
diff --git a/dll/win32/imm32/version.rc b/dll/win32/imm32/imm32.rc
similarity index 51%
rename from dll/win32/imm32/version.rc
rename to dll/win32/imm32/imm32.rc
index ae821025c01..317f986b7f2 100644
--- a/dll/win32/imm32/version.rc
+++ b/dll/win32/imm32/imm32.rc
@@ -24,3 +24,29 @@
#define WINE_PRODUCTVERSION_STR "5.1.2600.2180"
#include "wine/wine_common_ver.rc"
+
+#include "resource.h"
+
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
+
+IDB_T1_BACKSPACE BITMAP "res/1033_Bitmap_100.bmp"
+IDB_T1_TAB BITMAP "res/1033_Bitmap_101.bmp"
+IDB_T1_CAPS BITMAP "res/1033_Bitmap_102.bmp"
+IDB_T1_ENTER BITMAP "res/1033_Bitmap_103.bmp"
+IDB_T1_SHIFT BITMAP "res/1033_Bitmap_104.bmp"
+IDB_T1_CTRL BITMAP "res/1033_Bitmap_105.bmp"
+IDB_T1_ESCAPE BITMAP "res/1033_Bitmap_106.bmp"
+IDB_T1_ALT BITMAP "res/1033_Bitmap_107.bmp"
+IDB_T1_CHARS BITMAP "res/1033_Bitmap_108.bmp"
+
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
+
+IDB_C1_BACKSPACE BITMAP "res/2052_Bitmap_201.bmp"
+IDB_C1_TAB BITMAP "res/2052_Bitmap_202.bmp"
+IDB_C1_CAPS BITMAP "res/2052_Bitmap_203.bmp"
+IDB_C1_ENTER BITMAP "res/2052_Bitmap_204.bmp"
+IDB_C1_SHIFT BITMAP "res/2052_Bitmap_205.bmp"
+IDB_C1_INS BITMAP "res/2052_Bitmap_206.bmp"
+IDB_C1_DEL BITMAP "res/2052_Bitmap_207.bmp"
+IDB_C1_ESCAPE BITMAP "res/2052_Bitmap_208.bmp"
+IDB_C1_CHARS BITMAP "res/2052_Bitmap_209.bmp"
diff --git a/dll/win32/imm32/res/1033_Bitmap_100.bmp
b/dll/win32/imm32/res/1033_Bitmap_100.bmp
new file mode 100644
index 00000000000..79684fd689d
Binary files /dev/null and b/dll/win32/imm32/res/1033_Bitmap_100.bmp differ
diff --git a/dll/win32/imm32/res/1033_Bitmap_101.bmp
b/dll/win32/imm32/res/1033_Bitmap_101.bmp
new file mode 100644
index 00000000000..25cbf71f15c
Binary files /dev/null and b/dll/win32/imm32/res/1033_Bitmap_101.bmp differ
diff --git a/dll/win32/imm32/res/1033_Bitmap_102.bmp
b/dll/win32/imm32/res/1033_Bitmap_102.bmp
new file mode 100644
index 00000000000..063dbf4361b
Binary files /dev/null and b/dll/win32/imm32/res/1033_Bitmap_102.bmp differ
diff --git a/dll/win32/imm32/res/1033_Bitmap_103.bmp
b/dll/win32/imm32/res/1033_Bitmap_103.bmp
new file mode 100644
index 00000000000..44fdf073c2f
Binary files /dev/null and b/dll/win32/imm32/res/1033_Bitmap_103.bmp differ
diff --git a/dll/win32/imm32/res/1033_Bitmap_104.bmp
b/dll/win32/imm32/res/1033_Bitmap_104.bmp
new file mode 100644
index 00000000000..384b6cae779
Binary files /dev/null and b/dll/win32/imm32/res/1033_Bitmap_104.bmp differ
diff --git a/dll/win32/imm32/res/1033_Bitmap_105.bmp
b/dll/win32/imm32/res/1033_Bitmap_105.bmp
new file mode 100644
index 00000000000..49dc2b9bc84
Binary files /dev/null and b/dll/win32/imm32/res/1033_Bitmap_105.bmp differ
diff --git a/dll/win32/imm32/res/1033_Bitmap_106.bmp
b/dll/win32/imm32/res/1033_Bitmap_106.bmp
new file mode 100644
index 00000000000..01890744f87
Binary files /dev/null and b/dll/win32/imm32/res/1033_Bitmap_106.bmp differ
diff --git a/dll/win32/imm32/res/1033_Bitmap_107.bmp
b/dll/win32/imm32/res/1033_Bitmap_107.bmp
new file mode 100644
index 00000000000..755312a30fc
Binary files /dev/null and b/dll/win32/imm32/res/1033_Bitmap_107.bmp differ
diff --git a/dll/win32/imm32/res/1033_Bitmap_108.bmp
b/dll/win32/imm32/res/1033_Bitmap_108.bmp
new file mode 100644
index 00000000000..d98a6107674
Binary files /dev/null and b/dll/win32/imm32/res/1033_Bitmap_108.bmp differ
diff --git a/dll/win32/imm32/res/2052_Bitmap_201.bmp
b/dll/win32/imm32/res/2052_Bitmap_201.bmp
new file mode 100644
index 00000000000..d38078fa5bd
Binary files /dev/null and b/dll/win32/imm32/res/2052_Bitmap_201.bmp differ
diff --git a/dll/win32/imm32/res/2052_Bitmap_202.bmp
b/dll/win32/imm32/res/2052_Bitmap_202.bmp
new file mode 100644
index 00000000000..ea86471d6f4
Binary files /dev/null and b/dll/win32/imm32/res/2052_Bitmap_202.bmp differ
diff --git a/dll/win32/imm32/res/2052_Bitmap_203.bmp
b/dll/win32/imm32/res/2052_Bitmap_203.bmp
new file mode 100644
index 00000000000..d2def3fe5a7
Binary files /dev/null and b/dll/win32/imm32/res/2052_Bitmap_203.bmp differ
diff --git a/dll/win32/imm32/res/2052_Bitmap_204.bmp
b/dll/win32/imm32/res/2052_Bitmap_204.bmp
new file mode 100644
index 00000000000..b40316891af
Binary files /dev/null and b/dll/win32/imm32/res/2052_Bitmap_204.bmp differ
diff --git a/dll/win32/imm32/res/2052_Bitmap_205.bmp
b/dll/win32/imm32/res/2052_Bitmap_205.bmp
new file mode 100644
index 00000000000..6a3e43bea2e
Binary files /dev/null and b/dll/win32/imm32/res/2052_Bitmap_205.bmp differ
diff --git a/dll/win32/imm32/res/2052_Bitmap_206.bmp
b/dll/win32/imm32/res/2052_Bitmap_206.bmp
new file mode 100644
index 00000000000..f86ae147591
Binary files /dev/null and b/dll/win32/imm32/res/2052_Bitmap_206.bmp differ
diff --git a/dll/win32/imm32/res/2052_Bitmap_207.bmp
b/dll/win32/imm32/res/2052_Bitmap_207.bmp
new file mode 100644
index 00000000000..baa4c76d272
Binary files /dev/null and b/dll/win32/imm32/res/2052_Bitmap_207.bmp differ
diff --git a/dll/win32/imm32/res/2052_Bitmap_208.bmp
b/dll/win32/imm32/res/2052_Bitmap_208.bmp
new file mode 100644
index 00000000000..e29b9c40973
Binary files /dev/null and b/dll/win32/imm32/res/2052_Bitmap_208.bmp differ
diff --git a/dll/win32/imm32/res/2052_Bitmap_209.bmp
b/dll/win32/imm32/res/2052_Bitmap_209.bmp
new file mode 100644
index 00000000000..485074a9469
Binary files /dev/null and b/dll/win32/imm32/res/2052_Bitmap_209.bmp differ
diff --git a/dll/win32/imm32/resource.h b/dll/win32/imm32/resource.h
new file mode 100644
index 00000000000..9dba6404099
--- /dev/null
+++ b/dll/win32/imm32/resource.h
@@ -0,0 +1,19 @@
+/* Bitmap IDs */
+#define IDB_T1_BACKSPACE 100
+#define IDB_T1_TAB 101
+#define IDB_T1_CAPS 102
+#define IDB_T1_ENTER 103
+#define IDB_T1_SHIFT 104
+#define IDB_T1_CTRL 105
+#define IDB_T1_ESCAPE 106
+#define IDB_T1_ALT 107
+#define IDB_T1_CHARS 108
+#define IDB_C1_BACKSPACE 201
+#define IDB_C1_TAB 202
+#define IDB_C1_CAPS 203
+#define IDB_C1_ENTER 204
+#define IDB_C1_SHIFT 205
+#define IDB_C1_INS 206
+#define IDB_C1_DEL 207
+#define IDB_C1_ESCAPE 208
+#define IDB_C1_CHARS 209
diff --git a/dll/win32/imm32/softkbd.c b/dll/win32/imm32/softkbd.c
index 551331ffe40..8cf17248760 100644
--- a/dll/win32/imm32/softkbd.c
+++ b/dll/win32/imm32/softkbd.c
@@ -1,22 +1,53 @@
/*
* PROJECT: ReactOS IMM32
* LICENSE: LGPL-2.1-or-later (
https://spdx.org/licenses/LGPL-2.1-or-later)
- * PURPOSE: Implementing IMM Software Keyboard
+ * PURPOSE: Implementing IME Soft Keyboard
* COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
*/
#include "precomp.h"
+#include "resource.h"
WINE_DEFAULT_DEBUG_CHANNEL(imm);
-static UINT s_uScanCode[256];
-static RECT s_rcWorkArea;
-static POINT s_ptRaiseEdge;
-static LOGFONTW s_lfSKT1Font;
-static BOOL s_bWannaInitSoftKBD = TRUE;
+/*
+ * There are two types of IME Soft Keyboard: Type T1 and Type C1.
+ * T1 is created for Traditional Chinese but not limitted to it.
+ * C1 is created for Simplified Chinese but not limitted to it.
+ * Type C1 has SHIFT status while Type T1 hasn't.
+ */
+
+static UINT guScanCode[256]; /* Mapping: virtual key --> scan code */
+static POINT gptRaiseEdge; /* Border + Edge metrics */
+static BOOL g_bWantSoftKBDMetrics = TRUE;
+
+static inline BOOL
+Imm32PtInRect(
+ _In_ const POINT *ppt,
+ _In_ LONG x,
+ _In_ LONG y,
+ _In_ LONG cx,
+ _In_ LONG cy)
+{
+ return (x <= ppt->x) && (ppt->x < x + cx) && (y <=
ppt->y) && (ppt->y < y + cy);
+}
+
+static inline INT
+Imm32Clamp(
+ _In_ INT x,
+ _In_ INT xMin,
+ _In_ INT xMax)
+{
+ if (x < xMin)
+ return xMin;
+ if (x > xMax)
+ return xMax;
+ return x;
+}
static VOID
-Imm32GetAllMonitorSize(_Out_ LPRECT prcWork)
+Imm32GetAllMonitorSize(
+ _Out_ LPRECT prcWork)
{
if (GetSystemMetrics(SM_CMONITORS) == 1)
{
@@ -31,8 +62,8 @@ Imm32GetAllMonitorSize(_Out_ LPRECT prcWork)
}
static BOOL
-Imm32GetNearestMonitorSize(
- _In_ HWND hwnd,
+Imm32GetNearestWorkArea(
+ _In_opt_ HWND hwnd,
_Out_ LPRECT prcWork)
{
HMONITOR hMonitor;
@@ -46,39 +77,1054 @@ Imm32GetNearestMonitorSize(
hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (!hMonitor)
+ {
+ ERR("hwnd: %p\n", hwnd);
return FALSE;
+ }
ZeroMemory(&mi, sizeof(mi));
mi.cbSize = sizeof(mi);
GetMonitorInfoW(hMonitor, &mi);
-
*prcWork = mi.rcWork;
return TRUE;
}
-/* Software keyboard window procedure (Traditional Chinese) */
+/*****************************************************************************
+ * IME Soft Keyboard Type T1
+ */
+
+#define T1_CLASSNAMEW L"SoftKBDClsT1"
+
+#undef DEFINE_T1K
+#define DEFINE_T1K(t1k_code, virtual_key_code, t1k_code_name, virtual_key_name,
is_special) \
+ t1k_code_name = t1k_code,
+
+/* Define T1 internal codes (T1K_...) */
+typedef enum T1KEY
+{
+#include "t1keys.h"
+} T1KEY;
+
+#undef DEFINE_T1K
+#define DEFINE_T1K(t1k_code, virtual_key_code, t1k_code_name, virtual_key_name,
is_special) \
+ virtual_key_code,
+
+#define T1K_MAX 60
+
+/* Mapping: T1K --> Virtual Key */
+const BYTE gT1K2VK[T1K_MAX] =
+{
+#include "t1keys.h"
+};
+
+typedef struct T1WINDOW
+{
+ INT cxDefWidth; /* Regular key width */
+ INT cxWidth47; /* [BackSpace] width */
+ INT cxWidth48; /* [Tab] width */
+ INT cxWidth49; /* [Caps] width */
+ INT cxWidth50; /* [Enter] width */
+ INT cxWidth51or52; /* [Shift] width */
+ INT cxWidth53or54; /* [Ctrl] width */
+ INT cxWidth55or56; /* [Alt] width */
+ INT cxWidth57; /* [Esc] width */
+ INT cxWidth58; /* [Space] width */
+ INT cyDefHeight; /* Regular key height */
+ INT cyHeight50; /* [Enter] height */
+ POINT KeyPos[T1K_MAX]; /* T1K --> POINT */
+ WCHAR chKeyChar[48]; /* T1K --> WCHAR */
+ HBITMAP hbmKeyboard; /* The keyboard image */
+ DWORD CharSet; /* LOGFONT.lfCharSet */
+ UINT PressedKey; /* Currently pressed key */
+ POINT pt0, pt1; /* The soft keyboard window position */
+ LPARAM KeyboardSubType; /* See IMC_GETSOFTKBDSUBTYPE/IMC_SETSOFTKBDSUBTYPE */
+} T1WINDOW, *PT1WINDOW;
+
+#define T1_KEYPOS(iKey) pT1->KeyPos[iKey]
+
+static LOGFONTW g_T1LogFont;
+
+static void
+T1_GetTextMetric(_Out_ LPTEXTMETRICW ptm)
+{
+ WCHAR wch;
+ SIZE textSize;
+ HFONT hFont;
+ HGDIOBJ hFontOld;
+ HDC hDC;
+#ifndef NDEBUG
+ WCHAR szFace[LF_FACESIZE];
+#endif
+
+ ZeroMemory(&g_T1LogFont, sizeof(g_T1LogFont));
+ g_T1LogFont.lfHeight = -12;
+ g_T1LogFont.lfWeight = FW_NORMAL;
+ g_T1LogFont.lfCharSet = CHINESEBIG5_CHARSET;
+#ifdef NO_HACK /* FIXME: We lack proper Asian fonts! */
+ g_T1LogFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
+ g_T1LogFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ g_T1LogFont.lfQuality = PROOF_QUALITY;
+ g_T1LogFont.lfPitchAndFamily = FF_MODERN | FIXED_PITCH;
+#else
+ StringCchCopyW(g_T1LogFont.lfFaceName, _countof(g_T1LogFont.lfFaceName), L"MS
Shell Dlg");
+#endif
+ hFont = CreateFontIndirectW(&g_T1LogFont);
+
+ hDC = GetDC(NULL);
+ hFontOld = SelectObject(hDC, hFont);
+
+#ifndef NDEBUG
+ GetTextFaceW(hDC, _countof(szFace), szFace);
+ TRACE("szFace: %s\n", debugstr_w(szFace));
+#endif
+
+ GetTextMetricsW(hDC, ptm);
+
+ wch = 0x4E11; /* U+4E11: 丑 */
+ if (GetTextExtentPoint32W(hDC, &wch, 1, &textSize) && textSize.cx
> ptm->tmMaxCharWidth)
+ ptm->tmMaxCharWidth = textSize.cx;
+
+ DeleteObject(SelectObject(hDC, hFontOld));
+ ReleaseDC(NULL, hDC);
+}
+
+static void
+T1_InitButtonPos(_Out_ PT1WINDOW pT1)
+{
+ TEXTMETRICW tm;
+ LONG cxLarge, cyLarge;
+ LONG xKey1, yKey1, xKey2, yKey2, xKey3, yKey3;
+ LONG yKey4, xKey4, xKey5, yKey5, xKey6, xKey7;
+ INT iKey;
+
+ T1_GetTextMetric(&tm);
+
+ cxLarge = (3 * tm.tmMaxCharWidth + 18) / 2;
+ cyLarge = tm.tmHeight + 8;
+
+ /* key widths and heights */
+ pT1->cxDefWidth = (2 * tm.tmMaxCharWidth + 12) / 2;
+ pT1->cxWidth47 = (2 * tm.tmMaxCharWidth + 12) / 2 + 1;
+ pT1->cxWidth49 = (4 * tm.tmMaxCharWidth + 24) / 2 + 3;
+ pT1->cxWidth51or52 = (5 * tm.tmMaxCharWidth + 30) / 2 + 5;
+ pT1->cxWidth58 = 4 * (3 * tm.tmMaxCharWidth + 18) / 2 + 15;
+ pT1->cxWidth48 = pT1->cxWidth50 = cxLarge + 2;
+ pT1->cxWidth53or54 = pT1->cxWidth55or56 = cxLarge + 2;
+ pT1->cyHeight50 = 2 * (tm.tmHeight + 8) + 3;
+ pT1->cxWidth57 = cxLarge + 1;
+ pT1->cyDefHeight = cyLarge;
+
+ /* First row */
+ xKey1 = gptRaiseEdge.x + 3;
+ yKey1 = gptRaiseEdge.y + 3;
+ for (iKey = 0; iKey < T1K_Q; ++iKey)
+ {
+ T1_KEYPOS(iKey).x = xKey1;
+ T1_KEYPOS(iKey).y = yKey1;
+ xKey1 += pT1->cxDefWidth + 3;
+ }
+ T1_KEYPOS(T1K_BACKSPACE).y = yKey1;
+ T1_KEYPOS(T1K_BACKSPACE).x = xKey1;
+
+ /* 2nd row */
+ xKey2 = 3 + gptRaiseEdge.x + pT1->cxWidth48 + 3;
+ yKey2 = 3 + yKey1 + cyLarge;
+ T1_KEYPOS(T1K_TAB).x = gptRaiseEdge.x + 3;
+ T1_KEYPOS(T1K_TAB).y = yKey2;
+ for (iKey = T1K_Q; iKey < T1K_A; ++iKey)
+ {
+ T1_KEYPOS(iKey).x = xKey2;
+ T1_KEYPOS(iKey).y = yKey2;
+ xKey2 += pT1->cxDefWidth + 3;
+ }
+ T1_KEYPOS(T1K_ENTER).x = xKey2;
+ T1_KEYPOS(T1K_ENTER).y = yKey2;
+
+ /* 3rd row */
+ xKey3 = gptRaiseEdge.x + 3 + pT1->cxWidth49 + 3;
+ yKey3 = yKey2 + cyLarge + 3;
+ T1_KEYPOS(T1K_CAPS).x = gptRaiseEdge.x + 3;
+ T1_KEYPOS(T1K_CAPS).y = yKey3;
+ for (iKey = T1K_A; iKey < T1K_Z; ++iKey)
+ {
+ T1_KEYPOS(iKey).x = xKey3;
+ T1_KEYPOS(iKey).y = yKey3;
+ xKey3 += pT1->cxDefWidth + 3;
+ }
+
+ /* 4th row */
+ xKey4 = gptRaiseEdge.x + pT1->cxWidth51or52 + 3 + 3;
+ yKey4 = yKey3 + cyLarge + 3;
+ T1_KEYPOS(T1K_L_SHIFT).x = gptRaiseEdge.x + 3;
+ T1_KEYPOS(T1K_L_SHIFT).y = yKey4;
+ for (iKey = T1K_Z; iKey < T1K_BACKSPACE; ++iKey)
+ {
+ T1_KEYPOS(iKey).x = xKey4;
+ T1_KEYPOS(iKey).y = yKey4;
+ xKey4 += pT1->cxDefWidth + 3;
+ }
+ T1_KEYPOS(T1K_R_SHIFT).x = xKey4;
+ T1_KEYPOS(T1K_R_SHIFT).y = yKey4;
+
+ /* 5th row */
+ xKey5 = gptRaiseEdge.x + 3 + pT1->cxWidth53or54 + 3;
+ T1_KEYPOS(T1K_L_CTRL).x = gptRaiseEdge.x + 3;
+ T1_KEYPOS(T1K_ESCAPE).x = xKey5;
+ T1_KEYPOS(T1K_L_ALT).x = xKey5 + pT1->cxWidth57 + 3;
+
+ yKey5 = yKey4 + cyLarge + 3;
+ T1_KEYPOS(T1K_L_CTRL).y = T1_KEYPOS(T1K_ESCAPE).y = T1_KEYPOS(T1K_L_ALT).y = yKey5;
+ T1_KEYPOS(T1K_R_ALT).y = T1_KEYPOS(T1K_SPACE).y = T1_KEYPOS(T1K_R_CTRL).y = yKey5;
+
+ xKey6 = xKey5 + pT1->cxWidth57 + 3 + pT1->cxWidth55or56 + 3;
+ T1_KEYPOS(T1K_SPACE).x = xKey6;
+
+ xKey7 = xKey6 + pT1->cxWidth58 + 3;
+ T1_KEYPOS(T1K_R_ALT).x = xKey7;
+ T1_KEYPOS(T1K_R_CTRL).x = xKey7 + pT1->cxWidth57 + pT1->cxWidth55or56 + 6;
+}
+
+/* Draw keyboard key edge */
+static void
+T1_DrawConvexRect(
+ _In_ HDC hDC,
+ _In_ INT x,
+ _In_ INT y,
+ _In_ INT width,
+ _In_ INT height)
+{
+ HGDIOBJ hBlackPen = GetStockObject(BLACK_PEN);
+ HGDIOBJ hLtGrayBrush = GetStockObject(LTGRAY_BRUSH);
+ HGDIOBJ hGrayBrush = GetStockObject(GRAY_BRUSH);
+ INT dx = width + 4, dy = height + 4;
+ INT x0 = x - 2, y0 = y + height + 2;
+
+ /* Face */
+ SelectObject(hDC, hBlackPen);
+ SelectObject(hDC, hLtGrayBrush);
+ Rectangle(hDC, x0, y - 2, x0 + dx, y0);
+
+ /* Rounded corners */
+ PatBlt(hDC, x0, y - 2, 1, 1, PATCOPY);
+ PatBlt(hDC, x0, y0, 1, -1, PATCOPY);
+ PatBlt(hDC, x0 + dx, y - 2, -1, 1, PATCOPY);
+ PatBlt(hDC, x0 + dx, y0, -1, -1, PATCOPY);
+
+ /* Light edge */
+ PatBlt(hDC, x0 + 1, y + dy - 3, 1, 2 - dy, WHITENESS);
+ PatBlt(hDC, x0 + 1, y - 1, dx - 2, 1, WHITENESS);
+
+ /* Dark edge */
+ SelectObject(hDC, hGrayBrush);
+ PatBlt(hDC, x0 + 1, y + dy - 3, dx - 2, -1, PATCOPY);
+ 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,
+ _In_ const T1WINDOW *pT1,
+ _In_ LPCWSTR pszBmpName)
+{
+ HBITMAP hBitmap = LoadBitmapW(ghImm32Inst, pszBmpName);
+ HDC hdcMem = CreateCompatibleDC(hDC);
+ HGDIOBJ hbmOld = SelectObject(hdcMem, hBitmap);
+ INT iKey;
+ for (iKey = 0; iKey < T1K_BACKSPACE; ++iKey)
+ {
+ const POINT *ppt = &T1_KEYPOS(iKey);
+ BitBlt(hDC, ppt->x, ppt->y, 8, 8, hdcMem, iKey * 8, 0, SRCCOPY);
+ }
+ SelectObject(hdcMem, hbmOld);
+ DeleteDC(hdcMem);
+ DeleteObject(hBitmap);
+}
+
+static void
+T1_InitBitmap(
+ _In_ HWND hWnd,
+ _Inout_ PT1WINDOW pT1)
+{
+ HDC hDC, hMemDC;
+ HGDIOBJ hNullPen = GetStockObject(NULL_PEN), hbrLtGray =
GetStockObject(LTGRAY_BRUSH);
+ RECT rc;
+ INT iKey;
+
+ /* Create the bitmap */
+ hDC = GetDC(hWnd);
+ hMemDC = CreateCompatibleDC(hDC);
+ GetClientRect(hWnd, &rc);
+ pT1->hbmKeyboard = CreateCompatibleBitmap(hDC, rc.right - rc.left, rc.bottom -
rc.top);
+ ReleaseDC(hWnd, hDC);
+
+ /* Draw keyboard face */
+ SelectObject(hMemDC, pT1->hbmKeyboard);
+ SelectObject(hMemDC, hNullPen);
+ SelectObject(hMemDC, hbrLtGray);
+ Rectangle(hMemDC, rc.left, rc.top, rc.right + 1, rc.bottom + 1);
+ DrawEdge(hMemDC, &rc, EDGE_RAISED, BF_RECT);
+
+ /* 53 --> Left [Ctrl] */
+ 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);
+
+ /* 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);
+
+ /* 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);
+
+ /* 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);
+
+ /* 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);
+
+ /* 58 --> [Space] */
+ T1_DrawConvexRect(hMemDC,
+ T1_KEYPOS(T1K_SPACE).x, T1_KEYPOS(T1K_SPACE).y,
+ pT1->cxWidth58, pT1->cyDefHeight);
+
+ /* 51 --> Left [Shift] */
+ 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);
+
+ /* 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);
+
+ /* 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);
+
+ /* 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);
+
+ /* 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);
+
+ /* 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);
+
+ /* Regular keys */
+ for (iKey = 0; iKey < T1K_BACKSPACE; ++iKey)
+ {
+ LPPOINT ppt = &T1_KEYPOS(iKey);
+ T1_DrawConvexRect(hMemDC, ppt->x, ppt->y, pT1->cxDefWidth,
pT1->cyDefHeight);
+ }
+
+ T1_DrawLabels(hMemDC, pT1, MAKEINTRESOURCEW(IDB_T1_CHARS));
+ DeleteDC(hMemDC);
+}
+
+static INT
+T1_OnCreate(
+ _In_ HWND hWnd)
+{
+ PT1WINDOW pT1;
+ HGLOBAL hGlobal = GlobalAlloc(GHND, sizeof(T1WINDOW));
+ if (!hGlobal)
+ return -1;
+
+ pT1 = (PT1WINDOW)GlobalLock(hGlobal);
+ if (!pT1)
+ {
+ GlobalFree(hGlobal);
+ return -1;
+ }
+
+ SetWindowLongPtrW(hWnd, 0, (LONG_PTR)hGlobal);
+ pT1->pt1.x = pT1->pt1.y = -1;
+ pT1->PressedKey = T1K_NONE;
+ pT1->CharSet = CHINESEBIG5_CHARSET;
+
+ T1_InitButtonPos(pT1);
+ T1_InitBitmap(hWnd, pT1);
+ GlobalUnlock(hGlobal);
+
+ return 0;
+}
+
+static void
+T1_DrawDragBorder(
+ _In_ HWND hWnd,
+ _In_ const POINT *ppt1,
+ _In_ const POINT *ppt2)
+{
+ INT cxBorder = GetSystemMetrics(SM_CXBORDER), cyBorder =
GetSystemMetrics(SM_CYBORDER);
+ INT x = ppt1->x - ppt2->x, y = ppt1->y - ppt2->y;
+ HGDIOBJ hGrayBrush = GetStockObject(GRAY_BRUSH);
+ RECT rc;
+ HDC hDisplayDC;
+
+ GetWindowRect(hWnd, &rc);
+ hDisplayDC = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
+ SelectObject(hDisplayDC, hGrayBrush);
+ PatBlt(hDisplayDC, x, y, rc.right - rc.left - cxBorder, cyBorder, PATINVERT);
+ PatBlt(hDisplayDC, x, cyBorder + y, 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 void
+T1_OnDestroy(
+ _In_ HWND hWnd)
+{
+ HGLOBAL hGlobal;
+ PT1WINDOW pT1;
+ HWND hwndOwner;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pT1 = (PT1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pT1)
+ return;
+
+ if (pT1->pt1.x != -1 && pT1->pt1.y != -1)
+ T1_DrawDragBorder(hWnd, &pT1->pt0, &pT1->pt1);
+
+ DeleteObject(pT1->hbmKeyboard);
+ GlobalUnlock(hGlobal);
+ GlobalFree(hGlobal);
+
+ hwndOwner = GetWindow(hWnd, GW_OWNER);
+ if (hwndOwner)
+ SendMessageW(hwndOwner, WM_IME_NOTIFY, IMN_SOFTKBDDESTROYED, 0);
+}
+
+static void
+T1_InvertButton(
+ _In_ HWND hWnd,
+ _In_ HDC hDC,
+ _In_ const T1WINDOW *pT1,
+ _In_ UINT iPressed)
+{
+ INT cxWidth = pT1->cxDefWidth, cyHeight = pT1->cyDefHeight;
+ HDC hChoiceDC;
+
+ if (iPressed >= T1K_NONE)
+ return;
+
+ if (hDC)
+ hChoiceDC = hDC;
+ else
+ hChoiceDC = GetDC(hWnd);
+
+ if (iPressed >= T1K_BACKSPACE)
+ {
+ switch (iPressed)
+ {
+ case T1K_BACKSPACE:
+ cxWidth = pT1->cxWidth47;
+ break;
+ case T1K_TAB:
+ cxWidth = pT1->cxWidth48;
+ break;
+ case T1K_ENTER:
+ pT1 = pT1;
+ cxWidth = pT1->cxWidth50;
+ cyHeight = pT1->cyHeight50;
+ break;
+ case T1K_ESCAPE:
+ cxWidth = pT1->cxWidth57;
+ break;
+ case T1K_SPACE:
+ cxWidth = pT1->cxWidth58;
+ break;
+ default:
+ cxWidth = 0;
+ MessageBeep(0xFFFFFFFF);
+ break;
+ }
+ }
+
+ if (cxWidth > 0)
+ {
+ PatBlt(hChoiceDC,
+ T1_KEYPOS(iPressed).x - 1, T1_KEYPOS(iPressed).y - 1,
+ cxWidth + 2, cyHeight + 2,
+ DSTINVERT);
+ }
+
+ if (!hDC)
+ ReleaseDC(hWnd, hChoiceDC);
+}
+
+static void
+T1_OnDraw(
+ _In_ HDC hDC,
+ _In_ HWND hWnd)
+{
+ HGLOBAL hGlobal;
+ PT1WINDOW pT1;
+ HDC hMemDC;
+ RECT rc;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pT1 = (PT1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pT1)
+ return;
+
+ hMemDC = CreateCompatibleDC(hDC);
+ SelectObject(hMemDC, pT1->hbmKeyboard);
+ GetClientRect(hWnd, &rc);
+ BitBlt(hDC, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hMemDC, 0, 0, SRCCOPY);
+ DeleteDC(hMemDC);
+
+ if (pT1->PressedKey < T1K_NONE)
+ T1_InvertButton(hWnd, hDC, pT1, pT1->PressedKey);
+
+ GlobalUnlock(hGlobal);
+}
+
+static UINT
+T1_HitTest(
+ _In_ const T1WINDOW *pT1,
+ _In_ const POINT *ppt)
+{
+ INT iKey;
+ for (iKey = 0; iKey < T1K_BACKSPACE; ++iKey)
+ {
+ const POINT *pptKey = &T1_KEYPOS(iKey);
+ if (Imm32PtInRect(ppt, pptKey->x, pptKey->y, pT1->cxDefWidth,
pT1->cyDefHeight))
+ return iKey;
+ }
+
+ if (Imm32PtInRect(ppt, T1_KEYPOS(T1K_BACKSPACE).x, T1_KEYPOS(T1K_BACKSPACE).y,
pT1->cxWidth47, pT1->cyDefHeight))
+ return T1K_BACKSPACE;
+
+ if (Imm32PtInRect(ppt, T1_KEYPOS(T1K_TAB).x, T1_KEYPOS(T1K_TAB).y, pT1->cxWidth48,
pT1->cyDefHeight))
+ return T1K_TAB;
+
+ if (Imm32PtInRect(ppt, T1_KEYPOS(T1K_CAPS).x, T1_KEYPOS(T1K_CAPS).y,
pT1->cxWidth49, pT1->cyDefHeight))
+ return T1K_CAPS;
+
+ if (Imm32PtInRect(ppt, T1_KEYPOS(T1K_ENTER).x, T1_KEYPOS(T1K_ENTER).y,
pT1->cxWidth50, pT1->cyHeight50))
+ return T1K_ENTER;
+
+ if (Imm32PtInRect(ppt, T1_KEYPOS(T1K_L_SHIFT).x, T1_KEYPOS(T1K_L_SHIFT).y,
pT1->cxWidth51or52, pT1->cyDefHeight) ||
+ Imm32PtInRect(ppt, T1_KEYPOS(T1K_R_SHIFT).x, T1_KEYPOS(T1K_R_SHIFT).y,
pT1->cxWidth51or52, pT1->cyDefHeight))
+ {
+ return T1K_L_SHIFT;
+ }
+
+ if (Imm32PtInRect(ppt, T1_KEYPOS(T1K_L_CTRL).x, T1_KEYPOS(T1K_L_CTRL).y,
pT1->cxWidth53or54, pT1->cyDefHeight) ||
+ Imm32PtInRect(ppt, T1_KEYPOS(T1K_R_CTRL).x, T1_KEYPOS(T1K_R_CTRL).y,
pT1->cxWidth53or54, pT1->cyDefHeight))
+ {
+ return T1K_L_CTRL;
+ }
+
+ if (Imm32PtInRect(ppt, T1_KEYPOS(T1K_L_ALT).x, T1_KEYPOS(T1K_L_ALT).y,
pT1->cxWidth55or56, pT1->cyDefHeight) ||
+ Imm32PtInRect(ppt, T1_KEYPOS(T1K_R_ALT).x, T1_KEYPOS(T1K_R_ALT).y,
pT1->cxWidth55or56, pT1->cyDefHeight))
+ {
+ return T1K_L_ALT;
+ }
+
+ if (Imm32PtInRect(ppt, T1_KEYPOS(T1K_ESCAPE).x, T1_KEYPOS(T1K_ESCAPE).y,
pT1->cxWidth57, pT1->cyDefHeight))
+ return T1K_ESCAPE;
+
+ if (Imm32PtInRect(ppt, T1_KEYPOS(T1K_SPACE).x, T1_KEYPOS(T1K_SPACE).y,
pT1->cxWidth58, pT1->cyDefHeight))
+ return T1K_SPACE;
+
+ return T1K_NONE;
+}
+
+static BOOL
+T1_IsValidButton(
+ _In_ UINT iKey,
+ _In_ const T1WINDOW *pT1)
+{
+ if (iKey < T1K_BACKSPACE)
+ return !!pT1->chKeyChar[iKey];
+ return iKey <= T1K_TAB || iKey == T1K_ENTER || (T1K_ESCAPE <= iKey &&
iKey <= T1K_SPACE);
+}
+
+/**
+ * NOTE: The window that has WS_DISABLED style doesn't receive some mouse messages.
+ * Use WM_SETCURSOR handling to detect mouse events.
+ */
+static BOOL
+T1_OnSetCursor(
+ _In_ HWND hWnd,
+ _In_ LPARAM lParam)
+{
+ HGLOBAL hGlobal;
+ PT1WINDOW pT1;
+ HCURSOR hCursor;
+ UINT iPressed, iKey;
+ RECT rc, rcWork;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pT1 = (PT1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pT1)
+ return FALSE;
+
+ if (pT1->pt1.x != -1 && pT1->pt1.y != -1)
+ {
+ SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_SIZEALL));
+ GlobalUnlock(hGlobal);
+ return TRUE;
+ }
+
+ GetCursorPos(&pT1->pt0);
+ ScreenToClient(hWnd, &pT1->pt0);
+
+ iKey = T1_HitTest(pT1, &pT1->pt0);
+ if (iKey >= T1K_NONE)
+ hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_SIZEALL);
+ else
+ hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_HAND);
+ SetCursor(hCursor);
+
+ if (HIWORD(lParam) == WM_LBUTTONDOWN)
+ {
+ SetCapture(hWnd);
+
+ iPressed = pT1->PressedKey;
+ if (iPressed < T1K_NONE)
+ {
+ UINT iVK = gT1K2VK[iPressed];
+ keybd_event(iVK, guScanCode[iVK], KEYEVENTF_KEYUP, 0);
+ T1_InvertButton(hWnd, NULL, pT1, pT1->PressedKey);
+ pT1->PressedKey = T1K_NONE;
+ }
+
+ if (iKey >= T1K_NONE)
+ {
+ Imm32GetAllMonitorSize(&rcWork);
+ GetCursorPos(&pT1->pt0);
+ GetWindowRect(hWnd, &rc);
+ pT1->pt1.x = pT1->pt0.x - rc.left;
+ pT1->pt1.y = pT1->pt0.y - rc.top;
+ T1_DrawDragBorder(hWnd, &pT1->pt0, &pT1->pt1);
+ }
+ else if (T1_IsValidButton(iKey, pT1))
+ {
+ UINT iVK = gT1K2VK[iKey];
+ keybd_event(iVK, guScanCode[iVK], 0, 0);
+ pT1->PressedKey = iKey;
+ T1_InvertButton(hWnd, 0, pT1, iKey);
+ }
+ else
+ {
+ MessageBeep(0xFFFFFFFF);
+ }
+ }
+
+ return TRUE;
+}
+
+static BOOL
+T1_OnMouseMove(
+ _In_ HWND hWnd)
+{
+ BOOL ret = FALSE;
+ HGLOBAL hGlobal;
+ PT1WINDOW pT1;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pT1 = (PT1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pT1)
+ return FALSE;
+
+ if (pT1->pt1.x != -1 && pT1->pt1.y != -1)
+ {
+ T1_DrawDragBorder(hWnd, &pT1->pt0, &pT1->pt1);
+ GetCursorPos(&pT1->pt0);
+ T1_DrawDragBorder(hWnd, &pT1->pt0, &pT1->pt1);
+ ret = TRUE;
+ }
+
+ GlobalUnlock(hGlobal);
+ return ret;
+}
+
+static BOOL
+T1_OnButtonUp(
+ _In_ HWND hWnd)
+{
+ BOOL ret = FALSE;
+ HGLOBAL hGlobal;
+ PT1WINDOW pT1;
+ INT x, y, iPressed;
+ HWND hwndOwner, hwndCapture = GetCapture();
+ HIMC hIMC;
+ LPINPUTCONTEXT pIC;
+
+ if (hwndCapture == hWnd)
+ ReleaseCapture();
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pT1 = (PT1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pT1)
+ return FALSE;
+
+ iPressed = pT1->PressedKey;
+ if (iPressed >= T1K_NONE)
+ {
+ if (pT1->pt1.x != -1 && pT1->pt1.y != -1 )
+ {
+ T1_DrawDragBorder(hWnd, &pT1->pt0, &pT1->pt1);
+ x = pT1->pt0.x - pT1->pt1.x;
+ y = pT1->pt0.y - pT1->pt1.y;
+ SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER |
SWP_NOSIZE);
+ pT1->pt1.x = pT1->pt1.y = -1;
+ pT1->PressedKey = T1K_NONE;
+ 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);
+ }
+ }
+ }
+ }
+ else
+ {
+ UINT iVK = gT1K2VK[iPressed];
+ keybd_event(iVK, guScanCode[iVK], KEYEVENTF_KEYUP, 0);
+
+ T1_InvertButton(hWnd, 0, pT1, pT1->PressedKey);
+ pT1->PressedKey = T1K_NONE;
+ ret = TRUE;
+ }
+
+ GlobalUnlock(hGlobal);
+ return ret;
+}
+
+static LRESULT
+T1_SetData(
+ _In_ HWND hWnd,
+ _In_ const SOFTKBDDATA *pData)
+{
+ HGLOBAL hGlobal;
+ PT1WINDOW pT1;
+ HDC hDC, hMemDC;
+ HFONT hFont;
+ HGDIOBJ hFontOld, hbmOld;
+ RECT rc;
+ INT iKey;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pT1 = (PT1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pT1)
+ return 1;
+
+ hDC = GetDC(hWnd);
+ hMemDC = CreateCompatibleDC(hDC);
+ ReleaseDC(hWnd, hDC);
+
+ hbmOld = SelectObject(hMemDC, pT1->hbmKeyboard);
+#if 0 /* The default text color is black */
+ SetTextColor(hMemDC, RGB(0, 0, 0));
+#endif
+ SetBkColor(hMemDC, RGB(192, 192, 192));
+
+ if (pT1->CharSet == DEFAULT_CHARSET)
+ {
+ hFont = CreateFontIndirectW(&g_T1LogFont);
+ }
+ else
+ {
+ LOGFONTW lf = g_T1LogFont;
+ lf.lfCharSet = (BYTE)pT1->CharSet;
+ hFont = CreateFontIndirectW(&lf);
+ }
+ hFontOld = SelectObject(hMemDC, hFont);
+
+ for (iKey = 0; iKey < T1K_BACKSPACE; ++iKey)
+ {
+ INT x0 = T1_KEYPOS(iKey).x, y0 = T1_KEYPOS(iKey).y;
+ INT x = x0 + 6, y = y0 + 8;
+ WCHAR wch = pT1->chKeyChar[iKey] = pData->wCode[0][gT1K2VK[iKey]];
+ SetRect(&rc, x, y, x0 + pT1->cxDefWidth, y0 + pT1->cyDefHeight);
+ ExtTextOutW(hMemDC, x, y, ETO_OPAQUE, &rc, &wch, wch != 0, NULL);
+ }
+
+ DeleteObject(SelectObject(hMemDC, hFontOld));
+ SelectObject(hMemDC, hbmOld);
+ DeleteDC(hMemDC);
+ GlobalUnlock(hGlobal);
+ return 0;
+}
+
+static LRESULT
+T1_OnImeControl(
+ _In_ HWND hWnd,
+ _Inout_ WPARAM wParam,
+ _Inout_ LPARAM lParam)
+{
+ LRESULT ret = 1;
+ PT1WINDOW pT1;
+ HGLOBAL hGlobal;
+
+ switch (wParam)
+ {
+ case IMC_GETSOFTKBDFONT:
+ {
+ TRACE("IMC_GETSOFTKBDFONT: %p\n", lParam);
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pT1 = (PT1WINDOW)GlobalLock(hGlobal);
+ if (hGlobal && pT1)
+ {
+ LPLOGFONTW plf = (LPLOGFONTW)lParam;
+ DWORD CharSet = pT1->CharSet;
+ GlobalUnlock(hGlobal);
+
+ *plf = g_T1LogFont;
+ if (CharSet != DEFAULT_CHARSET)
+ plf->lfCharSet = (BYTE)CharSet;
+
+ ret = 0;
+ }
+ break;
+ }
+ case IMC_SETSOFTKBDFONT:
+ {
+ const LOGFONTW *plf = (LPLOGFONTW)lParam;
+ TRACE("IMC_SETSOFTKBDFONT: %p\n", lParam);
+ if (g_T1LogFont.lfCharSet == plf->lfCharSet)
+ return 0;
+
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pT1 = (PT1WINDOW)GlobalLock(hGlobal);
+ if (hGlobal && pT1)
+ {
+ pT1->CharSet = plf->lfCharSet;
+ GlobalUnlock(hGlobal);
+ return 0;
+ }
+
+ break;
+ }
+ case IMC_GETSOFTKBDPOS:
+ {
+ RECT rc;
+ TRACE("IMC_GETSOFTKBDPOS\n");
+ GetWindowRect(hWnd, &rc);
+ return MAKELRESULT(rc.left, rc.top);
+ }
+ case IMC_SETSOFTKBDPOS:
+ {
+ POINT pt;
+ HWND hwndParent;
+
+ POINTSTOPOINT(pt, lParam);
+ TRACE("IMC_SETSOFTKBDPOS(%ld, %ld)\n", pt.x, pt.y);
+
+ SetWindowPos(hWnd, NULL, pt.x, pt.y, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER |
SWP_NOSIZE);
+
+ hwndParent = GetParent(hWnd);
+ if (hwndParent)
+ {
+ HIMC hIMC = (HIMC)GetWindowLongPtrW(hwndParent, 0);
+ if (hIMC)
+ {
+ LPINPUTCONTEXT pIC = ImmLockIMC(hIMC);
+ if (pIC)
+ {
+ pIC->ptSoftKbdPos.x = pt.x;
+ pIC->ptSoftKbdPos.y = pt.y;
+ ImmUnlockIMC(hIMC);
+ return 0;
+ }
+ }
+ }
+ break;
+ }
+ case IMC_GETSOFTKBDSUBTYPE:
+ case IMC_SETSOFTKBDSUBTYPE:
+ {
+ TRACE("IMC_GETSOFTKBDSUBTYPE/IMC_SETSOFTKBDSUBTYPE\n");
+ hGlobal = (HGLOBAL)GetWindowLongPtrW(hWnd, 0);
+ pT1 = (PT1WINDOW)GlobalLock(hGlobal);
+ if (!hGlobal || !pT1)
+ return -1;
+
+ ret = pT1->KeyboardSubType;
+
+ if (wParam == IMC_SETSOFTKBDSUBTYPE)
+ pT1->KeyboardSubType = lParam;
+
+ GlobalUnlock(hGlobal);
+ break;
+ }
+ case IMC_SETSOFTKBDDATA:
+ {
+ TRACE("IMC_SETSOFTKBDDATA: %p\n", lParam);
+ ret = T1_SetData(hWnd, (SOFTKBDDATA*)lParam);
+ if (!ret)
+ {
+ InvalidateRect(hWnd, NULL, FALSE);
+ PostMessageW(hWnd, WM_PAINT, 0, 0);
+ }
+ break;
+ }
+ }
+
+ return ret;
+}
+
static LRESULT CALLBACK
-SKWndProcT1(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+T1_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
{
- FIXME("stub\n");
- return -1;
+ return T1_OnCreate(hWnd);
+ }
+ case WM_DESTROY:
+ {
+ T1_OnDestroy(hWnd);
+ break;
+ }
+ case WM_SETCURSOR:
+ {
+ if (T1_OnSetCursor(hWnd, lParam))
+ break;
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+ }
+ case WM_MOUSEMOVE:
+ {
+ if (T1_OnMouseMove(hWnd))
+ break;
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+ }
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hDC = BeginPaint(hWnd, &ps);
+ T1_OnDraw(hDC, hWnd);
+ EndPaint(hWnd, &ps);
+ break;
+ }
+ case WM_SHOWWINDOW:
+ {
+ if (!lParam && wParam != SW_SHOWNORMAL)
+ T1_OnButtonUp(hWnd);
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+ }
+ case WM_MOUSEACTIVATE:
+ {
+ return MA_NOACTIVATE;
+ }
+ case WM_LBUTTONUP:
+ {
+ if (T1_OnButtonUp(hWnd))
+ break;
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+ }
+ case WM_IME_CONTROL:
+ {
+ return T1_OnImeControl(hWnd, wParam, lParam);
}
-
default:
{
- return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
}
+
return 0;
}
-/* Software keyboard window procedure (Simplified Chinese) */
+/*****************************************************************************
+ * IME Soft Keyboard Type C1
+ */
+
+#define C1_CLASSNAMEW L"SoftKBDClsC1"
+
static LRESULT CALLBACK
-SKWndProcC1(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+C1_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
@@ -90,102 +1136,62 @@ SKWndProcC1(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
default:
{
- return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
}
return 0;
}
+/*****************************************************************************/
+
static BOOL
-Imm32RegisterSoftKeyboard(_In_ UINT uType)
+Imm32RegisterSoftKeyboard(
+ _In_ UINT uType)
{
- LPCWSTR pszClass;
WNDCLASSEXW wcx;
-
- if (uType == 1)
- pszClass = L"SoftKBDClsT1";
- else if (uType == 2)
- pszClass = L"SoftKBDClsC1";
- else
- return FALSE;
-
+ LPCWSTR pszClass = ((uType == SOFTKEYBOARD_TYPE_T1) ? T1_CLASSNAMEW :
C1_CLASSNAMEW);
if (GetClassInfoExW(ghImm32Inst, pszClass, &wcx))
return TRUE;
ZeroMemory(&wcx, sizeof(wcx));
- wcx.cbSize = sizeof(wcx);
- wcx.style = CS_IME;
- wcx.cbWndExtra = sizeof(LONG_PTR);
- wcx.hIcon = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
- wcx.hInstance = ghImm32Inst;
- wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_SIZEALL);
+ wcx.cbSize = sizeof(wcx);
+ wcx.style = CS_IME;
+ wcx.cbWndExtra = sizeof(PT1WINDOW);
+ wcx.hIcon = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
+ wcx.hInstance = ghImm32Inst;
+ wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_SIZEALL);
wcx.lpszClassName = pszClass;
- if (uType == 1)
+ if (uType == SOFTKEYBOARD_TYPE_T1)
{
- wcx.lpfnWndProc = SKWndProcT1;
+ wcx.lpfnWndProc = T1_WindowProc;
wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
}
else
{
- wcx.lpfnWndProc = SKWndProcC1;
+ wcx.lpfnWndProc = C1_WindowProc;
wcx.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
}
return !!RegisterClassExW(&wcx);
}
-static VOID
-Imm32GetSKT1TextMetric(_Out_ LPTEXTMETRICW lptm)
-{
- HDC hDC;
- HFONT hFont;
- SIZE size;
- HGDIOBJ hFontOld;
- WCHAR szText[2] = { 0x894E, 0 };
-
- hDC = GetDC(NULL);
-
- ZeroMemory(&s_lfSKT1Font, sizeof(s_lfSKT1Font));
- s_lfSKT1Font.lfHeight = -12;
- s_lfSKT1Font.lfWeight = FW_NORMAL;
- s_lfSKT1Font.lfCharSet = CHINESEBIG5_CHARSET;
- s_lfSKT1Font.lfOutPrecision = OUT_TT_ONLY_PRECIS;
- s_lfSKT1Font.lfClipPrecision = CLIP_DEFAULT_PRECIS;
- s_lfSKT1Font.lfQuality = PROOF_QUALITY;
- s_lfSKT1Font.lfPitchAndFamily = 49;
- hFont = CreateFontIndirectW(&s_lfSKT1Font);
-
- hFontOld = SelectObject(hDC, hFont);
-
- GetTextMetricsW(hDC, lptm);
-
- if (GetTextExtentPoint32W(hDC, szText, 1, &size) &&
lptm->tmMaxCharWidth < size.cx )
- lptm->tmMaxCharWidth = size.cx;
-
- DeleteObject(SelectObject(hDC, hFontOld));
- ReleaseDC(NULL, hDC);
-}
-
-static VOID
+static void
Imm32GetSoftKeyboardDimension(
_In_ UINT uType,
_Out_ LPINT pcx,
_Out_ LPINT pcy)
{
- INT cxEdge, cyEdge;
- TEXTMETRICW tm;
-
- if (uType == 1)
+ if (uType == SOFTKEYBOARD_TYPE_T1)
{
- Imm32GetSKT1TextMetric(&tm);
- *pcx = 15 * tm.tmMaxCharWidth + 2 * s_ptRaiseEdge.x + 139;
- *pcy = 5 * tm.tmHeight + 2 * s_ptRaiseEdge.y + 58;
+ TEXTMETRICW tm;
+ T1_GetTextMetric(&tm);
+ *pcx = 15 * tm.tmMaxCharWidth + 2 * gptRaiseEdge.x + 139;
+ *pcy = 5 * tm.tmHeight + 2 * gptRaiseEdge.y + 58;
}
else
{
- cxEdge = GetSystemMetrics(SM_CXEDGE);
- cyEdge = GetSystemMetrics(SM_CYEDGE);
+ INT cxEdge = GetSystemMetrics(SM_CXEDGE), cyEdge = GetSystemMetrics(SM_CXEDGE);
*pcx = 2 * (GetSystemMetrics(SM_CXBORDER) + cxEdge) + 348;
*pcy = 2 * (GetSystemMetrics(SM_CYBORDER) + cyEdge) + 136;
}
@@ -205,65 +1211,85 @@ ImmCreateSoftKeyboard(
{
HKL hKL;
PIMEDPI pImeDpi;
- DWORD dwUICaps, style = (WS_POPUP | WS_DISABLED);
- UINT i;
- INT xSoftKBD, ySoftKBD, cxSoftKBD, cySoftKBD;
+ UINT iVK;
+ INT xSoftKBD, ySoftKBD, cxSoftKBD, cySoftKBD, cxEdge, cyEdge;
HWND hwndSoftKBD;
+ DWORD Style, ExStyle, UICaps;
+ LPCWSTR pszClass;
+ RECT rcWorkArea;
- TRACE("(%u, %p, %d, %d)\n", uType, hwndParent, x, y);
-
- if (uType != 1 && uType != 2)
- return 0;
+ if ((uType != SOFTKEYBOARD_TYPE_T1) && (uType != SOFTKEYBOARD_TYPE_C1))
+ {
+ ERR("uType: %u\n", uType);
+ return NULL; /* Invalid keyboard type */
+ }
+ /* Check IME */
hKL = GetKeyboardLayout(0);
pImeDpi = ImmLockImeDpi(hKL);
- if (!pImeDpi)
- return NULL;
+ if (IS_NULL_UNEXPECTEDLY(pImeDpi))
+ return NULL; /* No IME */
- dwUICaps = pImeDpi->ImeInfo.fdwUICaps;
+ UICaps = pImeDpi->ImeInfo.fdwUICaps;
ImmUnlockImeDpi(pImeDpi);
- if (!(dwUICaps & UI_CAP_SOFTKBD))
- return NULL;
-
- if (s_bWannaInitSoftKBD)
+ /* Check IME capability */
+ if (!(UICaps & UI_CAP_SOFTKBD))
{
- if (!Imm32GetNearestMonitorSize(hwndParent, &s_rcWorkArea))
- return NULL;
+ ERR("UICaps: 0x%X\n", UICaps);
+ return NULL; /* No capability for soft keyboard */
+ }
- for (i = 0; i < 0xFF; ++i)
- s_uScanCode[i] = MapVirtualKeyW(i, 0);
+ /* Want metrics? */
+ if (g_bWantSoftKBDMetrics)
+ {
+ for (iVK = 0; iVK < 0xFF; ++iVK)
+ {
+ guScanCode[iVK] = MapVirtualKeyW(iVK, 0);
+ }
- s_ptRaiseEdge.x = GetSystemMetrics(SM_CXBORDER) + GetSystemMetrics(SM_CXEDGE);
- s_ptRaiseEdge.y = GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYEDGE);
+ cxEdge = GetSystemMetrics(SM_CXEDGE);
+ cyEdge = GetSystemMetrics(SM_CYEDGE);
+ gptRaiseEdge.x = GetSystemMetrics(SM_CXBORDER) + cxEdge;
+ gptRaiseEdge.y = GetSystemMetrics(SM_CYBORDER) + cyEdge;
- s_bWannaInitSoftKBD = FALSE;
+ g_bWantSoftKBDMetrics = FALSE;
}
+ if (!Imm32GetNearestWorkArea(hwndParent, &rcWorkArea))
+ return NULL;
+
+ /* Register the window class */
if (!Imm32RegisterSoftKeyboard(uType))
+ {
+ ERR("\n");
return NULL;
+ }
+ /* Calculate keyboard size */
Imm32GetSoftKeyboardDimension(uType, &cxSoftKBD, &cySoftKBD);
- xSoftKBD = max(s_rcWorkArea.left, min(x, s_rcWorkArea.right - cxSoftKBD));
- ySoftKBD = max(s_rcWorkArea.top, min(y, s_rcWorkArea.bottom - cySoftKBD));
+ /* Adjust keyboard position */
+ xSoftKBD = Imm32Clamp(x, rcWorkArea.left, rcWorkArea.right - cxSoftKBD);
+ ySoftKBD = Imm32Clamp(y, rcWorkArea.top , rcWorkArea.bottom - cySoftKBD);
- if (uType == 1) /* Traditional Chinese */
+ /* Create soft keyboard window */
+ if (uType == SOFTKEYBOARD_TYPE_T1)
{
- hwndSoftKBD = CreateWindowExW(0,
- L"SoftKBDClsT1", NULL, style,
- xSoftKBD, ySoftKBD, cxSoftKBD, cySoftKBD,
- hwndParent, NULL, ghImm32Inst, NULL);
+ Style = (WS_POPUP | WS_DISABLED);
+ ExStyle = 0;
+ pszClass = T1_CLASSNAMEW;
}
- else /* Simplified Chinese (uType == 2) */
+ else
{
- style |= WS_BORDER;
- hwndSoftKBD = CreateWindowExW(WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME,
- L"SoftKBDClsC1", NULL, style,
- xSoftKBD, ySoftKBD, cxSoftKBD, cySoftKBD,
- hwndParent, NULL, ghImm32Inst, NULL);
+ Style = (WS_POPUP | WS_DISABLED | WS_BORDER);
+ ExStyle = (WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME);
+ pszClass = C1_CLASSNAMEW;
}
-
+ hwndSoftKBD = CreateWindowExW(ExStyle, pszClass, NULL, Style,
+ xSoftKBD, ySoftKBD, cxSoftKBD, cySoftKBD,
+ hwndParent, NULL, ghImm32Inst, NULL);
+ /* Initial is hidden */
ShowWindow(hwndSoftKBD, SW_HIDE);
UpdateWindow(hwndSoftKBD);
@@ -281,6 +1307,10 @@ ImmShowSoftKeyboard(
_In_ INT nCmdShow)
{
TRACE("(%p, %d)\n", hwndSoftKBD, nCmdShow);
+
+ if (nCmdShow != SW_HIDE && nCmdShow != SW_SHOWNOACTIVATE)
+ WARN("nCmdShow %d is unexpected\n", nCmdShow);
+
return hwndSoftKBD && ShowWindow(hwndSoftKBD, nCmdShow);
}
diff --git a/dll/win32/imm32/t1keys.h b/dll/win32/imm32/t1keys.h
new file mode 100644
index 00000000000..22ed5b42469
--- /dev/null
+++ b/dll/win32/imm32/t1keys.h
@@ -0,0 +1,68 @@
+/*
+ * PROJECT: ReactOS IMM32
+ * LICENSE: LGPL-2.1-or-later (
https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE: Defining internal codes (T1K_...) of IME Soft Keyboard Type T1
+ * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
+ */
+
+/* DEFINE_T1K(t1k_code, virtual_key_code, t1k_code_name, virtual_key_name, is_special)
*/
+DEFINE_T1K( 0, 0xC0, T1K_BACKTICK, VK_OEM_3, FALSE)
+DEFINE_T1K( 1, 0x31, T1K_1, VK_1, FALSE)
+DEFINE_T1K( 2, 0x32, T1K_2, VK_2, FALSE)
+DEFINE_T1K( 3, 0x33, T1K_3, VK_3, FALSE)
+DEFINE_T1K( 4, 0x34, T1K_4, VK_4, FALSE)
+DEFINE_T1K( 5, 0x35, T1K_5, VK_5, FALSE)
+DEFINE_T1K( 6, 0x36, T1K_6, VK_6, FALSE)
+DEFINE_T1K( 7, 0x37, T1K_7, VK_7, FALSE)
+DEFINE_T1K( 8, 0x38, T1K_8, VK_8, FALSE)
+DEFINE_T1K( 9, 0x39, T1K_9, VK_9, FALSE)
+DEFINE_T1K(10, 0x30, T1K_0, VK_0, FALSE)
+DEFINE_T1K(11, 0xBD, T1K_MINUS, VK_OEM_MINUS, FALSE)
+DEFINE_T1K(12, 0xBB, T1K_PLUS, VK_OEM_PLUS, FALSE)
+DEFINE_T1K(13, 0xDC, T1K_OEM_5, VK_OEM_5, FALSE)
+DEFINE_T1K(14, 0x51, T1K_Q, VK_Q, FALSE)
+DEFINE_T1K(15, 0x57, T1K_W, VK_W, FALSE)
+DEFINE_T1K(16, 0x45, T1K_E, VK_E, FALSE)
+DEFINE_T1K(17, 0x52, T1K_R, VK_R, FALSE)
+DEFINE_T1K(18, 0x54, T1K_T, VK_T, FALSE)
+DEFINE_T1K(19, 0x59, T1K_Y, VK_Y, FALSE)
+DEFINE_T1K(20, 0x55, T1K_U, VK_U, FALSE)
+DEFINE_T1K(21, 0x49, T1K_I, VK_I, FALSE)
+DEFINE_T1K(22, 0x4F, T1K_O, VK_O, FALSE)
+DEFINE_T1K(23, 0x50, T1K_P, VK_P, FALSE)
+DEFINE_T1K(24, 0xDB, T1K_OEM_4, VK_OEM_4, FALSE)
+DEFINE_T1K(25, 0xDD, T1K_OEM_6, VK_OEM_6, FALSE)
+DEFINE_T1K(26, 0x41, T1K_A, VK_A, FALSE)
+DEFINE_T1K(27, 0x53, T1K_S, VK_S, FALSE)
+DEFINE_T1K(28, 0x44, T1K_D, VK_D, FALSE)
+DEFINE_T1K(29, 0x46, T1K_F, VK_F, FALSE)
+DEFINE_T1K(30, 0x47, T1K_G, VK_G, FALSE)
+DEFINE_T1K(31, 0x48, T1K_H, VK_H, FALSE)
+DEFINE_T1K(32, 0x4A, T1K_J, VK_J, FALSE)
+DEFINE_T1K(33, 0x4B, T1K_K, VK_K, FALSE)
+DEFINE_T1K(34, 0x4C, T1K_L, VK_L, FALSE)
+DEFINE_T1K(35, 0xBA, T1K_OEM_1, VK_OEM_1, FALSE)
+DEFINE_T1K(36, 0xDE, T1K_OEM_7, VK_OEM_7, FALSE)
+DEFINE_T1K(37, 0x5A, T1K_Z, VK_Z, FALSE)
+DEFINE_T1K(38, 0x58, T1K_X, VK_X, FALSE)
+DEFINE_T1K(39, 0x43, T1K_C, VK_C, FALSE)
+DEFINE_T1K(40, 0x56, T1K_V, VK_V, FALSE)
+DEFINE_T1K(41, 0x42, T1K_B, VK_B, FALSE)
+DEFINE_T1K(42, 0x4E, T1K_N, VK_N, FALSE)
+DEFINE_T1K(43, 0x4D, T1K_M, VK_M, FALSE)
+DEFINE_T1K(44, 0xBC, T1K_OEM_COMMA, VK_OEM_COMMA, FALSE)
+DEFINE_T1K(45, 0xBE, T1K_OEM_PERIOD, VK_OEM_PERIOD, FALSE)
+DEFINE_T1K(46, 0xBF, T1K_OEM_2, VK_OEM_2, FALSE)
+DEFINE_T1K(47, 0x08, T1K_BACKSPACE, VK_BACK, TRUE)
+DEFINE_T1K(48, 0x09, T1K_TAB, VK_TAB, TRUE)
+DEFINE_T1K(49, 0x14, T1K_CAPS, VK_CAPITAL, TRUE)
+DEFINE_T1K(50, 0x0D, T1K_ENTER, VK_RETURN, TRUE)
+DEFINE_T1K(51, 0x10, T1K_L_SHIFT, VK_SHIFT, TRUE)
+DEFINE_T1K(52, 0x10, T1K_R_SHIFT, VK_SHIFT, TRUE)
+DEFINE_T1K(53, 0x11, T1K_L_CTRL, VK_CONTROL, TRUE)
+DEFINE_T1K(54, 0x11, T1K_R_CTRL, VK_CONTROL, TRUE)
+DEFINE_T1K(55, 0x12, T1K_L_ALT, VK_MENU, TRUE)
+DEFINE_T1K(56, 0x12, T1K_R_ALT, VK_MENU, TRUE)
+DEFINE_T1K(57, 0x1B, T1K_ESCAPE, VK_ESCAPE, TRUE)
+DEFINE_T1K(58, 0x20, T1K_SPACE, VK_SPACE, TRUE)
+DEFINE_T1K(59, 0x00, T1K_NONE, 0, TRUE)
diff --git a/sdk/include/ddk/immdev.h b/sdk/include/ddk/immdev.h
index 619ac609367..8a8586b774d 100644
--- a/sdk/include/ddk/immdev.h
+++ b/sdk/include/ddk/immdev.h
@@ -17,12 +17,23 @@
extern "C" {
#endif
+typedef struct tagSOFTKBDDATA
+{
+ UINT uCount;
+ WORD wCode[1][256];
+} SOFTKBDDATA, *PSOFTKBDDATA, *LPSOFTKBDDATA;
+
/* wParam for WM_IME_CONTROL */
#define IMC_GETCONVERSIONMODE 0x0001
#define IMC_GETSENTENCEMODE 0x0003
#define IMC_GETOPENSTATUS 0x0005
+#define IMC_GETSOFTKBDFONT 0x0011
+#define IMC_SETSOFTKBDFONT 0x0012
#define IMC_GETSOFTKBDPOS 0x0013
#define IMC_SETSOFTKBDPOS 0x0014
+#define IMC_GETSOFTKBDSUBTYPE 0x0015
+#define IMC_SETSOFTKBDSUBTYPE 0x0016
+#define IMC_SETSOFTKBDDATA 0x0018
/* wParam for WM_IME_SYSTEM */
#define IMS_NOTIFYIMESHOW 0x05
@@ -46,6 +57,9 @@ extern "C" {
#define IMS_SETLANGBAND 0x23
#define IMS_UNSETLANGBAND 0x24
+/* wParam for WM_IME_NOTIFY */
+#define IMN_SOFTKBDDESTROYED 0x0011
+
#define IMMGWL_IMC 0
#define IMMGWL_PRIVATE (sizeof(LONG))
@@ -59,7 +73,7 @@ typedef struct _tagINPUTCONTEXT {
POINT ptSoftKbdPos;
DWORD fdwConversion;
DWORD fdwSentence;
- union {
+ union {
LOGFONTA A;
LOGFONTW W;
} lfFont;