/**************************************************************************** COMPUI.CPP Owner: cslim Copyright (c) 1997-1999 Microsoft Corporation Composition window UI functions History: 14-JUL-1999 cslim Copied from IME98 source tree *****************************************************************************/ #include "precomp.h" #include "ui.h" #include "imedefs.h" #include "names.h" #include "escape.h" #include "winex.h" #include "cicero.h" #include "debug.h" #include "resource.h" PRIVATE VOID PASCAL PaintCompWindow(HWND hCompWnd, HDC hDC); /////////////////////////////////////////////////////////////////////////////// LRESULT CALLBACK CompWndProc(HWND hCompWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) { Dbg(DBGID_UI, TEXT("CompWndProc():uMessage = 0x%08lX, wParam = 0x%04X, lParam = 0x%08lX"), uMessage, wParam, lParam); switch (uMessage) { case WM_IME_CHAR: case WM_IME_COMPOSITIONFULL: case WM_IME_COMPOSITION: case WM_IME_CONTROL: case WM_IME_SELECT: case WM_IME_SETCONTEXT: case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION: return (0L); case WM_PAINT: { HDC hDC; PAINTSTRUCT ps; hDC = BeginPaint(hCompWnd, &ps); PaintCompWindow(hCompWnd, hDC); EndPaint(hCompWnd, &ps); } break; default : return DefWindowProc(hCompWnd, uMessage, wParam, lParam); } return (0L); } VOID PASCAL PaintCompWindow(HWND hCompWnd, HDC hDC) { HWND hWndUI; HIMC hIMC; PCIMECtx pImeCtx; HFONT hFontFix, hOldFont; HBITMAP hBMComp; INT iSaveBkMode; hWndUI = GetWindow(hCompWnd, GW_OWNER); hIMC = GethImcFromHwnd(hWndUI); if ((pImeCtx = GetIMECtx(hIMC)) == NULL) return; Dbg(DBGID_UI, TEXT("PaintCompWindow():CompCh = 0x%X"), pImeCtx->GetCompBufStr()); if (pImeCtx->GetCompBufLen()) { // Create font if (IsWinNT()) hFontFix = CreateFontW( -16,0,0,0, 0,0,0,0, HANGUL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, wzIMECompFont); else hFontFix = CreateFontA( -16,0,0,0, 0,0,0,0, HANGUL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, szIMECompFont); hOldFont = (HFONT)SelectObject(hDC, hFontFix); // Draw comp window Bitmap hBMComp = (HBITMAP)OurLoadImage(MAKEINTRESOURCE(IDB_COMP_WIN), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE|LR_LOADMAP3DCOLORS ); DrawBitmap(hDC, 0, 0, hBMComp); iSaveBkMode = SetBkMode(hDC, TRANSPARENT); // Set text color SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); OurTextOutW(hDC, 3, 3, pImeCtx->GetCompBufStr()); // restore and delete created objects SelectObject(hDC, hOldFont); SetBkMode(hDC, iSaveBkMode); DeleteObject(hBMComp); DeleteObject(hFontFix); } } // open comp window VOID PASCAL OpenComp(HWND hUIWnd) { HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; HIMC hIMC; PCIMECtx pImeCtx; INT nShowCompCmd; POINT ptClientComp; CIMEData ImeData; Dbg(DBGID_UI, TEXT("OpenComp()")); hUIPrivate = GethUIPrivateFromHwnd(hUIWnd); // can not draw comp window if (!hUIPrivate) { DbgAssert(0); return; } lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate); if (!lpUIPrivate) return; // Check WM_IME_SETCONTEXT lParam if ((lpUIPrivate->uiShowParam & ISC_SHOWUICOMPOSITIONWINDOW) == 0) goto OpenCompUnlockUIPriv; hIMC = GethImcFromHwnd(hUIWnd); pImeCtx = GetIMECtx(hIMC); if (pImeCtx == NULL) { Dbg(DBGID_UI, TEXT("OpenComp - Invalid hImc")); ImeData->ptCompPos.x = ImeData->rcWorkArea.right - COMP_SIZEX; ImeData->ptCompPos.y = ImeData->rcWorkArea.bottom - COMP_SIZEY; nShowCompCmd = SW_HIDE; } else { #if 1 // MultiMonitor RECT rcWorkArea; ImeMonitorWorkAreaFromWindow(pImeCtx->GetAppWnd(), &rcWorkArea); // if client window exist in same monitor as status window if (!IsCicero() && PtInRect(&rcWorkArea, ImeData->ptStatusPos)) { ImeData->ptCompPos.x = (ImeData->ptStatusPos.x+ImeData->xStatusWi+UI_GAPX + COMP_SIZEX > ImeData->rcWorkArea.right) ? ImeData->ptStatusPos.x - UI_GAPX - COMP_SIZEX : ImeData->ptStatusPos.x + ImeData->xStatusWi + UI_GAPX; ImeData->ptCompPos.y = ImeData->ptStatusPos.y; Dbg(DBGID_UI, TEXT("OpenComp - PtInRect x = %d, y = %d"), ImeData->ptCompPos.x, ImeData->ptCompPos.y); } else { // if client window appeared in different monitor from status window resides, // then display left top of workarea of client window montitor ImeData->ptCompPos.x = 0; ImeData->ptCompPos.y = 0; } #else ImeData->ptCompPos.x = (ImeData->ptStatusPos.x+ImeData->xStatusWi+UI_GAPX + COMP_SIZEX > ImeData->rcWorkArea.right) ? ImeData->ptStatusPos.x - UI_GAPX - COMP_SIZEX : ImeData->ptStatusPos.x + ImeData->xStatusWi + UI_GAPX; ImeData->ptCompPos.y = ImeData->ptStatusPos.y; #endif // Set Comp wnd position of HIMC in client coordinate ptClientComp = ImeData->ptCompPos; ScreenToClient(pImeCtx->GetAppWnd(), &ptClientComp); pImeCtx->SetCompositionFormPos(ptClientComp); nShowCompCmd = SW_SHOWNOACTIVATE; } if (lpUIPrivate->hCompWnd) { SetWindowPos(lpUIPrivate->hCompWnd, NULL, ImeData->ptCompPos.x, ImeData->ptCompPos.y, 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER); } else { Dbg(DBGID_UI, TEXT("OpenComp - CreateWindow x = %d, y = %d"), ImeData->ptCompPos.x, ImeData->ptCompPos.y); // create comp window lpUIPrivate->hCompWnd = CreateWindow( szCompClassName, TEXT("\0"), WS_DISABLED | WS_POPUP, ImeData->ptCompPos.x, ImeData->ptCompPos.y, COMP_SIZEX, COMP_SIZEX, hUIWnd, (HMENU)NULL, vpInstData->hInst, NULL); DbgAssert(lpUIPrivate->hCompWnd != 0); //if (!lpUIPrivate->hCompWnd) // goto OpenCompUnlockUIPriv; } //if (pImeCtx) // ShowComp(hUIWnd, SW_SHOWNOACTIVATE); OpenCompUnlockUIPriv: GlobalUnlock(hUIPrivate); return; } // Show the composition window VOID ShowComp(HWND hUIWnd, INT nShowCompCmd) { HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; HIMC hIMC; PCIMECtx pImeCtx; Dbg(DBGID_UI, TEXT("ShowComp(): nShowCompCmd = %d"), nShowCompCmd); hUIPrivate = GethUIPrivateFromHwnd(hUIWnd); // can not draw comp window if (!hUIPrivate) { DbgAssert(0); return; } lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate); if (!lpUIPrivate) { DbgAssert(0); return; } hIMC = GethImcFromHwnd(hUIWnd); if ((pImeCtx = GetIMECtx(hIMC)) == NULL) goto SwCompNoChange; // b#53794 // Some absurd Apps send WM_IME_START_COMPOSITION and WM_IME_COMPOSITION, // even though they have no composition string // In this case wrong composition window appears in screen like white square or something. if (nShowCompCmd == SW_SHOWNOACTIVATE) { if (pImeCtx->GetCompBufLen() == 0 || vfWndOpen[COMP_WINDOW] == fFalse) nShowCompCmd = SW_HIDE; } if (lpUIPrivate->nShowCompCmd == nShowCompCmd) goto SwCompNoChange; if (lpUIPrivate->hCompWnd) { ShowWindow(lpUIPrivate->hCompWnd, nShowCompCmd); lpUIPrivate->nShowCompCmd = nShowCompCmd; } else lpUIPrivate->nShowCompCmd = SW_HIDE; SwCompNoChange: GlobalUnlock(hUIPrivate); } BOOL fSetCompWindowPos(HWND hCompWnd) { HIMC hIMC; PCIMECtx pImeCtx; RECT rcCur; POINT ptNew; CIMEData ImeData; // No composition window if (hCompWnd == 0) return fFalse; hIMC = GethImcFromHwnd(GetWindow(hCompWnd, GW_OWNER)); //if (!hIMC) // { // DbgAssert(0); // return fFalse; // } //lpIMC = (LPINPUTCONTEXT)OurImmLockIMC(hIMC); //if (!lpIMC) // { // DbgAssert(0); // return fFalse; // } if ((pImeCtx = GetIMECtx(hIMC)) == NULL) return fFalse; Dbg(DBGID_UI, TEXT("fSetCompWindowPos()")); if (pImeCtx->GetCompositionFormStyle() & CFS_RECT) { Dbg(DBGID_UI, TEXT("fSetCompWindowPos(): CFS_RECT")); pImeCtx->GetCompositionForm(&rcCur); ptNew.x = rcCur.left; ptNew.y = rcCur.top; ClientToScreen(pImeCtx->GetAppWnd(), &ptNew); } else if (pImeCtx->GetCompositionFormStyle() & CFS_POINT) { Dbg(DBGID_UI, TEXT("fSetCompWindowPos(): CFS_POINT")); pImeCtx->GetCompositionForm(&ptNew); ClientToScreen(pImeCtx->GetAppWnd(), &ptNew); } else { // For CFS_DEFAULT Dbg(DBGID_UI, TEXT("fSetCompWindowPos(): CFS_DEFAULT")); #if 1 // MultiMonitor RECT rcWorkArea; ImeMonitorWorkAreaFromWindow(pImeCtx->GetAppWnd(), &rcWorkArea); // if client window exist in same monitor as status window if ( PtInRect(&rcWorkArea, ImeData->ptStatusPos) ) { ptNew.x = (ImeData->ptStatusPos.x+ImeData->xStatusWi+UI_GAPX + COMP_SIZEX > ImeData->rcWorkArea.right) ? ImeData->ptStatusPos.x - UI_GAPX - COMP_SIZEX : ImeData->ptStatusPos.x + ImeData->xStatusWi + UI_GAPX; ptNew.y = ImeData->ptStatusPos.y; } else { // if client window appeared in different monitor from status window resides, // then display right bottom of workarea of client window montitor ptNew.x = rcWorkArea.right - COMP_SIZEX; ptNew.y = rcWorkArea.bottom - COMP_SIZEY; } #else ptNew.x = (ImeData->ptStatusPos.x+ImeData->xStatusWi+UI_GAPX + COMP_SIZEX > ImeData->rcWorkArea.right) ? ImeData->ptStatusPos.x - UI_GAPX - COMP_SIZEX : ImeData->ptStatusPos.x + ImeData->xStatusWi + UI_GAPX; ptNew.y = ImeData->ptStatusPos.y; #endif ImeData->ptCompPos = ptNew; ScreenToClient(pImeCtx->GetAppWnd(), &ptNew); pImeCtx->SetCompositionFormPos(ptNew); } SetWindowPos(hCompWnd, NULL, ptNew.x, ptNew.y, 0, 0, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOSIZE|SWP_NOZORDER); return (fTrue); }