WindowsXP-SP1/windows/feime/kor/imeui.c
2020-09-30 16:53:49 +02:00

1335 lines
49 KiB
C
Raw Blame History

/******************************************************************************
*
* 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("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
#else
hFontFix = CreateFont(-16,0,0,0,0,0,0,0,129,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH,TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
#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);
}