#include #include "PCMan.h" #include "AVDictionary.h" #include "AVConfig.h" #define ITEMS_PER_ROW 4 LRESULT APIENTRY CandWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_PAINT: PaintCandWindow(hWnd); break; case WM_SETCURSOR: case WM_MOUSEMOVE: case WM_LBUTTONUP: case WM_RBUTTONUP: DragUI(hWnd, NULL, msg, wParam, lParam, FALSE); if ((msg == WM_SETCURSOR) && (HIWORD(lParam) != WM_LBUTTONDOWN) && (HIWORD(lParam) != WM_RBUTTONDOWN)) return DefWindowProc(hWnd, msg, wParam, lParam); if ((msg == WM_LBUTTONUP) || (msg == WM_RBUTTONUP)) SetWindowLong(hWnd, FIGWL_MOUSE, 0L); break; default: if (!MyIsIMEMessage(msg)){ return DefWindowProc(hWnd, msg, wParam, lParam); } break; } return 0L; } void UICreateCandWindow(HWND hUIWnd) { if (!IsWindow(uiCand.hWnd)) { SIZE sz; sz.cx = sz.cy = 0; uiCand.hWnd = CreateWindowEx(0, UICANDCLASSNAME ,NULL, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, hUIWnd,NULL,hInst,NULL); SetWindowLong(uiCand.hWnd, FIGWL_SVRWND, (DWORD)hUIWnd); uiCand.sz.cx = sz.cx + 2; uiCand.sz.cy = sz.cy + 4; } ShowWindow(uiCand.hWnd, SW_HIDE); return; } int CompIndexToXPos( int i ); BOOL GetCandPosFromCompWnd(LPSIZE lpsz) { if (IsWindow(uiComp.hWnd)) { RECT rc, screenrc; POINT pt; GetWindowRect(uiComp.hWnd, &rc); pt.x = rc.left; pt.y = rc.bottom + 2; pt.x += CompIndexToXPos( CompCursorPos ); GetWindowRect(uiCand.hWnd, &rc); pt.x -= 16; if( pt.x < 0 ) pt.x = 0; SystemParametersInfo(SPI_GETWORKAREA, 0, &screenrc, 0); if( (pt.x + lpsz->cx) > screenrc.right) pt.x = screenrc.right - lpsz->cx - 5;//rc.left - lpsz->cx - 5; if( (pt.y + lpsz->cy) > screenrc.bottom) pt.y = screenrc.bottom - lpsz->cy; uiCand.pt.x = pt.x; uiCand.pt.y = pt.y; return TRUE; } return FALSE; } void UIMoveCandWindow(HWND hUIWnd, int X, int Y, wchar_t* lpStr) { free(lpCandStr); numCand = 0; lpCandStr = wcsdup(lpStr); if( !*lpStr ) { UIHideCandWindow(); return; } if (!IsWindow(uiCand.hWnd)) UICreateCandWindow(hUIWnd); // FIXME: UIMoveCandWindow will be called twice almost at the same time. // The first call cause some problems. // This should be fixed in the future. // It's impossible to have lpStr != NULL and lpCompStr ==NULL. // Since there is no composition string, is candidate window needed? // if( !lpCompStr || !*lpCompStr ) // return; if (IsWindow(uiCand.hWnd)) { HDC hDC; HFONT oldFont; SIZE sz; SIZE candsz; sz.cx = 0; sz.cy = 0; AVConfig cfg; AVDictionary *dict = AVDictionary::getDict(cfg.getUserDir(), "OVIMEUI"); int items_per_row = dict->keyExist("items_per_row") ? dict->getInteger("items_per_row") : ITEMS_PER_ROW; // No Cand if(lpStr == NULL) { ShowWindow(uiCand.hWnd, SW_HIDE); return; } hDC = GetDC(uiCand.hWnd); oldFont = (HFONT)SelectObject(hDC, hUIFont); LPCTSTR cand = wcstok( lpCandStr, L" "); // strtok, delimited by space int num = 0; int width = 0; while( cand ) { ++numCand; int len = (int)wcslen( cand ); GetTextExtentPoint32(hDC, cand, len, &candsz); candsz.cx += 4; candsz.cy += 2; width += candsz.cx; ++num; if( num >= items_per_row ) { sz.cy += candsz.cy; if( width > sz.cx ) sz.cx = width; width = 0; num = 0; } cand = wcstok( NULL, L" " ); } if( width > sz.cx ) sz.cx = width; if( num > 0 && num < items_per_row ) sz.cy += candsz.cy; sz.cy += 2; sz.cx += 2; SelectObject(hDC, oldFont); ReleaseDC(uiCand.hWnd,hDC); if( X > 0 && Y > 0) { RECT screenrc; SystemParametersInfo(SPI_GETWORKAREA, 0, &screenrc, 0); if( (X + sz.cx) > screenrc.right) X = screenrc.right - sz.cx - 5;//rc.left - lpsz->cx - 5; if( (Y + sz.cy) > screenrc.bottom) Y = screenrc.bottom - sz.cy; uiCand.pt.x = X; uiCand.pt.y = Y; MoveWindow(uiCand.hWnd, uiCand.pt.x, uiCand.pt.y, sz.cx, sz.cy, TRUE); //ShowWindow(uiCand.hWnd, SW_SHOWNOACTIVATE); InvalidateRect(uiCand.hWnd, NULL, FALSE); } else if( GetCandPosFromCompWnd(&sz) ) { MoveWindow(uiCand.hWnd, uiCand.pt.x, uiCand.pt.y, sz.cx, sz.cy, TRUE); //ShowWindow(uiCand.hWnd, SW_SHOWNOACTIVATE); InvalidateRect(uiCand.hWnd, NULL, FALSE); } } } void PaintCandWindow(HWND hCandWnd) { PAINTSTRUCT ps; HDC hDC; HFONT oldFont; RECT rc; //DWORD i; hDC = BeginPaint(hCandWnd,&ps); oldFont = (HFONT)SelectObject(hDC, hUIFont); GetClientRect(hCandWnd,&rc); if(lpCandStr) { SetTextColor( hDC, GetSysColor( COLOR_WINDOWTEXT ) ); SetBkColor( hDC, GetSysColor( COLOR_WINDOW ) ); AVConfig cfg; AVDictionary *dict = AVDictionary::getDict(cfg.getBaseDir(), "OVIMEUI"); int items_per_row = dict->keyExist("items_per_row") ? dict->getInteger("items_per_row") : ITEMS_PER_ROW; RECT cand_rc; cand_rc.left = 1; cand_rc.top = 1; LPCTSTR cand = lpCandStr; //Array foo = cand.split(new char[]{' '}); int num = 0; for( int i = 0; i < numCand; ++i ) { ++num; int len = (int)wcslen( cand ); SIZE candsz; GetTextExtentPoint32(hDC, cand, len, &candsz); candsz.cx += 4; candsz.cy += 2; cand_rc.right = cand_rc.left + candsz.cx; cand_rc.bottom = cand_rc.top + candsz.cy; if( (i + 1) == numCand ) SetTextColor( hDC, RGB(0, 0, 192) ); ExtTextOut( hDC, cand_rc.left + 2, cand_rc.top, ETO_OPAQUE, &cand_rc, cand, len, NULL); if( num >= items_per_row && (i + 1) < numCand ) { cand_rc.left = 1; cand_rc.top += candsz.cy; num = 0; } else cand_rc.left = cand_rc.right; cand = cand + wcslen(cand) + 1; } cand_rc.left = cand_rc.right; cand_rc.right = rc.right; ExtTextOut( hDC, cand_rc.left, cand_rc.top, ETO_OPAQUE, &cand_rc, NULL, 0, NULL); } Draw3DBorder( hDC, &rc, GetSysColor(COLOR_3DFACE), 0/*GetSysColor(COLOR_3DDKSHADOW)*/); SelectObject(hDC, oldFont); EndPaint(hCandWnd,&ps); } void UIShowCandWindow() { if (IsWindow(uiCand.hWnd)) ShowWindow(uiCand.hWnd, SW_SHOWNOACTIVATE); } void UIHideCandWindow() { if (IsWindow(uiCand.hWnd)) ShowWindow(uiCand.hWnd, SW_HIDE); }