mirror of https://github.com/tongzx/nt5src
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.
1334 lines
48 KiB
1334 lines
48 KiB
/******************************************************************************
|
|
*
|
|
* File Name: imeui.c
|
|
*
|
|
* - User Interface routines.
|
|
*
|
|
* Author: Beomseok Oh (BeomOh)
|
|
*
|
|
* Copyright (C) Microsoft Corp 1993-1995. All rights reserved.
|
|
*
|
|
******************************************************************************/
|
|
|
|
// include files
|
|
#include "precomp.h"
|
|
|
|
// local definitions
|
|
#define UIGWL_FLAGS 0
|
|
#define UIF_WNDMOVE 0x00000001UL
|
|
#define UIF_HANPRESS 0x00000002UL
|
|
#define UIF_JUNPRESS 0x00000004UL
|
|
#define UIF_CHIPRESS 0x00000008UL
|
|
#define UIF_MOUSEIN 0x00000010UL
|
|
#define UIF_SHOWSTATUS 0x00000020UL
|
|
#define UIF_PRIVATEPOS 0x00000040UL
|
|
|
|
extern BOOL fWndOpen[3];
|
|
extern WORD wWndCmd[3];
|
|
|
|
// public data
|
|
#pragma data_seg(".text", "CODE")
|
|
const TCHAR szUIClassName[] = TEXT("MSIME95K");
|
|
const TCHAR szStateWndName[] = TEXT("IMESTATE");
|
|
const TCHAR szCompWndName[] = TEXT("IMECOMP");
|
|
const TCHAR szCandWndName[] = TEXT("IMECAND");
|
|
const static RECT rcHan = { 4, 2, 21, 19 }, rcJun = { 24, 2, 41, 19 },
|
|
rcChi = { 44, 2, 61, 19 };
|
|
|
|
const static RECT rcCandCli = { 0, 0, 319, 29 },
|
|
rcLArrow = { 15, 4, 27, 25 }, rcRArrow = { 292, 4, 304, 25 },
|
|
rcBtn[9] = { { 30, 4, 57, 25 }, { 59, 4, 86, 25 },
|
|
{ 88, 4, 115, 25 }, { 117, 4, 144, 25 },
|
|
{ 146, 4, 173, 25 }, { 175, 4, 202, 25 },
|
|
{ 204, 4, 231, 25 }, { 233, 4, 260, 25 },
|
|
{ 262, 4, 289, 25 } };
|
|
#pragma data_seg()
|
|
|
|
HBITMAP hBMClient, hBMComp, hBMCand, hBMCandNum, hBMCandArr[2];
|
|
HBITMAP hBMEng, hBMHan, hBMBan, hBMJun, hBMChi[2];
|
|
HCURSOR hIMECursor;
|
|
HFONT hFontFix = NULL;
|
|
#pragma data_seg("SHAREDDATA")
|
|
RECT rcScreen = { 0, 0, 0, 0 };
|
|
RECT rcOldScrn = { 0, 0, 0, 0 };
|
|
POINT ptDefPos[3] = { { -1, -1 }, { -1, -1 }, { -1, -1 } };
|
|
POINT ptState = { -1, -1 };
|
|
POINT ptComp = { -1, -1 };
|
|
POINT ptCand = { -1, -1 };
|
|
DWORD dwScreenRes = 0;
|
|
#pragma data_seg()
|
|
|
|
static POINT ptPos;
|
|
static RECT rc;
|
|
|
|
|
|
void UpdateUIPosition(void)
|
|
{
|
|
HKEY hKey;
|
|
DWORD dwBuf, dwCb;
|
|
|
|
SystemParametersInfo(SPI_GETWORKAREA, sizeof(rcScreen), &rcScreen, FALSE);
|
|
if (!EqualRect(&rcOldScrn, &rcScreen))
|
|
{
|
|
ptDefPos[STATE_WINDOW].x = rcScreen.right - STATEXSIZE - GetSystemMetrics(SM_CXBORDER)
|
|
- GetSystemMetrics(SM_CXVSCROLL) - GetSystemMetrics(SM_CXHSCROLL);
|
|
ptDefPos[STATE_WINDOW].y = rcScreen.bottom - STATEYSIZE;
|
|
ptDefPos[COMP_WINDOW].x = ptDefPos[STATE_WINDOW].x + STATEXSIZE + GAPX;
|
|
ptDefPos[COMP_WINDOW].y = ptDefPos[STATE_WINDOW].y + GAPY;
|
|
ptDefPos[CAND_WINDOW].x = rcScreen.right - CANDXSIZE;
|
|
ptDefPos[CAND_WINDOW].y = rcScreen.bottom - CANDYSIZE;
|
|
if (ptState.x == -1 && ptState.y == -1)
|
|
{
|
|
if (RegOpenKey(HKEY_CURRENT_USER, szIMEKey, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
dwCb = sizeof(dwBuf);
|
|
if (RegQueryValueEx(hKey, szStatePos, NULL, NULL, (LPBYTE)&dwBuf, &dwCb)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
ptState.x = HIWORD(dwBuf);
|
|
ptState.y = LOWORD(dwBuf);
|
|
wWndCmd[STATE_WINDOW] = wWndCmd[COMP_WINDOW] = 0x04; // MCW_SCREEN
|
|
}
|
|
else
|
|
ptState = ptDefPos[STATE_WINDOW];
|
|
dwCb = sizeof(dwBuf);
|
|
if (RegQueryValueEx(hKey, szCandPos, NULL, NULL, (LPBYTE)&dwBuf, &dwCb)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
ptCand.x = HIWORD(dwBuf);
|
|
ptCand.y = LOWORD(dwBuf);
|
|
}
|
|
else
|
|
ptCand = ptDefPos[CAND_WINDOW];
|
|
RegCloseKey(hKey);
|
|
}
|
|
else
|
|
{
|
|
ptState = ptDefPos[STATE_WINDOW];
|
|
ptCand = ptDefPos[CAND_WINDOW];
|
|
}
|
|
dwScreenRes = MAKELONG(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
|
|
}
|
|
else
|
|
{
|
|
ptState.x += rcScreen.left - rcOldScrn.left;
|
|
ptState.y += rcScreen.top - rcOldScrn.top;
|
|
ptComp.x += rcScreen.left - rcOldScrn.left;
|
|
ptComp.y += rcScreen.top - rcOldScrn.top;
|
|
ptCand.x += rcScreen.left - rcOldScrn.left;
|
|
ptCand.y += rcScreen.top - rcOldScrn.top;
|
|
}
|
|
if (ptState.x < rcScreen.left)
|
|
ptState.x = rcScreen.left;
|
|
else if (ptState.x > rcScreen.right - STATEXSIZE)
|
|
ptState.x = rcScreen.right - STATEXSIZE;
|
|
if (ptState.y < rcScreen.top)
|
|
ptState.y = rcScreen.top;
|
|
else if (ptState.y > rcScreen.bottom - STATEYSIZE)
|
|
ptState.y = rcScreen.bottom - STATEYSIZE;
|
|
ptComp.x = (ptState.x + STATEXSIZE + GAPX + COMPSIZE > rcScreen.right)?
|
|
ptState.x - GAPX - COMPSIZE: ptState.x + STATEXSIZE + GAPX;
|
|
ptComp.y = ptState.y + GAPY;
|
|
if (ptCand.x < rcScreen.left)
|
|
ptCand.x = rcScreen.left;
|
|
else if (ptCand.x > rcScreen.right - CANDXSIZE)
|
|
ptCand.x = rcScreen.right - CANDXSIZE;
|
|
if (ptCand.y < rcScreen.top)
|
|
ptCand.y = rcScreen.top;
|
|
else if (ptCand.y > rcScreen.bottom - CANDYSIZE)
|
|
ptCand.y = rcScreen.bottom - CANDYSIZE;
|
|
rcOldScrn = rcScreen;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL InitializeResource(HANDLE hInstance)
|
|
{
|
|
hBMClient = MyCreateMappedBitmap(hInst, TEXT("Client"));
|
|
hBMEng = MyCreateMappedBitmap(hInst, TEXT("English"));
|
|
hBMHan = MyCreateMappedBitmap(hInst, TEXT("Hangeul"));
|
|
hBMBan = MyCreateMappedBitmap(hInst, TEXT("Banja"));
|
|
hBMJun = MyCreateMappedBitmap(hInst, TEXT("Junja"));
|
|
hBMChi[0] = MyCreateMappedBitmap(hInst, TEXT("ChineseOff"));
|
|
hBMChi[1] = MyCreateMappedBitmap(hInst, TEXT("ChineseOn"));
|
|
hBMComp = MyCreateMappedBitmap(hInst, TEXT("Composition"));
|
|
hBMCand = MyCreateMappedBitmap(hInst, TEXT("Candidate"));
|
|
hBMCandNum = MyCreateMappedBitmap(hInst, TEXT("CandNumber"));
|
|
hBMCandArr[0] = MyCreateMappedBitmap(hInst, TEXT("CandArrow1"));
|
|
hBMCandArr[1] = MyCreateMappedBitmap(hInst, TEXT("CandArrow2"));
|
|
hIMECursor = LoadCursor(hInstance, TEXT("MyHand"));
|
|
#ifdef JOHAB_IME
|
|
hFontFix = CreateFont(-16,0,0,0,0,0,0,0,130,OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH,TEXT("±¼¸²"));
|
|
#else
|
|
hFontFix = CreateFont(-16,0,0,0,0,0,0,0,129,OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH,TEXT("±¼¸²"));
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL RegisterUIClass(HANDLE hInstance)
|
|
{
|
|
BOOL fRet = TRUE;
|
|
WNDCLASSEX wc;
|
|
|
|
wc.cbSize = sizeof(WNDCLASSEX);
|
|
wc.style = CS_VREDRAW | CS_HREDRAW | CS_IME;
|
|
wc.cbClsExtra = 0;
|
|
wc.hInstance = hInstance;
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hIcon = NULL;
|
|
wc.hIconSm = NULL;
|
|
wc.lpszMenuName = (LPTSTR)NULL;
|
|
wc.hbrBackground = NULL;
|
|
|
|
wc.cbWndExtra = 8;
|
|
wc.lpfnWndProc = UIWndProc;
|
|
wc.lpszClassName = (LPTSTR)szUIClassName;
|
|
if (!RegisterClassEx((LPWNDCLASSEX)&wc))
|
|
{
|
|
MyDebugOut(MDB_LOG, "RegisterClassEx() Failed for UIWindow.");
|
|
fRet = FALSE;
|
|
}
|
|
wc.style = CS_VREDRAW | CS_HREDRAW | CS_IME;
|
|
wc.cbWndExtra = 4;
|
|
wc.lpfnWndProc = StateWndProc;
|
|
wc.lpszClassName = (LPTSTR)szStateWndName;
|
|
if (!RegisterClassEx((LPWNDCLASSEX)&wc))
|
|
{
|
|
MyDebugOut(MDB_LOG, "RegisterClassEx() Failed for StateWindow.");
|
|
fRet = FALSE;
|
|
}
|
|
wc.lpfnWndProc = CompWndProc;
|
|
wc.lpszClassName = (LPTSTR)szCompWndName;
|
|
if (!RegisterClassEx((LPWNDCLASSEX)&wc))
|
|
{
|
|
MyDebugOut(MDB_LOG, "RegisterClassEx() Failed for CompWindow.");
|
|
fRet = FALSE;
|
|
}
|
|
wc.lpfnWndProc = CandWndProc;
|
|
wc.lpszClassName = (LPTSTR)szCandWndName;
|
|
if (!RegisterClassEx((LPWNDCLASSEX)&wc))
|
|
{
|
|
MyDebugOut(MDB_LOG, "RegisterClassEx() Failed for CandWindow.");
|
|
fRet = FALSE;
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL UnregisterUIClass(HANDLE hInstance)
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
if (!UnregisterClass(szUIClassName, hInstance))
|
|
{
|
|
MyDebugOut(MDB_LOG, "UnregisterClass() Failed for UIWindow.");
|
|
fRet = FALSE;
|
|
}
|
|
if (!UnregisterClass(szStateWndName, hInstance))
|
|
{
|
|
MyDebugOut(MDB_LOG, "UnregisterClass() Failed for StateWindow.");
|
|
fRet = FALSE;
|
|
}
|
|
if (!UnregisterClass(szCompWndName, hInstance))
|
|
{
|
|
MyDebugOut(MDB_LOG, "UnregisterClass() Failed for CompWindow.");
|
|
fRet = FALSE;
|
|
}
|
|
if (!UnregisterClass(szCandWndName, hInstance))
|
|
{
|
|
MyDebugOut(MDB_LOG, "UnregisterClass() Failed for CandWindow.");
|
|
fRet = FALSE;
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
void DrawBitmap(HDC hDC, long xStart, long yStart, HBITMAP hBitmap)
|
|
{
|
|
HDC hMemDC;
|
|
HBITMAP hBMOld;
|
|
BITMAP bm;
|
|
POINT pt;
|
|
|
|
hMemDC = CreateCompatibleDC(hDC);
|
|
hBMOld = SelectObject(hMemDC, hBitmap);
|
|
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
|
|
pt.x = bm.bmWidth;
|
|
pt.y = bm.bmHeight;
|
|
BitBlt(hDC, xStart, yStart, pt.x, pt.y, hMemDC, 0, 0, SRCCOPY);
|
|
SelectObject(hMemDC, hBMOld);
|
|
DeleteDC(hMemDC);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void ShowWindowBorder(RECT rc)
|
|
{
|
|
HDC hDC;
|
|
HBRUSH hBrOld;
|
|
int cxBorder, cyBorder;
|
|
|
|
hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
|
|
hBrOld = SelectObject(hDC, GetStockObject(GRAY_BRUSH));
|
|
cxBorder = GetSystemMetrics(SM_CXBORDER);
|
|
cyBorder = GetSystemMetrics(SM_CYBORDER);
|
|
PatBlt(hDC, rc.left, rc.top, rc.right-rc.left-cxBorder, cyBorder, PATINVERT);
|
|
PatBlt(hDC, rc.right-cxBorder, rc.top, cxBorder, rc.bottom-rc.top-cyBorder, PATINVERT);
|
|
PatBlt(hDC, rc.right, rc.bottom-cyBorder, -(rc.right-rc.left-cxBorder), cyBorder, PATINVERT);
|
|
PatBlt(hDC, rc.left, rc.bottom, cxBorder, -(rc.bottom-rc.top-cyBorder), PATINVERT);
|
|
SelectObject(hDC, hBrOld);
|
|
DeleteDC(hDC);
|
|
|
|
return;
|
|
}
|
|
|
|
void ShowHideUIWnd(HIMC hIMC, LPUIINSTANCE lpUIInst, BOOL fShow, LPARAM lParam)
|
|
{
|
|
LPINPUTCONTEXT lpIMC;
|
|
LPCOMPOSITIONSTRING lpCompStr;
|
|
DWORD fdwUIFlags;
|
|
|
|
if (fShow && hIMC && (lpIMC = ImmLockIMC(hIMC)))
|
|
{
|
|
UpdateUIPosition();
|
|
fdwUIFlags = (DWORD)GetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS);
|
|
if (!(fdwUIFlags & UIF_PRIVATEPOS))
|
|
lpIMC->ptStatusWndPos = ptState;
|
|
MoveWindow(lpUIInst->rghWnd[STATE_WINDOW], lpIMC->ptStatusWndPos.x,
|
|
lpIMC->ptStatusWndPos.y, STATEXSIZE, STATEYSIZE, TRUE);
|
|
if (lpIMC->cfCompForm.dwStyle == CFS_DEFAULT)
|
|
{
|
|
MoveWindow(lpUIInst->rghWnd[COMP_WINDOW], ptComp.x, ptComp.y, COMPSIZE, COMPSIZE, TRUE);
|
|
}
|
|
if (fWndOpen[STATE_WINDOW] != FALSE && (fdwUIFlags & UIF_SHOWSTATUS))
|
|
ShowWindow(lpUIInst->rghWnd[STATE_WINDOW], SW_SHOWNOACTIVATE);
|
|
else
|
|
ShowWindow(lpUIInst->rghWnd[STATE_WINDOW], SW_HIDE);
|
|
lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
|
|
if (lpCompStr && lpCompStr->dwCompStrLen
|
|
&& fWndOpen[COMP_WINDOW] && (lParam & ISC_SHOWUICOMPOSITIONWINDOW))
|
|
ShowWindow(lpUIInst->rghWnd[COMP_WINDOW], SW_SHOWNOACTIVATE);
|
|
else
|
|
ShowWindow(lpUIInst->rghWnd[COMP_WINDOW], SW_HIDE);
|
|
if (lpIMC->fdwConversion & IME_CMODE_HANJACONVERT
|
|
&& fWndOpen[CAND_WINDOW] && (lParam & ISC_SHOWUICANDIDATEWINDOW))
|
|
ShowWindow(lpUIInst->rghWnd[CAND_WINDOW], SW_SHOWNOACTIVATE);
|
|
else
|
|
ShowWindow(lpUIInst->rghWnd[CAND_WINDOW], SW_HIDE);
|
|
ImmUnlockIMCC(lpIMC->hCompStr);
|
|
ImmUnlockIMC(hIMC);
|
|
}
|
|
else
|
|
{
|
|
ShowWindow(lpUIInst->rghWnd[STATE_WINDOW], SW_HIDE);
|
|
ShowWindow(lpUIInst->rghWnd[COMP_WINDOW], SW_HIDE);
|
|
ShowWindow(lpUIInst->rghWnd[CAND_WINDOW], SW_HIDE);
|
|
}
|
|
}
|
|
|
|
|
|
LRESULT CALLBACK UIWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HGLOBAL hUIInst;
|
|
LPUIINSTANCE lpUIInst;
|
|
|
|
switch (uMessage)
|
|
{
|
|
case WM_CREATE:
|
|
hUIInst = GlobalAlloc(GHND, sizeof(UIINSTANCE));
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
lpUIInst->rghWnd[STATE_WINDOW] = CreateWindow(szStateWndName, TEXT("\0"),
|
|
WS_DISABLED | WS_POPUP, ptState.x, ptState.y,
|
|
STATEXSIZE, STATEYSIZE, hWnd, NULL, hInst, NULL);
|
|
lpUIInst->rghWnd[COMP_WINDOW] = CreateWindow(szCompWndName, TEXT("\0"),
|
|
WS_DISABLED | WS_POPUP, ptComp.x, ptComp.y,
|
|
COMPSIZE, COMPSIZE, hWnd, NULL, hInst, NULL );
|
|
lpUIInst->rghWnd[CAND_WINDOW] = CreateWindow(szCandWndName, TEXT("\0"),
|
|
WS_DISABLED | WS_POPUP, ptCand.x, ptCand.y,
|
|
CANDXSIZE, CANDYSIZE, hWnd, NULL, hInst, NULL );
|
|
GlobalUnlock(hUIInst);
|
|
SetWindowLongPtr(hWnd, IMMGWL_PRIVATE, (LONG_PTR)hUIInst);
|
|
return 0;
|
|
|
|
case WM_DESTROY:
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
DestroyWindow(lpUIInst->rghWnd[STATE_WINDOW]);
|
|
DestroyWindow(lpUIInst->rghWnd[COMP_WINDOW]);
|
|
DestroyWindow(lpUIInst->rghWnd[CAND_WINDOW]);
|
|
GlobalUnlock(hUIInst);
|
|
GlobalFree(hUIInst);
|
|
SetWindowLongPtr(hWnd, IMMGWL_PRIVATE, (LONG_PTR)0);
|
|
return 0;
|
|
|
|
case WM_IME_SELECT:
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
ShowHideUIWnd(GetWindowLongPtr(hWnd, IMMGWL_IMC), lpUIInst, wParam, ISC_SHOWUIALL);
|
|
GlobalUnlock(hUIInst);
|
|
return 0;
|
|
|
|
case WM_IME_COMPOSITION:
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
InvalidateRect(lpUIInst->rghWnd[COMP_WINDOW], NULL, TRUE);
|
|
GlobalUnlock(hUIInst);
|
|
return 0;
|
|
|
|
case WM_IME_CONTROL:
|
|
return (LRESULT)DoIMEControl(hWnd, wParam, lParam);
|
|
|
|
case WM_IME_NOTIFY:
|
|
return (LRESULT)DoIMENotify(hWnd, wParam, lParam);
|
|
|
|
case WM_IME_SETCONTEXT:
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
ShowHideUIWnd(GetWindowLongPtr(hWnd, IMMGWL_IMC), lpUIInst, wParam, lParam);
|
|
GlobalUnlock(hUIInst);
|
|
return 0;
|
|
|
|
case WM_IME_STARTCOMPOSITION:
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
ShowWindow(lpUIInst->rghWnd[COMP_WINDOW], fWndOpen[COMP_WINDOW]? SW_SHOWNOACTIVATE: SW_HIDE);
|
|
GlobalUnlock(hUIInst);
|
|
return 0;
|
|
|
|
case WM_IME_ENDCOMPOSITION:
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
ShowWindow(lpUIInst->rghWnd[COMP_WINDOW], SW_HIDE);
|
|
GlobalUnlock(hUIInst);
|
|
return 0;
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
GetSysColorsAndMappedBitmap();
|
|
return 0;
|
|
|
|
case WM_DISPLAYCHANGE:
|
|
if (dwScreenRes != (DWORD)lParam)
|
|
{
|
|
ptState.x += LOWORD(lParam) - LOWORD(dwScreenRes);
|
|
ptState.y += HIWORD(lParam) - HIWORD(dwScreenRes);
|
|
ptComp.x += LOWORD(lParam) - LOWORD(dwScreenRes);
|
|
ptComp.y += HIWORD(lParam) - HIWORD(dwScreenRes);
|
|
ptCand.x += LOWORD(lParam) - LOWORD(dwScreenRes);
|
|
ptCand.y += HIWORD(lParam) - HIWORD(dwScreenRes);
|
|
dwScreenRes = MAKELONG(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
|
|
}
|
|
return 0;
|
|
}
|
|
return DefWindowProc(hWnd, uMessage, wParam, lParam);
|
|
}
|
|
|
|
|
|
LRESULT CALLBACK StateWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMessage)
|
|
{
|
|
HANDLE_DUMMYMSG(WM_IME_CHAR);
|
|
HANDLE_DUMMYMSG(WM_IME_COMPOSITIONFULL);
|
|
HANDLE_DUMMYMSG(WM_IME_COMPOSITION);
|
|
HANDLE_DUMMYMSG(WM_IME_CONTROL);
|
|
HANDLE_DUMMYMSG(WM_IME_NOTIFY);
|
|
HANDLE_DUMMYMSG(WM_IME_SELECT);
|
|
HANDLE_DUMMYMSG(WM_IME_SETCONTEXT);
|
|
HANDLE_DUMMYMSG(WM_IME_STARTCOMPOSITION);
|
|
HANDLE_DUMMYMSG(WM_IME_ENDCOMPOSITION);
|
|
HANDLE_MSG(hWnd, WM_SETCURSOR, State_OnSetCursor);
|
|
HANDLE_MSG(hWnd, WM_MOUSEMOVE, State_OnMouseMove);
|
|
HANDLE_MSG(hWnd, WM_LBUTTONUP, State_OnLButtonUp);
|
|
HANDLE_MSG(hWnd, WM_PAINT, State_OnPaint);
|
|
HANDLE_MSG(hWnd, WM_COMMAND, State_OnCommand);
|
|
}
|
|
return DefWindowProc(hWnd, uMessage, wParam, lParam);
|
|
}
|
|
|
|
|
|
BOOL State_OnSetCursor(HWND hWnd, HWND hWndCursor, UINT codeHitTest, UINT msg)
|
|
{
|
|
HWND hWndUI;
|
|
HIMC hIMC;
|
|
DWORD fdwUIFlags;
|
|
|
|
SetCursor(hIMECursor);
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_LBUTTONDOWN:
|
|
GetCursorPos(&ptPos);
|
|
ScreenToClient(hWnd, &ptPos);
|
|
fdwUIFlags = (DWORD)GetWindowLong(hWnd, UIGWL_FLAGS);
|
|
if (PtInRect((LPRECT)&rcHan, ptPos))
|
|
{
|
|
fdwUIFlags |= UIF_HANPRESS;
|
|
}
|
|
else if (PtInRect((LPRECT)&rcJun, ptPos))
|
|
{
|
|
fdwUIFlags |= UIF_JUNPRESS;
|
|
}
|
|
else if (PtInRect((LPRECT)&rcChi, ptPos))
|
|
{
|
|
fdwUIFlags |= UIF_CHIPRESS;
|
|
}
|
|
else
|
|
{
|
|
fdwUIFlags |= UIF_WNDMOVE;
|
|
GetWindowRect(hWnd, &rc);
|
|
ShowWindowBorder(rc);
|
|
SetCapture(hWnd);
|
|
}
|
|
SetWindowLong(hWnd, UIGWL_FLAGS, fdwUIFlags);
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
GetCursorPos(&ptPos);
|
|
ScreenToClient(hWnd, &ptPos);
|
|
fdwUIFlags = (DWORD)GetWindowLong( hWnd, UIGWL_FLAGS );
|
|
if ((fdwUIFlags & UIF_HANPRESS) && PtInRect((LPRECT)&rcHan, ptPos))
|
|
{
|
|
fdwUIFlags &= ~UIF_HANPRESS;
|
|
keybd_event(VK_HANGEUL, 0, 0, 0);
|
|
keybd_event(VK_HANGEUL, 0, KEYEVENTF_KEYUP, 0);
|
|
}
|
|
else if ((fdwUIFlags & UIF_JUNPRESS) && PtInRect((LPRECT)&rcJun, ptPos))
|
|
{
|
|
fdwUIFlags &= ~UIF_JUNPRESS;
|
|
keybd_event(VK_JUNJA, 0, 0, 0);
|
|
keybd_event(VK_JUNJA, 0, KEYEVENTF_KEYUP, 0);
|
|
}
|
|
else if ((fdwUIFlags & UIF_CHIPRESS) && PtInRect((LPRECT)&rcChi, ptPos))
|
|
{
|
|
fdwUIFlags &= ~UIF_CHIPRESS;
|
|
keybd_event(VK_HANJA, 0, 0, 0);
|
|
keybd_event(VK_HANJA, 0, KEYEVENTF_KEYUP, 0);
|
|
}
|
|
else
|
|
fdwUIFlags &= ~(UIF_HANPRESS | UIF_JUNPRESS | UIF_CHIPRESS);
|
|
SetWindowLong(hWnd, UIGWL_FLAGS, fdwUIFlags);
|
|
break;
|
|
|
|
case WM_RBUTTONDOWN:
|
|
hWndUI = GetWindow(hWnd, GW_OWNER);
|
|
hIMC = (HIMC)GetWindowLongPtr(hWndUI, IMMGWL_IMC);
|
|
if (bState) MakeFinalMsgBuf(hIMC, 0);
|
|
break;
|
|
|
|
case WM_RBUTTONUP:
|
|
State_OnMyMenu(hWnd);
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void State_OnMouseMove(HWND hWnd, int x, int y, UINT keyFlags)
|
|
{
|
|
DWORD fdwUIFlags;
|
|
|
|
fdwUIFlags = (DWORD)GetWindowLong(hWnd, UIGWL_FLAGS);
|
|
if (fdwUIFlags & UIF_WNDMOVE)
|
|
{
|
|
ShowWindowBorder(rc);
|
|
rc.left += x - ptPos.x;
|
|
rc.top += y - ptPos.y;
|
|
rc.right += x - ptPos.x;
|
|
rc.bottom += y - ptPos.y;
|
|
ShowWindowBorder(rc);
|
|
ptPos.x = x;
|
|
ptPos.y = y;
|
|
}
|
|
return;
|
|
|
|
UNREFERENCED_PARAMETER(keyFlags);
|
|
}
|
|
|
|
|
|
void State_OnLButtonUp(HWND hWnd, int x, int y, UINT keyFlags)
|
|
{
|
|
HKEY hKey;
|
|
DWORD fdwUIFlags, dwBuf, dwCb;
|
|
HGLOBAL hUIInst;
|
|
LPUIINSTANCE lpUIInst;
|
|
HWND hWndUI;
|
|
HIMC hIMC;
|
|
LPINPUTCONTEXT lpIMC;
|
|
|
|
ReleaseCapture();
|
|
fdwUIFlags = (DWORD)GetWindowLong(hWnd, UIGWL_FLAGS);
|
|
if (fdwUIFlags & UIF_WNDMOVE)
|
|
{
|
|
ShowWindowBorder(rc);
|
|
MoveWindow(hWnd, rc.left, rc.top, STATEXSIZE, STATEYSIZE, TRUE);
|
|
ptState.x = rc.left;
|
|
ptState.y = rc.top;
|
|
if (RegCreateKey(HKEY_CURRENT_USER, szIMEKey, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
dwCb = sizeof(dwBuf);
|
|
dwBuf = (ptState.x << 16) | (ptState.y & 0x0FFFF); // HIWORD : X, LOWORD : Y
|
|
RegSetValueEx(hKey, szStatePos, 0, REG_DWORD, (LPBYTE)&dwBuf, dwCb);
|
|
RegCloseKey(hKey);
|
|
}
|
|
ptComp.x = (ptState.x + STATEXSIZE + GAPX + COMPSIZE > rcScreen.right)?
|
|
ptState.x - GAPX - COMPSIZE: ptState.x + STATEXSIZE + GAPX;
|
|
ptComp.y = ptState.y + GAPY;
|
|
|
|
hWndUI = GetWindow(hWnd, GW_OWNER);
|
|
hIMC = (HIMC)GetWindowLongPtr(hWndUI, IMMGWL_IMC);
|
|
lpIMC = ImmLockIMC(hIMC);
|
|
if (lpIMC != NULL) {
|
|
lpIMC->ptStatusWndPos = ptState;
|
|
if (lpIMC->cfCompForm.dwStyle == CFS_DEFAULT)
|
|
{
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(GetWindow(hWnd, GW_OWNER), IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
MoveWindow(lpUIInst->rghWnd[COMP_WINDOW], ptComp.x, ptComp.y, COMPSIZE, COMPSIZE, TRUE);
|
|
GlobalUnlock(hUIInst);
|
|
lpIMC->cfCompForm.ptCurrentPos = ptComp;
|
|
}
|
|
ImmUnlockIMC(hIMC);
|
|
}
|
|
wWndCmd[STATE_WINDOW] = wWndCmd[COMP_WINDOW] = 0x04; // MCW_SCREEN
|
|
fdwUIFlags &= ~UIF_WNDMOVE;
|
|
}
|
|
SetWindowLong(hWnd, UIGWL_FLAGS, fdwUIFlags);
|
|
|
|
return;
|
|
|
|
UNREFERENCED_PARAMETER(x);
|
|
UNREFERENCED_PARAMETER(y);
|
|
UNREFERENCED_PARAMETER(keyFlags);
|
|
}
|
|
|
|
|
|
typedef struct tagCOLORMAP
|
|
{
|
|
COLORREF bgrfrom;
|
|
COLORREF bgrto;
|
|
COLORREF sysColor;
|
|
} COLORMAP;
|
|
|
|
// these are the default colors used to map the dib colors
|
|
// to the current system colors
|
|
|
|
#define BGR_BUTTONTEXT (RGB(000,000,000)) // black
|
|
#define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey
|
|
#define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey
|
|
#define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white
|
|
#define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue
|
|
#define BGR_BACKGROUND (RGB(255,000,255)) // magenta
|
|
#define FlipColor(rgb) (RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb)))
|
|
|
|
HBITMAP MyCreateMappedBitmap(HINSTANCE hInstance, LPTSTR lpszBitmap)
|
|
{
|
|
HDC hdc, hdcMem = NULL;
|
|
HANDLE h;
|
|
LPDWORD p;
|
|
LPSTR lpBits;
|
|
HANDLE hRes;
|
|
LPBITMAPINFOHEADER lpBitmapInfo, lpTmpBMInfo;
|
|
HBITMAP hbm = NULL, hbmOld;
|
|
int numcolors, i, wid, hgt;
|
|
static COLORMAP ColorMap[] =
|
|
{
|
|
{BGR_BUTTONTEXT, BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black
|
|
{BGR_BUTTONSHADOW, BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey
|
|
{BGR_BUTTONFACE, BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey
|
|
{BGR_BUTTONHILIGHT, BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white
|
|
{BGR_BACKGROUNDSEL, BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue
|
|
{BGR_BACKGROUND, BGR_BACKGROUND, COLOR_WINDOW} // magenta
|
|
};
|
|
|
|
#define NUM_MAPS (sizeof(ColorMap)/sizeof(COLORMAP))
|
|
|
|
h = FindResource(hInstance, lpszBitmap, RT_BITMAP);
|
|
if (!h)
|
|
return NULL;
|
|
|
|
hRes = LoadResource(hInstance, h);
|
|
|
|
/* Lock the bitmap and get a pointer to the color table. */
|
|
lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource(hRes);
|
|
if (!lpBitmapInfo)
|
|
return NULL;
|
|
|
|
// HACK: We need to use temp copy of BITMAPINFO because original info is destroyed
|
|
// after change color. It cause next time LoadResource result has wrong info.
|
|
i = sizeof(BITMAPINFOHEADER) + 16*sizeof(RGBQUAD);
|
|
lpTmpBMInfo = (LPBITMAPINFOHEADER) LocalAlloc(LPTR, i);
|
|
if (!lpTmpBMInfo) {
|
|
UnlockResource(hRes);
|
|
FreeResource(hRes);
|
|
return NULL;
|
|
}
|
|
CopyMemory(lpTmpBMInfo, lpBitmapInfo, i);
|
|
|
|
//
|
|
// So what are the new colors anyway ?
|
|
//
|
|
for (i=0; i < NUM_MAPS; i++)
|
|
ColorMap[i].bgrto = FlipColor(GetSysColor((int)ColorMap[i].sysColor));
|
|
|
|
// HACK: ??? p = (LPDWORD)(((LPSTR)lpBitmapInfo) + lpBitmapInfo->biSize);
|
|
p = (LPDWORD)(((LPSTR)lpTmpBMInfo) + lpTmpBMInfo->biSize);
|
|
|
|
/* Replace button-face and button-shadow colors with the current values
|
|
*/
|
|
numcolors = 16;
|
|
|
|
while (numcolors-- > 0)
|
|
{
|
|
for (i = 0; i < NUM_MAPS; i++)
|
|
{
|
|
if (*p == ColorMap[i].bgrfrom)
|
|
{
|
|
*p = ColorMap[i].bgrto;
|
|
break;
|
|
}
|
|
}
|
|
p++;
|
|
}
|
|
|
|
/* First skip over the header structure */
|
|
lpBits = (LPSTR)(lpBitmapInfo + 1);
|
|
|
|
/* Skip the color table entries, if any */
|
|
lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
|
|
|
|
/* Create a color bitmap compatible with the display device */
|
|
i = wid = (int)lpBitmapInfo->biWidth;
|
|
hgt = (int)lpBitmapInfo->biHeight;
|
|
hdc = GetDC(NULL);
|
|
|
|
hdcMem = CreateCompatibleDC(hdc);
|
|
if (hdcMem)
|
|
{
|
|
hbm = CreateDiscardableBitmap(hdc, i, hgt);
|
|
if (hbm)
|
|
{
|
|
hbmOld = SelectObject(hdcMem, hbm);
|
|
// set the main image
|
|
StretchDIBits(hdcMem, 0, 0, wid, hgt, 0, 0, wid, hgt, lpBits,
|
|
(LPBITMAPINFO)lpTmpBMInfo, DIB_RGB_COLORS, SRCCOPY);
|
|
SelectObject(hdcMem, hbmOld);
|
|
}
|
|
DeleteObject(hdcMem);
|
|
}
|
|
ReleaseDC(NULL, hdc);
|
|
UnlockResource(hRes);
|
|
FreeResource(hRes);
|
|
// HACK: Remove hack temp BITMAPINFO.
|
|
LocalFree(lpTmpBMInfo);
|
|
|
|
return hbm;
|
|
}
|
|
|
|
|
|
void GetSysColorsAndMappedBitmap(void)
|
|
{
|
|
static DWORD rgbFace, rgbShadow, rgbHilight, rgbFrame;
|
|
static COLORREF rgbSaveFace = 0xFFFFFFFFL,
|
|
rgbSaveShadow = 0xFFFFFFFFL,
|
|
rgbSaveHilight = 0xFFFFFFFFL,
|
|
rgbSaveFrame = 0xFFFFFFFFL;
|
|
|
|
rgbFace = GetSysColor(COLOR_BTNFACE);
|
|
rgbShadow = GetSysColor(COLOR_BTNSHADOW);
|
|
rgbHilight = GetSysColor(COLOR_BTNHIGHLIGHT);
|
|
rgbFrame = GetSysColor(COLOR_WINDOWFRAME);
|
|
|
|
if (rgbSaveFace != rgbFace || rgbSaveShadow != rgbShadow
|
|
|| rgbSaveHilight != rgbHilight || rgbSaveFrame != rgbFrame)
|
|
{
|
|
rgbSaveFace = rgbFace;
|
|
rgbSaveShadow = rgbShadow;
|
|
rgbSaveHilight = rgbHilight;
|
|
rgbSaveFrame = rgbFrame;
|
|
|
|
DeleteObject(hBMClient);
|
|
DeleteObject(hBMEng);
|
|
DeleteObject(hBMHan);
|
|
DeleteObject(hBMBan);
|
|
DeleteObject(hBMJun);
|
|
DeleteObject(hBMChi[0]);
|
|
DeleteObject(hBMChi[1]);
|
|
DeleteObject(hBMComp);
|
|
DeleteObject(hBMCand);
|
|
DeleteObject(hBMCandNum);
|
|
DeleteObject(hBMCandArr[0]);
|
|
DeleteObject(hBMCandArr[1]);
|
|
|
|
hBMClient = MyCreateMappedBitmap(hInst, TEXT("Client"));
|
|
hBMEng = MyCreateMappedBitmap(hInst, TEXT("English"));
|
|
hBMHan = MyCreateMappedBitmap(hInst, TEXT("Hangeul"));
|
|
hBMBan = MyCreateMappedBitmap(hInst, TEXT("Banja"));
|
|
hBMJun = MyCreateMappedBitmap(hInst, TEXT("Junja"));
|
|
hBMChi[0] = MyCreateMappedBitmap(hInst, TEXT("ChineseOff"));
|
|
hBMChi[1] = MyCreateMappedBitmap(hInst, TEXT("ChineseOn"));
|
|
hBMComp = MyCreateMappedBitmap(hInst, TEXT("Composition"));
|
|
hBMCand = MyCreateMappedBitmap(hInst, TEXT("Candidate"));
|
|
hBMCandNum = MyCreateMappedBitmap(hInst, TEXT("CandNumber"));
|
|
hBMCandArr[0] = MyCreateMappedBitmap(hInst, TEXT("CandArrow1"));
|
|
hBMCandArr[1] = MyCreateMappedBitmap(hInst, TEXT("CandArrow2"));
|
|
}
|
|
}
|
|
|
|
|
|
void State_OnPaint(HWND hWnd)
|
|
{
|
|
HDC hDC;
|
|
HWND hWndUI;
|
|
HIMC hIMC;
|
|
LPINPUTCONTEXT lpIMC;
|
|
PAINTSTRUCT ps;
|
|
DWORD fdwUIFlags;
|
|
|
|
hDC = BeginPaint(hWnd, &ps);
|
|
hWndUI = GetWindow(hWnd, GW_OWNER);
|
|
hIMC = (HIMC)GetWindowLongPtr(hWndUI, IMMGWL_IMC);
|
|
if (hIMC && (lpIMC = ImmLockIMC(hIMC)))
|
|
{
|
|
fdwUIFlags = (DWORD)GetWindowLong(hWnd, UIGWL_FLAGS);
|
|
DrawBitmap(hDC, 0, 0, hBMClient);
|
|
DrawBitmap(hDC, rcHan.left, rcHan.top,
|
|
(lpIMC->fOpen && (lpIMC->fdwConversion & IME_CMODE_HANGEUL))? hBMHan: hBMEng);
|
|
DrawBitmap(hDC, rcJun.left, rcJun.top,
|
|
(lpIMC->fOpen && (lpIMC->fdwConversion & IME_CMODE_FULLSHAPE))? hBMJun: hBMBan);
|
|
DrawBitmap(hDC, rcChi.left, rcChi.top,
|
|
(lpIMC->fdwConversion & IME_CMODE_HANJACONVERT)? hBMChi[1]: hBMChi[0]);
|
|
ImmUnlockIMC(hIMC);
|
|
}
|
|
EndPaint(hWnd, &ps);
|
|
}
|
|
|
|
|
|
void State_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify)
|
|
{
|
|
switch (id)
|
|
{
|
|
case IDM_CONFIG:
|
|
State_OnMyConfig(hWnd);
|
|
break;
|
|
|
|
case IDM_ABOUT:
|
|
State_OnMyAbout(hWnd);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void State_OnMyMenu(HWND hWnd)
|
|
{
|
|
HMENU hMenu;
|
|
POINT ptCurrent;
|
|
TCHAR szBuffer[256];
|
|
|
|
GetCursorPos(&ptCurrent);
|
|
hMenu = CreatePopupMenu();
|
|
LoadString(hInst, IDS_CONFIG, szBuffer, sizeof(szBuffer));
|
|
AppendMenu(hMenu, MF_ENABLED, IDM_CONFIG, szBuffer);
|
|
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
|
|
LoadString(hInst, IDS_ABOUT, szBuffer, sizeof(szBuffer));
|
|
AppendMenu(hMenu, MF_ENABLED, IDM_ABOUT, szBuffer);
|
|
TrackPopupMenu(hMenu, TPM_LEFTALIGN, ptCurrent.x, ptCurrent.y, 0, hWnd, NULL);
|
|
DestroyMenu(hMenu);
|
|
}
|
|
|
|
|
|
void State_OnMyConfig(HWND hWnd)
|
|
{
|
|
HIMC hIMC;
|
|
LPINPUTCONTEXT lpIMC;
|
|
|
|
hIMC = (HIMC)GetWindowLongPtr(GetWindow(hWnd, GW_OWNER), IMMGWL_IMC);
|
|
if (lpIMC = ImmLockIMC(hIMC))
|
|
{
|
|
ImeConfigure(0, lpIMC->hWnd, IME_CONFIG_GENERAL, NULL);
|
|
ImmUnlockIMC(hIMC);
|
|
}
|
|
}
|
|
|
|
|
|
void State_OnMyAbout(HWND hWnd)
|
|
{
|
|
HIMC hIMC;
|
|
LPINPUTCONTEXT lpIMC;
|
|
TCHAR szBuffer[256];
|
|
|
|
hIMC = (HIMC)GetWindowLongPtr(GetWindow(hWnd, GW_OWNER), IMMGWL_IMC);
|
|
if (lpIMC = ImmLockIMC(hIMC))
|
|
{
|
|
LoadString(hInst, IDS_PROGRAM, szBuffer, sizeof(szBuffer));
|
|
ShellAbout(lpIMC->hWnd, szBuffer, NULL, LoadIcon(hInst, TEXT("IMEIcon")));
|
|
ImmUnlockIMC(hIMC);
|
|
}
|
|
}
|
|
|
|
|
|
LRESULT CALLBACK CompWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMessage)
|
|
{
|
|
HANDLE_DUMMYMSG(WM_IME_CHAR);
|
|
HANDLE_DUMMYMSG(WM_IME_COMPOSITIONFULL);
|
|
HANDLE_DUMMYMSG(WM_IME_COMPOSITION);
|
|
HANDLE_DUMMYMSG(WM_IME_CONTROL);
|
|
HANDLE_DUMMYMSG(WM_IME_NOTIFY);
|
|
HANDLE_DUMMYMSG(WM_IME_SELECT);
|
|
HANDLE_DUMMYMSG(WM_IME_SETCONTEXT);
|
|
HANDLE_DUMMYMSG(WM_IME_STARTCOMPOSITION);
|
|
HANDLE_DUMMYMSG(WM_IME_ENDCOMPOSITION);
|
|
HANDLE_MSG(hWnd, WM_PAINT, Comp_OnPaint);
|
|
}
|
|
return DefWindowProc(hWnd, uMessage, wParam, lParam);
|
|
}
|
|
|
|
|
|
void Comp_OnPaint(HWND hWnd)
|
|
{
|
|
HDC hDC;
|
|
HWND hWndUI;
|
|
HIMC hIMC;
|
|
LPINPUTCONTEXT lpIMC;
|
|
LPCOMPOSITIONSTRING lpUICompStr;
|
|
PAINTSTRUCT ps;
|
|
HFONT hOldFont;
|
|
int iSaveBkMode;
|
|
|
|
hDC = BeginPaint(hWnd, &ps);
|
|
hWndUI = GetWindow(hWnd, GW_OWNER);
|
|
hIMC = (HIMC)GetWindowLongPtr(hWndUI, IMMGWL_IMC);
|
|
lpIMC = ImmLockIMC(hIMC);
|
|
if (lpIMC) {
|
|
lpUICompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
|
|
if (lpUICompStr && lpUICompStr->dwCompStrLen)
|
|
{
|
|
DrawBitmap(hDC, 0, 0, hBMComp);
|
|
iSaveBkMode = SetBkMode(hDC, TRANSPARENT);
|
|
hOldFont = SelectObject(hDC, hFontFix);
|
|
TextOut(hDC, 3, 3, (LPTSTR)lpUICompStr + lpUICompStr->dwCompStrOffset, 2);
|
|
SelectObject(hDC, hOldFont);
|
|
SetBkMode(hDC, iSaveBkMode);
|
|
}
|
|
ImmUnlockIMCC(lpIMC->hCompStr);
|
|
ImmUnlockIMC(hIMC);
|
|
}
|
|
EndPaint(hWnd, &ps);
|
|
}
|
|
|
|
|
|
LRESULT CALLBACK CandWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMessage)
|
|
{
|
|
HANDLE_DUMMYMSG(WM_IME_CHAR);
|
|
HANDLE_DUMMYMSG(WM_IME_COMPOSITIONFULL);
|
|
HANDLE_DUMMYMSG(WM_IME_COMPOSITION);
|
|
HANDLE_DUMMYMSG(WM_IME_CONTROL);
|
|
HANDLE_DUMMYMSG(WM_IME_NOTIFY);
|
|
HANDLE_DUMMYMSG(WM_IME_SELECT);
|
|
HANDLE_DUMMYMSG(WM_IME_SETCONTEXT);
|
|
HANDLE_DUMMYMSG(WM_IME_STARTCOMPOSITION);
|
|
HANDLE_DUMMYMSG(WM_IME_ENDCOMPOSITION);
|
|
HANDLE_MSG(hWnd, WM_SETCURSOR, Cand_OnSetCursor);
|
|
HANDLE_MSG(hWnd, WM_PAINT, Cand_OnPaint);
|
|
}
|
|
return DefWindowProc(hWnd, uMessage, wParam, lParam);
|
|
}
|
|
|
|
|
|
BOOL Cand_OnSetCursor(HWND hWnd, HWND hWndCursor, UINT codeHitTest, UINT msg)
|
|
{
|
|
int iLoop;
|
|
|
|
SetCursor(hIMECursor);
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_LBUTTONDOWN:
|
|
GetCursorPos(&ptPos);
|
|
ScreenToClient(hWnd, &ptPos);
|
|
if (PtInRect((LPRECT)&rcCandCli, ptPos))
|
|
{
|
|
if (!PtInRect((LPRECT)&rcLArrow, ptPos)
|
|
&& !PtInRect((LPRECT)&rcRArrow, ptPos)
|
|
&& !PtInRect((LPRECT)&rcBtn[0], ptPos)
|
|
&& !PtInRect((LPRECT)&rcBtn[1], ptPos)
|
|
&& !PtInRect((LPRECT)&rcBtn[2], ptPos)
|
|
&& !PtInRect((LPRECT)&rcBtn[3], ptPos)
|
|
&& !PtInRect((LPRECT)&rcBtn[4], ptPos)
|
|
&& !PtInRect((LPRECT)&rcBtn[5], ptPos)
|
|
&& !PtInRect((LPRECT)&rcBtn[6], ptPos)
|
|
&& !PtInRect((LPRECT)&rcBtn[7], ptPos)
|
|
&& !PtInRect((LPRECT)&rcBtn[8], ptPos))
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
GetCursorPos(&ptPos);
|
|
ScreenToClient(hWnd, &ptPos);
|
|
if (PtInRect((LPRECT)&rcLArrow, ptPos))
|
|
{
|
|
keybd_event(VK_LEFT, 0, 0, 0);
|
|
keybd_event(VK_LEFT, 0, KEYEVENTF_KEYUP, 0);
|
|
}
|
|
else if (PtInRect((LPRECT)&rcRArrow, ptPos))
|
|
{
|
|
keybd_event(VK_RIGHT, 0, 0, 0);
|
|
keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0);
|
|
}
|
|
else
|
|
{
|
|
for (iLoop = 0; iLoop < 9; iLoop++)
|
|
if (PtInRect((LPRECT)&rcBtn[iLoop], ptPos))
|
|
{
|
|
keybd_event((BYTE)(iLoop + '1'), 0, 0, 0);
|
|
keybd_event((BYTE)(iLoop + '1'), 0, KEYEVENTF_KEYUP, 0);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void Cand_OnPaint(HWND hWnd)
|
|
{
|
|
HDC hDC;
|
|
HWND hWndUI;
|
|
HIMC hIMC;
|
|
LPINPUTCONTEXT lpIMC;
|
|
LPCANDIDATEINFO lpCandInfo;
|
|
LPCANDIDATELIST lpCandList;
|
|
LPTSTR lpCandStr;
|
|
PAINTSTRUCT ps;
|
|
HFONT hOldFont;
|
|
DWORD iLoop, iStart;
|
|
int iSaveBkMode;
|
|
|
|
hDC = BeginPaint(hWnd, &ps);
|
|
hWndUI = GetWindow(hWnd, GW_OWNER);
|
|
hIMC = (HIMC)GetWindowLongPtr(hWndUI, IMMGWL_IMC);
|
|
lpIMC = ImmLockIMC(hIMC);
|
|
if (lpIMC != NULL) {
|
|
lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
|
|
lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + sizeof(CANDIDATEINFO));
|
|
if (lpCandInfo && lpCandList->dwCount)
|
|
{
|
|
hOldFont = SelectObject(hDC, hFontFix);
|
|
DrawBitmap(hDC, 0, 0, hBMCand);
|
|
iSaveBkMode = SetBkMode(hDC, TRANSPARENT);
|
|
iStart = (lpCandList->dwSelection / lpCandList->dwPageSize) * lpCandList->dwPageSize;
|
|
for (iLoop = 0; iLoop < 9 && iStart+iLoop < lpCandList->dwCount; iLoop++)
|
|
{
|
|
lpCandStr = (LPTSTR)lpCandList + lpCandList->dwOffset[iStart + iLoop];
|
|
TextOut(hDC, rcBtn[iLoop].left + 10, rcBtn[iLoop].top +3, lpCandStr, 2);
|
|
}
|
|
SetBkMode(hDC, iSaveBkMode);
|
|
for (iLoop = iLoop; iLoop < 9; iLoop++)
|
|
DrawBitmap(hDC, rcBtn[iLoop].left + 3, rcBtn[iLoop].top + 6, hBMCandNum);
|
|
if (iStart)
|
|
DrawBitmap(hDC, 19, 8, hBMCandArr[0]);
|
|
if (iStart + 9 < lpCandList->dwCount)
|
|
DrawBitmap(hDC, 296, 8, hBMCandArr[1]);
|
|
SelectObject(hDC, hOldFont);
|
|
}
|
|
ImmUnlockIMCC(lpIMC->hCandInfo);
|
|
ImmUnlockIMC(hIMC);
|
|
}
|
|
EndPaint(hWnd, &ps);
|
|
}
|
|
|
|
|
|
LRESULT DoIMEControl(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HIMC hIMC;
|
|
LPINPUTCONTEXT lpIMC;
|
|
HGLOBAL hUIInst;
|
|
LPUIINSTANCE lpUIInst;
|
|
LPCANDIDATEFORM lpCandForm;
|
|
LPLOGFONT lpLogFont;
|
|
LOGFONT lfFont;
|
|
LPCOMPOSITIONFORM lpCompForm;
|
|
PPOINTS pPointS;
|
|
RECT rcRect;
|
|
LRESULT lRet = FALSE;
|
|
|
|
switch (wParam)
|
|
{
|
|
case IMC_GETCANDIDATEPOS:
|
|
hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
|
|
if (hIMC && (lpIMC = ImmLockIMC(hIMC)))
|
|
{
|
|
lpCandForm = (LPCANDIDATEFORM)lParam;
|
|
*lpCandForm = lpIMC->cfCandForm[0];
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
GetWindowRect(lpUIInst->rghWnd[CAND_WINDOW], (LPRECT)&rcRect);
|
|
lpCandForm->ptCurrentPos.x = rcRect.left;
|
|
lpCandForm->ptCurrentPos.y = rcRect.top;
|
|
GlobalUnlock(hUIInst);
|
|
ImmUnlockIMC(hIMC);
|
|
}
|
|
break;
|
|
|
|
case IMC_GETCOMPOSITIONFONT:
|
|
lpLogFont = (LPLOGFONT)lParam;
|
|
if (GetObject(hFontFix, sizeof(lfFont), (LPVOID)&lfFont))
|
|
*lpLogFont = lfFont;
|
|
break;
|
|
|
|
case IMC_GETCOMPOSITIONWINDOW:
|
|
hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
|
|
if (hIMC && (lpIMC = ImmLockIMC(hIMC)))
|
|
{
|
|
lpCompForm = (LPCOMPOSITIONFORM)lParam;
|
|
*lpCompForm = lpIMC->cfCompForm;
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
GetWindowRect(lpUIInst->rghWnd[COMP_WINDOW], (LPRECT)&rcRect);
|
|
lpCompForm->ptCurrentPos.x = rcRect.left;
|
|
lpCompForm->ptCurrentPos.y = rcRect.top;
|
|
GlobalUnlock(hUIInst);
|
|
ImmUnlockIMC(hIMC);
|
|
}
|
|
break;
|
|
|
|
case IMC_GETSTATUSWINDOWPOS:
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
GetWindowRect(lpUIInst->rghWnd[STATE_WINDOW], (LPRECT)&rcRect);
|
|
pPointS = (PPOINTS)&lRet;
|
|
pPointS->x = (short)rcRect.left;
|
|
pPointS->y = (short)rcRect.top;
|
|
GlobalUnlock(hUIInst);
|
|
break;
|
|
|
|
default:
|
|
lRet = TRUE;
|
|
}
|
|
return lRet;
|
|
}
|
|
|
|
|
|
LRESULT DoIMENotify(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HIMC hIMC;
|
|
LPINPUTCONTEXT lpIMC;
|
|
HGLOBAL hUIInst;
|
|
LPUIINSTANCE lpUIInst;
|
|
LPCANDIDATEINFO lpCandInfo;
|
|
DWORD fdwUIFlags;
|
|
POINT pt, ptTmp;
|
|
RECT rcTmp;
|
|
BOOL lRet = FALSE;
|
|
|
|
switch (wParam)
|
|
{
|
|
case IMN_OPENSTATUSWINDOW:
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
fdwUIFlags = (DWORD)GetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS);
|
|
fdwUIFlags |= UIF_SHOWSTATUS;
|
|
SetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS, fdwUIFlags);
|
|
if (fWndOpen[STATE_WINDOW] != FALSE && GetWindowLongPtr(hWnd, IMMGWL_IMC)) {
|
|
ShowWindow(lpUIInst->rghWnd[STATE_WINDOW], SW_SHOWNOACTIVATE);
|
|
}
|
|
GlobalUnlock(hUIInst);
|
|
break;
|
|
|
|
case IMN_CLOSESTATUSWINDOW:
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
fdwUIFlags = (DWORD)GetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS);
|
|
fdwUIFlags &= ~UIF_SHOWSTATUS;
|
|
SetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS, fdwUIFlags);
|
|
ShowWindow(lpUIInst->rghWnd[STATE_WINDOW], SW_HIDE);
|
|
GlobalUnlock(hUIInst);
|
|
break;
|
|
|
|
case IMN_CHANGECANDIDATE:
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
InvalidateRect(lpUIInst->rghWnd[CAND_WINDOW], NULL, TRUE);
|
|
GlobalUnlock(hUIInst);
|
|
break;
|
|
|
|
case IMN_CLOSECANDIDATE:
|
|
hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
|
|
lpIMC = ImmLockIMC(hIMC);
|
|
if (lpIMC != NULL) {
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
if (lpUIInst == NULL) {
|
|
ImmUnlockIMC(hIMC);
|
|
break;
|
|
}
|
|
lpIMC->hCandInfo = ImmReSizeIMCC(lpIMC->hCandInfo, sizeof(CANDIDATEINFO));
|
|
lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
|
|
lpCandInfo->dwSize = sizeof(CANDIDATEINFO);
|
|
lpCandInfo->dwCount = 0;
|
|
ImmUnlockIMCC(lpIMC->hCandInfo);
|
|
InvalidateRect(lpUIInst->rghWnd[STATE_WINDOW], NULL, TRUE);
|
|
ShowWindow(lpUIInst->rghWnd[CAND_WINDOW], SW_HIDE);
|
|
GlobalUnlock(hUIInst);
|
|
ImmUnlockIMC(hIMC);
|
|
}
|
|
break;
|
|
|
|
case IMN_OPENCANDIDATE:
|
|
hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
|
|
lpIMC = ImmLockIMC(hIMC);
|
|
if (lpIMC != NULL) {
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
if (lpUIInst == NULL) {
|
|
ImmUnlockIMC(hIMC);
|
|
break;
|
|
}
|
|
InvalidateRect(lpUIInst->rghWnd[STATE_WINDOW], NULL, TRUE);
|
|
ShowWindow(lpUIInst->rghWnd[CAND_WINDOW], fWndOpen[CAND_WINDOW]? SW_SHOWNOACTIVATE: SW_HIDE);
|
|
UpdateWindow(lpUIInst->rghWnd[STATE_WINDOW]);
|
|
UpdateWindow(lpUIInst->rghWnd[CAND_WINDOW]);
|
|
GlobalUnlock(hUIInst);
|
|
ImmUnlockIMC(hIMC);
|
|
}
|
|
break;
|
|
|
|
case IMN_SETCONVERSIONMODE:
|
|
case IMN_SETOPENSTATUS:
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
if (lpUIInst != NULL) {
|
|
InvalidateRect(lpUIInst->rghWnd[STATE_WINDOW], NULL, TRUE);
|
|
GlobalUnlock(hUIInst);
|
|
}
|
|
break;
|
|
|
|
case IMN_SETCANDIDATEPOS:
|
|
hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
|
|
lpIMC = ImmLockIMC(hIMC);
|
|
if (lpIMC == NULL)
|
|
break;
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
if (lpUIInst == NULL) {
|
|
ImmUnlockIMC(hIMC);
|
|
break;
|
|
}
|
|
if (lpIMC->cfCandForm[0].dwIndex == -1)
|
|
pt = ptCand;
|
|
else
|
|
{
|
|
switch (lpIMC->cfCandForm[0].dwStyle)
|
|
{
|
|
case CFS_CANDIDATEPOS:
|
|
pt = lpIMC->cfCandForm[0].ptCurrentPos;
|
|
ClientToScreen(lpIMC->hWnd, &pt);
|
|
if (pt.x < rcScreen.left)
|
|
pt.x = rcScreen.left;
|
|
else if (pt.x > rcScreen.right - CANDXSIZE)
|
|
pt.x = rcScreen.right - CANDXSIZE;
|
|
if (pt.y < rcScreen.top)
|
|
pt.y = rcScreen.top;
|
|
else if (pt.y > rcScreen.bottom - CANDYSIZE)
|
|
pt.y = rcScreen.bottom - CANDYSIZE;
|
|
break;
|
|
|
|
case CFS_EXCLUDE:
|
|
pt = lpIMC->cfCandForm[0].ptCurrentPos;
|
|
rcTmp.left = pt.x;
|
|
rcTmp.top = pt.y;
|
|
rcTmp.right = pt.x + CANDXSIZE;
|
|
rcTmp.bottom = pt.y + CANDYSIZE;
|
|
ClientToScreen(lpIMC->hWnd, &pt);
|
|
if (pt.x < rcScreen.left)
|
|
pt.x = rcScreen.left;
|
|
else if (pt.x > rcScreen.right - CANDXSIZE)
|
|
pt.x = rcScreen.right - CANDXSIZE;
|
|
if (pt.y < rcScreen.top)
|
|
pt.y = rcScreen.top;
|
|
else if (pt.y > rcScreen.bottom - CANDYSIZE)
|
|
pt.y = rcScreen.bottom - CANDYSIZE;
|
|
if (IntersectRect(&rcTmp, &rcTmp, &lpIMC->cfCandForm[0].rcArea))
|
|
{
|
|
ptTmp.x = lpIMC->cfCandForm[0].rcArea.right;
|
|
ptTmp.y = lpIMC->cfCandForm[0].rcArea.bottom;
|
|
ClientToScreen(lpIMC->hWnd, &ptTmp);
|
|
pt.y = (ptTmp.y < rcScreen.bottom - CANDYSIZE)? ptTmp.y:
|
|
ptTmp.y - lpIMC->cfCandForm[0].rcArea.bottom
|
|
+ lpIMC->cfCandForm[0].rcArea.top - CANDYSIZE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
pt = ptCand;
|
|
}
|
|
}
|
|
MoveWindow(lpUIInst->rghWnd[CAND_WINDOW], pt.x, pt.y, CANDXSIZE, CANDYSIZE, TRUE);
|
|
GlobalUnlock(hUIInst);
|
|
ImmUnlockIMC(hIMC);
|
|
break;
|
|
|
|
case IMN_SETCOMPOSITIONWINDOW:
|
|
hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
|
|
lpIMC = ImmLockIMC(hIMC);
|
|
if (lpIMC == NULL)
|
|
break;
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
if (lpUIInst == NULL) {
|
|
ImmUnlockIMC(hIMC);
|
|
break;
|
|
}
|
|
if (lpIMC->cfCompForm.dwStyle & CFS_RECT)
|
|
{
|
|
pt.x = lpIMC->cfCompForm.rcArea.left;
|
|
pt.y = lpIMC->cfCompForm.rcArea.top;
|
|
ClientToScreen(lpIMC->hWnd, &pt);
|
|
}
|
|
else if (lpIMC->cfCompForm.dwStyle & CFS_POINT)
|
|
{
|
|
pt = lpIMC->cfCompForm.ptCurrentPos;
|
|
ClientToScreen(lpIMC->hWnd, &pt);
|
|
}
|
|
else // For CFS_DEFAULT
|
|
pt = lpIMC->cfCompForm.ptCurrentPos = ptComp;
|
|
MoveWindow(lpUIInst->rghWnd[COMP_WINDOW], pt.x, pt.y, COMPSIZE, COMPSIZE, TRUE);
|
|
GlobalUnlock(hUIInst);
|
|
ImmUnlockIMC(hIMC);
|
|
break;
|
|
|
|
case IMN_SETSTATUSWINDOWPOS:
|
|
hIMC = (HIMC)GetWindowLongPtr(hWnd, IMMGWL_IMC);
|
|
lpIMC = ImmLockIMC(hIMC);
|
|
if (lpIMC == NULL)
|
|
break;
|
|
hUIInst = (HGLOBAL)GetWindowLongPtr(hWnd, IMMGWL_PRIVATE);
|
|
lpUIInst = (LPUIINSTANCE)GlobalLock(hUIInst);
|
|
if (lpUIInst == NULL) {
|
|
ImmUnlockIMC(hIMC);
|
|
break;
|
|
}
|
|
MoveWindow(lpUIInst->rghWnd[STATE_WINDOW], lpIMC->ptStatusWndPos.x,
|
|
lpIMC->ptStatusWndPos.y, STATEXSIZE, STATEYSIZE, TRUE);
|
|
fdwUIFlags = (DWORD)GetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS);
|
|
fdwUIFlags |= UIF_PRIVATEPOS;
|
|
SetWindowLong(lpUIInst->rghWnd[STATE_WINDOW], UIGWL_FLAGS, fdwUIFlags);
|
|
GlobalUnlock(hUIInst);
|
|
ImmUnlockIMC(hIMC);
|
|
break;
|
|
|
|
default:
|
|
lRet = TRUE;
|
|
}
|
|
return lRet;
|
|
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
}
|