1 /* 2 * PROJECT: ReactOS msctfime.ime 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: User Interface of msctfime.ime 5 * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 */ 7 8 #include "msctfime.h" 9 10 WINE_DEFAULT_DEBUG_CHANNEL(msctfime); 11 12 /***********************************************************************/ 13 14 UINT WM_MSIME_SERVICE = 0; 15 UINT WM_MSIME_UIREADY = 0; 16 UINT WM_MSIME_RECONVERTREQUEST = 0; 17 UINT WM_MSIME_RECONVERT = 0; 18 UINT WM_MSIME_DOCUMENTFEED = 0; 19 UINT WM_MSIME_QUERYPOSITION = 0; 20 UINT WM_MSIME_MODEBIAS = 0; 21 UINT WM_MSIME_SHOWIMEPAD = 0; 22 UINT WM_MSIME_MOUSE = 0; 23 UINT WM_MSIME_KEYMAP = 0; 24 25 /// @implemented 26 BOOL IsMsImeMessage(_In_ UINT uMsg) 27 { 28 return (uMsg == WM_MSIME_SERVICE || 29 uMsg == WM_MSIME_UIREADY || 30 uMsg == WM_MSIME_RECONVERTREQUEST || 31 uMsg == WM_MSIME_RECONVERT || 32 uMsg == WM_MSIME_DOCUMENTFEED || 33 uMsg == WM_MSIME_QUERYPOSITION || 34 uMsg == WM_MSIME_MODEBIAS || 35 uMsg == WM_MSIME_SHOWIMEPAD || 36 uMsg == WM_MSIME_MOUSE || 37 uMsg == WM_MSIME_KEYMAP); 38 } 39 40 /// @implemented 41 BOOL RegisterMSIMEMessage(VOID) 42 { 43 // Using ANSI (A) version here can reduce binary size. 44 WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService"); 45 WM_MSIME_UIREADY = RegisterWindowMessageA("MSIMEUIReady"); 46 WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest"); 47 WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert"); 48 WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed"); 49 WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition"); 50 WM_MSIME_MODEBIAS = RegisterWindowMessageA("MSIMEModeBias"); 51 WM_MSIME_SHOWIMEPAD = RegisterWindowMessageA("MSIMEShowImePad"); 52 WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation"); 53 WM_MSIME_KEYMAP = RegisterWindowMessageA("MSIMEKeyMap"); 54 return (WM_MSIME_SERVICE && 55 WM_MSIME_UIREADY && 56 WM_MSIME_RECONVERTREQUEST && 57 WM_MSIME_RECONVERT && 58 WM_MSIME_DOCUMENTFEED && 59 WM_MSIME_QUERYPOSITION && 60 WM_MSIME_MODEBIAS && 61 WM_MSIME_SHOWIMEPAD && 62 WM_MSIME_MOUSE && 63 WM_MSIME_KEYMAP); 64 } 65 66 /***********************************************************************/ 67 68 /// @implemented 69 CDefCompFrameGripper::CDefCompFrameGripper( 70 CDefCompFrameWindow *pDefCompFrameWindow, 71 LPCRECT prc, 72 DWORD style) : CUIFGripper(pDefCompFrameWindow, prc, style) 73 { 74 m_pDefCompFrameWindow = pDefCompFrameWindow; 75 } 76 77 /***********************************************************************/ 78 79 /// @implemented 80 CCompFinalizeButton::CCompFinalizeButton( 81 CCompFrameWindow *pParent, 82 DWORD nObjectID, 83 LPCRECT prc, 84 DWORD style, 85 DWORD dwButtonFlags, 86 LPCWSTR pszText) 87 : CUIFToolbarButton(pParent, nObjectID, prc, style, dwButtonFlags, pszText) 88 { 89 m_pCompFrameWindow = pParent; 90 } 91 92 /// @implemented 93 CCompFinalizeButton::~CCompFinalizeButton() 94 { 95 HICON hIcon = CUIFToolbarButton::GetIcon(); 96 if (hIcon) 97 { 98 ::DestroyIcon(hIcon); 99 CUIFToolbarButton::SetIcon(NULL); 100 } 101 } 102 103 /// @implemented 104 void CCompFinalizeButton::OnLeftClick() 105 { 106 HIMC hIMC = m_pCompFrameWindow->m_hIMC; 107 if (hIMC) 108 ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); 109 } 110 111 /***********************************************************************/ 112 113 /// @implemented 114 CCompFrameWindow::CCompFrameWindow(HIMC hIMC, DWORD style) 115 : CUIFWindow(g_hInst, style) 116 { 117 m_hIMC = hIMC; 118 } 119 120 /***********************************************************************/ 121 122 /// @implemented 123 CCompButtonFrameWindow::CCompButtonFrameWindow(HIMC hIMC, DWORD style) 124 : CCompFrameWindow(hIMC, style) 125 { 126 } 127 128 /// @implemented 129 void CCompButtonFrameWindow::Init() 130 { 131 if (m_pFinalizeButton) 132 return; 133 134 RECT rc = { 0, 0, 0, 0 }; 135 m_pFinalizeButton = new(cicNoThrow) CCompFinalizeButton(this, 0, &rc, 0, 0x10000, NULL); 136 137 m_pFinalizeButton->Initialize(); 138 m_pFinalizeButton->Init(); 139 140 HICON hIcon = (HICON)::LoadImageW(g_hInst, MAKEINTRESOURCEW(IDI_DOWN), IMAGE_ICON, 16, 16, 0); 141 m_pFinalizeButton->SetIcon(hIcon); 142 143 WCHAR szText[256]; 144 LoadStringW(g_hInst, IDS_FINALIZE_STRING, szText, _countof(szText)); 145 m_pFinalizeButton->SetToolTip(szText); 146 147 AddUIObj(m_pFinalizeButton); 148 } 149 150 /// @implemented 151 void CCompButtonFrameWindow::MoveShow(LONG x, LONG y, BOOL bShow) 152 { 153 INT nWidth = m_Margins.cxRightWidth + m_Margins.cxLeftWidth + 18; 154 INT nHeight = m_Margins.cyBottomHeight + m_Margins.cyTopHeight + 18; 155 Move(x, y, nWidth + 4, nHeight + 4); 156 157 if (m_pFinalizeButton) 158 { 159 RECT rc = { 1, 1, nWidth + 1, nHeight + 1 }; 160 m_pFinalizeButton->SetRect(&rc); 161 } 162 163 Show(bShow); 164 } 165 166 /// @implemented 167 STDMETHODIMP_(void) CCompButtonFrameWindow::OnCreate(HWND hWnd) 168 { 169 ::SetWindowTheme(hWnd, L"TOOLBAR", NULL); 170 171 ZeroMemory(&m_Margins, sizeof(m_Margins)); 172 173 CUIFTheme theme; 174 theme.m_hTheme = NULL; 175 theme.m_iPartId = 1; 176 theme.m_iStateId = 0; 177 theme.m_pszClassList = L"TOOLBAR"; 178 if (SUCCEEDED(theme.InternalOpenThemeData(hWnd))) 179 theme.GetThemeMargins(NULL, 1, 3602, NULL, &m_Margins); 180 } 181 182 /***********************************************************************/ 183 184 /// @implemented 185 CDefCompFrameWindow::CDefCompFrameWindow(HIMC hIMC, DWORD style) 186 : CCompFrameWindow(hIMC, style) 187 { 188 LoadPosition(); 189 m_iPartId = 1; 190 m_iStateId = 1; 191 m_pszClassList = L"TASKBAR"; 192 } 193 194 /// @implemented 195 CDefCompFrameWindow::~CDefCompFrameWindow() 196 { 197 SavePosition(); 198 } 199 200 /// @implemented 201 void CDefCompFrameWindow::Init() 202 { 203 RECT rc; 204 205 if (!m_pGripper) 206 { 207 ZeroMemory(&rc, sizeof(rc)); 208 m_pGripper = new(cicNoThrow) CDefCompFrameGripper(this, &rc, 0); 209 m_pGripper->Initialize(); 210 AddUIObj(m_pGripper); 211 } 212 213 if (!m_pFinalizeButton) 214 { 215 ZeroMemory(&rc, sizeof(rc)); 216 m_pFinalizeButton = new(cicNoThrow) CCompFinalizeButton(this, 0, &rc, 0, 0x10000, NULL); 217 m_pFinalizeButton->Initialize(); 218 m_pFinalizeButton->Init(); 219 220 HICON hIcon = (HICON)LoadImageW(g_hInst, MAKEINTRESOURCEW(IDI_DOWN), IMAGE_ICON, 16, 16, 0); 221 m_pFinalizeButton->SetIcon(hIcon); 222 223 WCHAR szText[256]; 224 ::LoadStringW(g_hInst, IDS_FINALIZE_STRING, szText, _countof(szText)); 225 SetToolTip(szText); 226 227 AddUIObj(m_pFinalizeButton); 228 } 229 } 230 231 /// @implemented 232 INT CDefCompFrameWindow::GetGripperWidth() 233 { 234 if (!m_pGripper || FAILED(m_pGripper->EnsureThemeData(m_hWnd))) 235 return 5; 236 237 INT ret = -1; 238 HDC hDC = ::GetDC(m_hWnd); 239 SIZE partSize; 240 if (SUCCEEDED(m_pGripper->GetThemePartSize(hDC, 1, 0, TS_TRUE, &partSize))) 241 ret = partSize.cx + 4; 242 243 ::ReleaseDC(m_hWnd, hDC); 244 245 return ((ret < 0) ? 5 : ret); 246 } 247 248 /// @implemented 249 void CDefCompFrameWindow::MyScreenToClient(LPPOINT ppt, LPRECT prc) 250 { 251 if (ppt) 252 ::ScreenToClient(m_hWnd, ppt); 253 254 if (prc) 255 { 256 ::ScreenToClient(m_hWnd, (LPPOINT)prc); 257 ::ScreenToClient(m_hWnd, (LPPOINT)&prc->right); 258 } 259 } 260 261 /// @implemented 262 void CDefCompFrameWindow::SetCompStrRect(INT nWidth, INT nHeight, BOOL bShow) 263 { 264 INT GripperWidth = GetGripperWidth(); 265 266 RECT rc; 267 ::GetWindowRect(m_hWnd, &rc); 268 269 Move(rc.left, rc.top, GripperWidth + nWidth + 24, nHeight + 10); 270 271 if (m_pGripper) 272 { 273 rc = { 2, 3, GripperWidth + 2, nHeight + 7 }; 274 m_pGripper->SetRect(&rc); 275 } 276 277 if (m_pFinalizeButton) 278 { 279 rc = { 280 GripperWidth + nWidth + 4, 281 3, 282 m_Margins.cxLeftWidth + m_Margins.cxRightWidth + GripperWidth + nWidth + 22, 283 m_Margins.cyBottomHeight + m_Margins.cyTopHeight + 21 284 }; 285 m_pFinalizeButton->SetRect(&rc); 286 } 287 288 Show(bShow); 289 290 ::MoveWindow(m_hwndCompStr, GripperWidth + 2, 7, nWidth, nHeight, TRUE); 291 ::ShowWindow(m_hwndCompStr, (bShow ? SW_SHOWNOACTIVATE : SW_HIDE)); 292 } 293 294 /// @implemented 295 void CDefCompFrameWindow::LoadPosition() 296 { 297 DWORD x = 0, y = 0; 298 299 LSTATUS error; 300 CicRegKey regKey; 301 error = regKey.Open(HKEY_CURRENT_USER, 302 TEXT("SOFTWARE\\Microsoft\\CTF\\CUAS\\DefaultCompositionWindow")); 303 if (error == ERROR_SUCCESS) 304 { 305 regKey.QueryDword(TEXT("Left"), &x); 306 regKey.QueryDword(TEXT("Top"), &y); 307 } 308 309 Move(x, y, 0, 0); 310 } 311 312 /// @implemented 313 void CDefCompFrameWindow::SavePosition() 314 { 315 LSTATUS error; 316 CicRegKey regKey; 317 error = regKey.Create(HKEY_CURRENT_USER, 318 TEXT("SOFTWARE\\Microsoft\\CTF\\CUAS\\DefaultCompositionWindow")); 319 if (error == ERROR_SUCCESS) 320 { 321 regKey.SetDword(TEXT("Left"), m_nLeft); 322 regKey.SetDword(TEXT("Top"), m_nTop); 323 } 324 } 325 326 /// @implemented 327 STDMETHODIMP_(void) CDefCompFrameWindow::OnCreate(HWND hWnd) 328 { 329 ::SetWindowTheme(hWnd, L"TASKBAR", NULL); 330 331 ZeroMemory(&m_Margins, sizeof(m_Margins)); 332 333 CUIFTheme theme; 334 theme.m_hTheme = NULL; 335 theme.m_iPartId = 1; 336 theme.m_iStateId = 0; 337 theme.m_pszClassList = L"TOOLBAR"; 338 if (SUCCEEDED(theme.InternalOpenThemeData(hWnd))) 339 GetThemeMargins(NULL, 1, 3602, NULL, &m_Margins); 340 } 341 342 /// @implemented 343 STDMETHODIMP_(BOOL) CDefCompFrameWindow::OnSetCursor(UINT uMsg, LONG x, LONG y) 344 { 345 if (!::IsWindow(m_hwndCompStr)) 346 return FALSE; 347 348 RECT rc; 349 ::GetWindowRect(m_hwndCompStr, &rc); 350 MyScreenToClient(NULL, &rc); 351 POINT pt = { x, y }; 352 return ::PtInRect(&rc, pt); 353 } 354 355 /// @implemented 356 STDMETHODIMP_(LRESULT) 357 CDefCompFrameWindow::OnWindowPosChanged(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 358 { 359 CicIMCLock imcLock(m_hIMC); 360 if (SUCCEEDED(imcLock.m_hr)) 361 ::SendMessage(imcLock.get().hWnd, WM_IME_NOTIFY, 0xF, (LPARAM)m_hIMC); 362 return ::DefWindowProc(hWnd, uMsg, wParam, lParam); 363 } 364 365 /// @implemented 366 STDMETHODIMP_(void) CDefCompFrameWindow::HandleMouseMsg(UINT uMsg, LONG x, LONG y) 367 { 368 if (::IsWindow(m_hwndCompStr)) 369 { 370 RECT rc; 371 ::GetWindowRect(m_hwndCompStr, &rc); 372 MyScreenToClient(NULL, &rc); 373 374 POINT pt = { x, y }; 375 if (::PtInRect(&rc, pt)) 376 ::SendMessage(m_hwndCompStr, 0x7E8, 0, 0); 377 } 378 379 CUIFWindow::HandleMouseMsg(uMsg, x, y); 380 } 381 382 /***********************************************************************/ 383 384 /// @implemented 385 POLYTEXTW *CPolyText::GetPolyAt(INT iItem) 386 { 387 return &m_PolyTextArray[iItem]; 388 } 389 390 /// @implemented 391 HRESULT CPolyText::ShiftPolyText(INT xDelta, INT yDelta) 392 { 393 for (size_t iItem = 0; iItem < m_PolyTextArray.size(); ++iItem) 394 { 395 POLYTEXTW *pPolyText = &m_PolyTextArray[iItem]; 396 pPolyText->x += xDelta; 397 pPolyText->y += yDelta; 398 ::OffsetRect((LPRECT)&pPolyText->rcl, xDelta, yDelta); 399 } 400 return S_OK; 401 } 402 403 /// @implemented 404 HRESULT CPolyText::RemoveLastLine(BOOL bHorizontal) 405 { 406 size_t iItem, cItems = m_PolyTextArray.size(); 407 if (!cItems) 408 return E_FAIL; 409 410 POLYTEXTW *pData1 = &m_PolyTextArray[cItems - 1]; 411 412 for (iItem = 0; iItem < cItems; ++iItem) 413 { 414 POLYTEXTW *pData2 = &m_PolyTextArray[iItem]; 415 if (bHorizontal) 416 { 417 if (pData1->x == pData2->x) 418 break; 419 } 420 else 421 { 422 if (pData1->y == pData2->y) 423 break; 424 } 425 } 426 427 if (iItem >= cItems) 428 return E_FAIL; 429 430 m_PolyTextArray.Remove(iItem, cItems - iItem); 431 m_ValueArray.Remove(iItem, cItems - iItem); 432 return S_OK; 433 } 434 435 /// @implemented 436 void CPolyText::RemoveAll() 437 { 438 m_PolyTextArray.clear(); 439 m_ValueArray.clear(); 440 } 441 442 /***********************************************************************/ 443 444 /// @implemented 445 void COMPWND::_ClientToScreen(LPRECT prc) 446 { 447 ::ClientToScreen(m_hWnd, (LPPOINT)prc); 448 ::ClientToScreen(m_hWnd, (LPPOINT)&prc->right); 449 } 450 451 /***********************************************************************/ 452 453 // For GetWindowLongPtr/SetWindowLongPtr 454 #define UICOMP_GWLP_INDEX 0 455 #define UICOMP_GWLP_SIZE (UICOMP_GWLP_INDEX + sizeof(INT)) 456 457 /// @unimplemented 458 UIComposition::UIComposition(HWND hwndParent) 459 { 460 } 461 462 /// @implemented 463 UIComposition::~UIComposition() 464 { 465 DestroyCompositionWindow(); 466 467 if (m_hFont1) 468 { 469 ::DeleteObject(m_hFont1); 470 m_hFont1 = NULL; 471 } 472 473 if (m_hFont2) 474 { 475 ::DeleteObject(m_hFont2); 476 m_hFont2 = NULL; 477 } 478 479 if (m_strCompStr) 480 { 481 cicMemFree(m_strCompStr); 482 m_strCompStr = NULL; 483 } 484 485 m_cchCompStr = 0; 486 } 487 488 // @implemented 489 BOOL UIComposition::SendMessageToUI(CicIMCLock& imcLock, WPARAM wParam, LPARAM lParam) 490 { 491 HWND hImeWnd = ImmGetDefaultIMEWnd(0); 492 if (!::IsWindow(hImeWnd)) 493 return TRUE; 494 TLS *pTLS = TLS::GetTLS(); 495 LRESULT ret; 496 if (pTLS && pTLS->m_cWnds > 1) 497 ret = ::SendMessage(imcLock.get().hWnd, WM_IME_NOTIFY, wParam, lParam); 498 else 499 ret = ::SendMessage(hImeWnd, WM_IME_NOTIFY, wParam, lParam); 500 return !ret; 501 } 502 503 /// @implemented 504 HRESULT UIComposition::CreateDefFrameWnd(HWND hwndParent, HIMC hIMC) 505 { 506 if (!m_pDefCompFrameWindow) 507 { 508 m_pDefCompFrameWindow = new(cicNoThrow) CDefCompFrameWindow(hIMC, 0x800000A4); 509 if (!m_pDefCompFrameWindow) 510 return E_OUTOFMEMORY; 511 if (!m_pDefCompFrameWindow->Initialize()) 512 { 513 delete m_pDefCompFrameWindow; 514 m_pDefCompFrameWindow = NULL; 515 return E_FAIL; 516 } 517 518 m_pDefCompFrameWindow->Init(); 519 } 520 521 m_pDefCompFrameWindow->CreateWnd(hwndParent); 522 return S_OK; 523 } 524 525 /// @implemented 526 HRESULT UIComposition::CreateCompButtonWnd(HWND hwndParent, HIMC hIMC) 527 { 528 TLS *pTLS = TLS::GetTLS(); 529 if (!pTLS || !pTLS->NonEACompositionEnabled()) 530 return S_OK; 531 532 if (IsEALang(0)) 533 { 534 if (m_pCompButtonFrameWindow) 535 { 536 delete m_pCompButtonFrameWindow; 537 m_pCompButtonFrameWindow = NULL; 538 } 539 return S_OK; 540 } 541 542 if (!m_pCompButtonFrameWindow) 543 { 544 m_pCompButtonFrameWindow = new(cicNoThrow) CCompButtonFrameWindow(hIMC, 0x800000B4); 545 if (!m_pCompButtonFrameWindow) 546 return E_OUTOFMEMORY; 547 548 if (!m_pCompButtonFrameWindow->Initialize()) 549 { 550 if (m_pCompButtonFrameWindow) 551 { 552 delete m_pCompButtonFrameWindow; 553 m_pCompButtonFrameWindow = NULL; 554 } 555 return E_FAIL; 556 } 557 558 m_pCompButtonFrameWindow->Init(); 559 } 560 561 m_pCompButtonFrameWindow->CreateWnd(hwndParent); 562 return S_OK; 563 } 564 565 /// @implemented 566 HRESULT UIComposition::CreateCompositionWindow(CicIMCLock& imcLock, HWND hwndParent) 567 { 568 if (FAILED(imcLock.m_hr)) 569 return imcLock.m_hr; 570 571 if (!::IsWindow(hwndParent) || m_bHasCompWnd) 572 return E_FAIL; 573 574 for (INT iCompStr = 0; iCompStr < 3; ++iCompStr) 575 { 576 DWORD style = WS_POPUP | WS_DISABLED; 577 HWND hwndCompStr = ::CreateWindowExW(0, L"MSCTFIME Composition", NULL, style, 578 0, 0, 0, 0, hwndParent, NULL, g_hInst, NULL); 579 m_CompStrs[iCompStr].m_hWnd = hwndCompStr; 580 ::SetWindowLongPtrW(hwndCompStr, GWLP_USERDATA, (LONG_PTR)this); 581 ::SetWindowLongPtrW(hwndCompStr, UICOMP_GWLP_INDEX, iCompStr); 582 m_CompStrs[iCompStr].m_Caret.CreateCaret(hwndCompStr, m_CaretSize); 583 } 584 585 HRESULT hr = CreateCompButtonWnd(hwndParent, imcLock.m_hIMC); 586 if (FAILED(hr)) 587 { 588 DestroyCompositionWindow(); 589 return E_OUTOFMEMORY; 590 } 591 592 hr = CreateDefFrameWnd(hwndParent, imcLock.m_hIMC); 593 if (FAILED(hr)) 594 { 595 DestroyCompositionWindow(); 596 return E_OUTOFMEMORY; 597 } 598 599 DWORD style = WS_CHILD | WS_DISABLED; 600 HWND hwndCompStr = ::CreateWindowExW(WS_EX_CLIENTEDGE, L"MSCTFIME Composition", NULL, style, 601 0, 0, 0, 0, *m_pDefCompFrameWindow, NULL, g_hInst, NULL); 602 if (!hwndCompStr) 603 { 604 DestroyCompositionWindow(); 605 return E_OUTOFMEMORY; 606 } 607 608 m_CompStrs[3].m_hWnd = hwndCompStr; 609 m_pDefCompFrameWindow->m_hwndCompStr = hwndCompStr; 610 ::SetWindowLongPtrW(hwndCompStr, GWLP_USERDATA, (LONG_PTR)this); 611 ::SetWindowLongPtrW(hwndCompStr, UICOMP_GWLP_INDEX, -1); 612 m_CompStrs[3].m_Caret.CreateCaret(hwndCompStr, m_CaretSize); 613 m_bHasCompWnd = TRUE; 614 615 return S_OK; 616 } 617 618 /// @implemented 619 HRESULT UIComposition::DestroyCompositionWindow() 620 { 621 for (INT i = 0; i < 4; ++i) 622 { 623 COMPWND *pCompStr = &m_CompStrs[i]; 624 pCompStr->m_Caret.DestroyCaret(); 625 if (::IsWindow(pCompStr->m_hWnd)) 626 { 627 DestroyWindow(pCompStr->m_hWnd); 628 pCompStr->m_PolyText.RemoveAll(); 629 } 630 pCompStr->m_hWnd = NULL; 631 } 632 633 if (m_pCompButtonFrameWindow) 634 { 635 ::DestroyWindow(*m_pCompButtonFrameWindow); 636 delete m_pCompButtonFrameWindow; 637 m_pCompButtonFrameWindow = NULL; 638 } 639 640 if (m_pDefCompFrameWindow) 641 { 642 ::DestroyWindow(*m_pDefCompFrameWindow); 643 delete m_pDefCompFrameWindow; 644 m_pDefCompFrameWindow = NULL; 645 } 646 647 return 0; 648 } 649 650 // @implemented 651 BOOL UIComposition::InquireImeUIWndState(CicIMCLock& imcLock) 652 { 653 BOOL bValue = FALSE; 654 UIComposition::SendMessageToUI(imcLock, 0x11u, (LPARAM)&bValue); 655 return bValue; 656 } 657 658 /// @implemented 659 HRESULT UIComposition::UpdateShowCompWndFlag(CicIMCLock& imcLock, DWORD *pdwCompStrLen) 660 { 661 if (FAILED(imcLock.m_hr)) 662 return imcLock.m_hr; 663 if (!::IsWindow(imcLock.get().hWnd)) 664 return E_FAIL; 665 666 CicIMCCLock<COMPOSITIONSTRING> compStr(imcLock.get().hCompStr); 667 if (FAILED(compStr.m_hr)) 668 return compStr.m_hr; 669 670 if ((m_dwUnknown56[0] & 0x80000000) && compStr.get().dwCompStrLen) 671 m_bHasCompStr = TRUE; 672 else 673 m_bHasCompStr = FALSE; 674 675 if (pdwCompStrLen) 676 *pdwCompStrLen = compStr.get().dwCompStrLen; 677 678 return S_OK; 679 } 680 681 /// @implemented 682 HRESULT UIComposition::UpdateFont(CicIMCLock& imcLock) 683 { 684 if (FAILED(imcLock.m_hr)) 685 return imcLock.m_hr; 686 687 if (m_hFont1) 688 ::DeleteObject(m_hFont1); 689 if (m_hFont2) 690 ::DeleteObject(m_hFont2); 691 692 LOGFONTW lf = imcLock.get().lfFont.W; 693 m_hFont2 = ::CreateFontIndirectW(&lf); 694 695 lf.lfEscapement = 0; 696 lf.lfOrientation = 0; 697 BOOL bVertical = (lf.lfFaceName[0] == L'@'); 698 if (bVertical) 699 { 700 MoveMemory(lf.lfFaceName, &lf.lfFaceName[1], sizeof(lf.lfFaceName) - sizeof(WCHAR)); 701 lf.lfFaceName[_countof(lf.lfFaceName) - 1] = UNICODE_NULL; 702 } 703 m_hFont1 = ::CreateFontIndirectW(&lf); 704 705 return S_OK; 706 } 707 708 // @implemented 709 void UIComposition::OnTimer(HWND hWnd) 710 { 711 INT iCompStr = (INT)::GetWindowLongPtrW(hWnd, UICOMP_GWLP_INDEX); 712 if (iCompStr == -1) 713 m_CompStrs[3].m_Caret.OnTimer(); 714 else 715 m_CompStrs[iCompStr].m_Caret.OnTimer(); 716 } 717 718 /// @implemented 719 BOOL UIComposition::GetImeUIWndTextExtent(CicIMCLock& imcLock, LPARAM lParam) 720 { 721 return !UIComposition::SendMessageToUI(imcLock, 0x14, lParam); 722 } 723 724 /// @implemented 725 LPWSTR UIComposition::GetCompStrBuffer(INT cchStr) 726 { 727 if (!m_strCompStr) 728 { 729 m_strCompStr = (LPWSTR)cicMemAllocClear((cchStr + 1) * sizeof(WCHAR)); 730 m_cchCompStr = cchStr; 731 } 732 if (m_cchCompStr < cchStr) 733 { 734 m_strCompStr = (LPWSTR)cicMemReAlloc(m_strCompStr, (cchStr + 1) * sizeof(WCHAR)); 735 m_cchCompStr = cchStr; 736 } 737 return m_strCompStr; 738 } 739 740 /// @unimplemented 741 void UIComposition::OnImeStartComposition(CicIMCLock& imcLock, HWND hUIWnd) 742 { 743 //FIXME 744 } 745 746 /// @implemented 747 HRESULT UIComposition::OnImeCompositionUpdate(CicIMCLock& imcLock) 748 { 749 m_dwUnknown56[0] |= 0x8000; 750 return UIComposition::UpdateShowCompWndFlag(imcLock, NULL); 751 } 752 753 /// @unimplemented 754 HRESULT UIComposition::OnImeEndComposition() 755 { 756 m_dwUnknown56[0] = 0; 757 return DestroyCompositionWindow(); 758 } 759 760 /// @unimplemented 761 void UIComposition::OnImeSetContext(CicIMCLock& imcLock, HWND hUIWnd, WPARAM wParam, LPARAM lParam) 762 { 763 //FIXME 764 } 765 766 /// @unimplemented 767 void UIComposition::OnPaintTheme(WPARAM wParam) 768 { 769 //FIXME 770 } 771 772 /// @implemented 773 HRESULT UIComposition::OnDestroy() 774 { 775 return DestroyCompositionWindow(); 776 } 777 778 /// @unimplemented 779 LRESULT CALLBACK 780 UIComposition::CompWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 781 { 782 if (uMsg == WM_CREATE) 783 return -1; // FIXME 784 return 0; 785 } 786 787 /// @implemented 788 HRESULT UIComposition::OnImeNotifySetCompositionWindow(CicIMCLock& imcLock) 789 { 790 return UpdateCompositionRect(imcLock); 791 } 792 793 /// @unimplemented 794 HRESULT UIComposition::UpdateCompositionRect(CicIMCLock& imcLock) 795 { 796 return E_NOTIMPL; 797 } 798 799 /// @implemented 800 INT UIComposition::GetLevelFromIMC(CicIMCLock& imcLock) 801 { 802 DWORD dwStyle = imcLock.get().cfCompForm.dwStyle; 803 if (dwStyle == CFS_DEFAULT) 804 return 1; 805 if (!(dwStyle & (CFS_FORCE_POSITION | CFS_POINT | CFS_RECT))) 806 return 0; 807 808 RECT rc; 809 ::GetClientRect(imcLock.get().hWnd, &rc); 810 if (!::PtInRect(&rc, imcLock.get().cfCompForm.ptCurrentPos)) 811 return 1; 812 813 INPUTCONTEXT *pIC = &imcLock.get(); 814 if ((pIC->cfCompForm.dwStyle & CFS_RECT) && 815 (pIC->cfCompForm.rcArea.top == pIC->cfCompForm.rcArea.bottom) && 816 (pIC->cfCompForm.rcArea.left == pIC->cfCompForm.rcArea.right)) 817 { 818 return 1; 819 } 820 821 return 2; 822 } 823 824 /// @implemented 825 HRESULT UIComposition::OnImeSetContextAfter(CicIMCLock& imcLock) 826 { 827 if ((!m_pDefCompFrameWindow || !::IsWindow(*m_pDefCompFrameWindow)) && !::IsWindow(m_CompStrs[0].m_hWnd)) 828 { 829 m_dwUnknown56[0] &= ~0x8000; 830 return S_OK; 831 } 832 833 if (FAILED(imcLock.m_hr)) 834 return imcLock.m_hr; 835 836 INT Level = GetLevelFromIMC(imcLock); 837 if ((Level == 1 || Level == 2) && (m_dwUnknown56[0] & 0x80000000) && m_dwUnknown56[1]) 838 { 839 DWORD dwCompStrLen = 0; 840 UpdateShowCompWndFlag(imcLock, &dwCompStrLen); 841 842 if (Level == 1) 843 { 844 ::ShowWindow(*m_pDefCompFrameWindow, (m_bHasCompStr ? SW_SHOWNOACTIVATE : SW_HIDE)); 845 } 846 else if (Level == 2 && !m_bHasCompStr && dwCompStrLen) 847 { 848 for (INT iCompStr = 0; iCompStr < 3; ++iCompStr) 849 { 850 m_CompStrs[iCompStr].m_Caret.HideCaret(); 851 ::ShowWindow(m_CompStrs[iCompStr].m_Caret, SW_HIDE); 852 } 853 } 854 } 855 else 856 { 857 ::ShowWindow(*m_pDefCompFrameWindow, SW_HIDE); 858 859 for (INT iCompStr = 0; iCompStr < 3; ++iCompStr) 860 { 861 m_CompStrs[iCompStr].m_Caret.HideCaret(); 862 ::ShowWindow(m_CompStrs[iCompStr].m_Caret, SW_HIDE); 863 } 864 } 865 866 return S_OK; 867 } 868 869 /***********************************************************************/ 870 871 // For GetWindowLongPtr/SetWindowLongPtr 872 #define UI_GWLP_HIMC 0 873 #define UI_GWLP_UI sizeof(HIMC) 874 #define UI_GWLP_SIZE (UI_GWLP_UI + sizeof(UI*)) 875 876 /// @implemented 877 UI::UI(HWND hWnd) : m_hWnd(hWnd) 878 { 879 } 880 881 /// @implemented 882 UI::~UI() 883 { 884 delete m_pComp; 885 } 886 887 /// @implemented 888 HRESULT UI::_Create() 889 { 890 m_pComp = new(cicNoThrow) UIComposition(m_hWnd); 891 if (!m_pComp) 892 return E_OUTOFMEMORY; 893 894 ::SetWindowLongPtrW(m_hWnd, UI_GWLP_UI, (LONG_PTR)this); 895 return S_OK; 896 } 897 898 /// @implemented 899 void UI::_Destroy() 900 { 901 m_pComp->OnDestroy(); 902 ::SetWindowLongPtrW(m_hWnd, UI_GWLP_UI, 0); 903 } 904 905 /// @implemented 906 void UI::OnCreate(HWND hWnd) 907 { 908 UI *pUI = (UI*)::GetWindowLongPtrW(hWnd, UI_GWLP_UI); 909 if (pUI) 910 return; 911 pUI = new(cicNoThrow) UI(hWnd); 912 if (pUI) 913 pUI->_Create(); 914 } 915 916 /// @implemented 917 void UI::OnDestroy(HWND hWnd) 918 { 919 UI *pUI = (UI*)::GetWindowLongPtrW(hWnd, UI_GWLP_UI); 920 if (!pUI) 921 return; 922 923 pUI->_Destroy(); 924 delete pUI; 925 } 926 927 /// @implemented 928 void UI::OnImeSetContext(CicIMCLock& imcLock, WPARAM wParam, LPARAM lParam) 929 { 930 m_pComp->OnImeSetContext(imcLock, m_hWnd, wParam, lParam); 931 } 932 933 /***********************************************************************/ 934 935 struct CIMEUIWindowHandler 936 { 937 static LRESULT CALLBACK ImeUIMsImeHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 938 static HRESULT CALLBACK ImeUIMsImeMouseHandler(HWND hWnd, WPARAM wParam, LPARAM lParam); 939 static LRESULT CALLBACK ImeUIMsImeModeBiasHandler(HWND hWnd, WPARAM wParam, LPARAM lParam); 940 static LRESULT CALLBACK ImeUIMsImeReconvertRequest(HWND hWnd, WPARAM wParam, LPARAM lParam); 941 static LRESULT CALLBACK ImeUIWndProcWorker(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 942 static HRESULT CALLBACK ImeUIDelayedReconvertFuncCall(HWND hWnd); 943 static HRESULT CALLBACK ImeUIOnLayoutChange(LPARAM lParam); 944 static HRESULT CALLBACK ImeUIPrivateHandler(UINT uMsg, WPARAM wParam, LPARAM lParam); 945 static LRESULT CALLBACK ImeUINotifyHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 946 }; 947 948 /// @implemented 949 HRESULT CALLBACK 950 CIMEUIWindowHandler::ImeUIMsImeMouseHandler(HWND hWnd, WPARAM wParam, LPARAM lParam) 951 { 952 if ((BYTE)wParam == 0xFF) 953 return TRUE; 954 955 CicIMCLock imcLock((HIMC)lParam); 956 if (FAILED(imcLock.m_hr)) 957 return imcLock.m_hr; 958 959 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); 960 if (FAILED(imeContext.m_hr)) 961 return FALSE; 962 963 HRESULT hr = E_FAIL; 964 CicInputContext *pCicIC = imeContext.get().m_pCicIC; 965 if (pCicIC) 966 { 967 UINT keys = 0; 968 if (wParam & MK_LBUTTON) 969 keys |= 0x1; 970 if (wParam & MK_SHIFT) 971 keys |= 0x10; 972 if (wParam & MK_RBUTTON) 973 keys |= 0x2; 974 if (wParam & MK_MBUTTON) 975 keys |= 0x780000; 976 else if (wParam & MK_ALT) 977 keys |= 0xFF880000; 978 hr = pCicIC->MsImeMouseHandler(HIWORD(wParam), HIBYTE(LOWORD(wParam)), keys, imcLock); 979 } 980 981 return hr; 982 } 983 984 /// @implemented 985 HRESULT CALLBACK CIMEUIWindowHandler::ImeUIOnLayoutChange(LPARAM lParam) 986 { 987 CicIMCLock imcLock((HIMC)lParam); 988 if (FAILED(imcLock.m_hr)) 989 return S_OK; 990 991 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); 992 if (FAILED(imeContext.m_hr)) 993 return S_OK; 994 995 CicInputContext *pCicIC = imeContext.get().m_pCicIC; 996 if (pCicIC) 997 { 998 auto pContextOwnerServices = pCicIC->m_pContextOwnerServices; 999 pContextOwnerServices->AddRef(); 1000 pContextOwnerServices->OnLayoutChange(); 1001 pContextOwnerServices->Release(); 1002 } 1003 1004 return S_OK; 1005 } 1006 1007 /// @implemented 1008 HRESULT CALLBACK 1009 CIMEUIWindowHandler::ImeUIPrivateHandler(UINT uMsg, WPARAM wParam, LPARAM lParam) 1010 { 1011 CicIMCLock imcLock((HIMC)lParam); 1012 if (FAILED(imcLock.m_hr)) 1013 return imcLock.m_hr; 1014 1015 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); 1016 if (FAILED(imeContext.m_hr)) 1017 return imeContext.m_hr; 1018 1019 CicInputContext *pCicIC = imeContext.get().m_pCicIC; 1020 if (pCicIC && wParam == 0x10) 1021 pCicIC->EscbClearDocFeedBuffer(imcLock, TRUE); 1022 1023 return S_OK; 1024 } 1025 1026 /// @implemented 1027 LRESULT CALLBACK 1028 CIMEUIWindowHandler::ImeUIMsImeModeBiasHandler(HWND hWnd, WPARAM wParam, LPARAM lParam) 1029 { 1030 if (!wParam) 1031 return TRUE; 1032 1033 CicIMCLock imcLock((HIMC)lParam); 1034 if (FAILED(imcLock.m_hr)) 1035 return imcLock.m_hr; 1036 1037 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); 1038 if (FAILED(imeContext.m_hr)) 1039 return FALSE; 1040 1041 CicInputContext *pCicIC = imeContext.get().m_pCicIC; 1042 if (!pCicIC) 1043 return FALSE; 1044 1045 if (wParam == 1) 1046 { 1047 if (lParam == 0 || lParam == 1 || lParam == 4 || lParam == 0x10000) 1048 { 1049 GUID guid = pCicIC->m_ModeBias.ConvertModeBias((DWORD)lParam); 1050 pCicIC->m_ModeBias.SetModeBias(guid); 1051 1052 pCicIC->m_dwUnknown7[2] |= 1; 1053 pCicIC->m_pContextOwnerServices->AddRef(); 1054 pCicIC->m_pContextOwnerServices->OnAttributeChange(GUID_PROP_MODEBIAS); 1055 pCicIC->m_pContextOwnerServices->Release(); 1056 return TRUE; 1057 } 1058 } 1059 else if (wParam == 2) 1060 { 1061 return pCicIC->m_ModeBias.ConvertModeBias(pCicIC->m_ModeBias.m_guid); 1062 } 1063 1064 return FALSE; 1065 } 1066 1067 /// @implemented 1068 LRESULT CALLBACK 1069 CIMEUIWindowHandler::ImeUIMsImeReconvertRequest(HWND hWnd, WPARAM wParam, LPARAM lParam) 1070 { 1071 if (wParam == 0x10000000) 1072 return TRUE; 1073 1074 HIMC hIMC = (HIMC)::GetWindowLongPtrW(hWnd, UI_GWLP_HIMC); 1075 CicIMCLock imcLock(hIMC); 1076 if (FAILED(imcLock.m_hr)) 1077 return FALSE; 1078 1079 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); 1080 if (FAILED(imeContext.m_hr)) 1081 return FALSE; 1082 1083 CicInputContext *pCicIC = imeContext.get().m_pCicIC; 1084 TLS *pTLS = TLS::GetTLS(); 1085 if (!pCicIC || !pTLS) 1086 return FALSE; 1087 1088 auto pThreadMgr = pTLS->m_pThreadMgr; 1089 auto pProfile = pTLS->m_pProfile; 1090 if (!pThreadMgr || !pProfile) 1091 return FALSE; 1092 1093 UINT uCodePage = 0; 1094 pProfile->GetCodePageA(&uCodePage); 1095 pCicIC->SetupReconvertString(imcLock, pThreadMgr, uCodePage, WM_MSIME_RECONVERT, FALSE); 1096 pCicIC->EndReconvertString(imcLock); 1097 return TRUE; 1098 } 1099 1100 /// @implemented 1101 LRESULT CALLBACK 1102 CIMEUIWindowHandler::ImeUIMsImeHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 1103 { 1104 if (uMsg == WM_MSIME_MOUSE) 1105 return ImeUIMsImeMouseHandler(hWnd, wParam, lParam); 1106 if (uMsg == WM_MSIME_MODEBIAS) 1107 return ImeUIMsImeModeBiasHandler(hWnd, wParam, lParam); 1108 if (uMsg == WM_MSIME_RECONVERTREQUEST) 1109 return ImeUIMsImeReconvertRequest(hWnd, wParam, lParam); 1110 if (uMsg == WM_MSIME_SERVICE) 1111 { 1112 TLS *pTLS = TLS::GetTLS(); 1113 if (pTLS && pTLS->m_pProfile) 1114 { 1115 LANGID LangID; 1116 pTLS->m_pProfile->GetLangId(&LangID); 1117 if (PRIMARYLANGID(LangID) == LANG_KOREAN) 1118 return FALSE; 1119 } 1120 return TRUE; 1121 } 1122 return 0; 1123 } 1124 1125 /// @implemented 1126 HRESULT CALLBACK 1127 CIMEUIWindowHandler::ImeUIDelayedReconvertFuncCall(HWND hWnd) 1128 { 1129 HIMC hIMC = (HIMC)::GetWindowLongPtrW(hWnd, UI_GWLP_HIMC); 1130 CicIMCLock imcLock(hIMC); 1131 if (FAILED(imcLock.m_hr)) 1132 return imcLock.m_hr; 1133 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); 1134 if (FAILED(imeContext.m_hr)) 1135 return imeContext.m_hr; 1136 CicInputContext *pCicIC = imeContext.get().m_pCicIC; 1137 if (pCicIC) 1138 pCicIC->DelayedReconvertFuncCall(imcLock); 1139 return S_OK; 1140 } 1141 1142 /// @unimplemented 1143 LRESULT CALLBACK 1144 CIMEUIWindowHandler::ImeUINotifyHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 1145 { 1146 HIMC hIMC = (HIMC)::GetWindowLongPtrW(hWnd, UI_GWLP_HIMC); 1147 CicIMCLock imcLock(hIMC); 1148 if (FAILED(imcLock.m_hr)) 1149 return imcLock.m_hr; 1150 CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); 1151 if (FAILED(imeContext.m_hr)) 1152 return imeContext.m_hr; 1153 1154 CicInputContext *pCicIC = imeContext.get().m_pCicIC; 1155 if (pCicIC) 1156 { 1157 switch (wParam) 1158 { 1159 case IMN_CLOSECANDIDATE: 1160 { 1161 pCicIC->m_bCandidateOpen = FALSE; 1162 HWND hImeWnd = ::ImmGetDefaultIMEWnd(NULL); 1163 if (::IsWindow(hImeWnd)) 1164 ::PostMessage(hImeWnd, WM_IME_NOTIFY, 0x10, (LPARAM)hIMC); 1165 break; 1166 } 1167 case IMN_OPENCANDIDATE: 1168 { 1169 pCicIC->m_bCandidateOpen = TRUE; 1170 pCicIC->ClearPrevCandidatePos(); 1171 break; 1172 } 1173 case IMN_SETCANDIDATEPOS: 1174 { 1175 //FIXME 1176 break; 1177 } 1178 case IMN_SETCOMPOSITIONFONT: 1179 { 1180 //FIXME 1181 break; 1182 } 1183 case IMN_SETCOMPOSITIONWINDOW: 1184 { 1185 //FIXME 1186 break; 1187 } 1188 case 0xF: 1189 { 1190 CIMEUIWindowHandler::ImeUIOnLayoutChange(lParam); 1191 break; 1192 } 1193 case 0x10: 1194 { 1195 CIMEUIWindowHandler::ImeUIPrivateHandler(uMsg, 0x10, lParam); 1196 break; 1197 } 1198 case 0x13: 1199 { 1200 CIMEUIWindowHandler::ImeUIOnLayoutChange(lParam); 1201 break; 1202 } 1203 case 0x14: 1204 { 1205 //FIXME 1206 break; 1207 } 1208 case 0x16: 1209 { 1210 ::SetTimer(hWnd, 2, 100, NULL); 1211 break; 1212 } 1213 case 0x17: 1214 { 1215 return (LRESULT)hWnd; 1216 } 1217 case 0x10D: 1218 { 1219 //FIXME 1220 break; 1221 } 1222 case 0x10E: 1223 pCicIC->m_dwQueryPos = 0; 1224 break; 1225 } 1226 } 1227 1228 return 0; 1229 } 1230 1231 /// @implemented 1232 LRESULT CALLBACK 1233 CIMEUIWindowHandler::ImeUIWndProcWorker(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 1234 { 1235 TLS *pTLS = TLS::GetTLS(); 1236 if (pTLS && (pTLS->m_dwSystemInfoFlags & IME_SYSINFO_WINLOGON)) 1237 { 1238 if (uMsg == WM_CREATE) 1239 return -1; 1240 return ::DefWindowProcW(hWnd, uMsg, wParam, lParam); 1241 } 1242 1243 switch (uMsg) 1244 { 1245 case WM_CREATE: 1246 { 1247 UI::OnCreate(hWnd); 1248 break; 1249 } 1250 case WM_DESTROY: 1251 case WM_ENDSESSION: 1252 { 1253 UI::OnDestroy(hWnd); 1254 break; 1255 } 1256 case WM_IME_STARTCOMPOSITION: 1257 case WM_IME_COMPOSITION: 1258 case WM_IME_ENDCOMPOSITION: 1259 case WM_IME_SETCONTEXT: 1260 case WM_IME_NOTIFY: 1261 case WM_IME_SELECT: 1262 case WM_TIMER: 1263 { 1264 HIMC hIMC = (HIMC)GetWindowLongPtrW(hWnd, UI_GWLP_HIMC); 1265 UI* pUI = (UI*)GetWindowLongPtrW(hWnd, UI_GWLP_UI); 1266 CicIMCLock imcLock(hIMC); 1267 switch (uMsg) 1268 { 1269 case WM_IME_STARTCOMPOSITION: 1270 { 1271 pUI->m_pComp->OnImeStartComposition(imcLock, pUI->m_hWnd); 1272 break; 1273 } 1274 case WM_IME_COMPOSITION: 1275 { 1276 if (lParam & GCS_COMPSTR) 1277 { 1278 pUI->m_pComp->OnImeCompositionUpdate(imcLock); 1279 ::SetTimer(hWnd, 0, 10, NULL); 1280 pUI->m_pComp->m_bInComposition = TRUE; 1281 } 1282 break; 1283 } 1284 case WM_IME_ENDCOMPOSITION: 1285 { 1286 ::KillTimer(hWnd, 0); 1287 pUI->m_pComp->OnImeEndComposition(); 1288 break; 1289 } 1290 case WM_IME_SETCONTEXT: 1291 { 1292 pUI->OnImeSetContext(imcLock, wParam, lParam); 1293 ::KillTimer(hWnd, 1); 1294 ::SetTimer(hWnd, 1, 300, NULL); 1295 break; 1296 } 1297 case WM_TIMER: 1298 { 1299 switch (wParam) 1300 { 1301 case 0: 1302 ::KillTimer(hWnd, wParam); 1303 pUI->m_pComp->m_bInComposition = FALSE; 1304 pUI->m_pComp->OnImeNotifySetCompositionWindow(imcLock); 1305 break; 1306 case 1: 1307 ::KillTimer(hWnd, wParam); 1308 pUI->m_pComp->OnImeSetContextAfter(imcLock); 1309 break; 1310 case 2: 1311 ::KillTimer(hWnd, wParam); 1312 CIMEUIWindowHandler::ImeUIDelayedReconvertFuncCall(hWnd); 1313 break; 1314 default: 1315 break; 1316 } 1317 break; 1318 } 1319 case WM_IME_NOTIFY: 1320 case WM_IME_SELECT: 1321 default: 1322 { 1323 pUI->m_pComp->OnPaintTheme(wParam); 1324 break; 1325 } 1326 } 1327 break; 1328 } 1329 default: 1330 { 1331 if (IsMsImeMessage(uMsg)) 1332 return CIMEUIWindowHandler::ImeUIMsImeHandler(hWnd, uMsg, wParam, lParam); 1333 return ::DefWindowProcW(hWnd, uMsg, wParam, lParam); 1334 } 1335 } 1336 1337 return 0; 1338 } 1339 1340 /***********************************************************************/ 1341 1342 /// @implemented 1343 EXTERN_C LRESULT CALLBACK 1344 UIWndProc( 1345 _In_ HWND hWnd, 1346 _In_ UINT uMsg, 1347 _In_ WPARAM wParam, 1348 _In_ LPARAM lParam) 1349 { 1350 return CIMEUIWindowHandler::ImeUIWndProcWorker(hWnd, uMsg, wParam, lParam); 1351 } 1352 1353 /***********************************************************************/ 1354 1355 /// @implemented 1356 BOOL RegisterImeClass(VOID) 1357 { 1358 WNDCLASSEXW wcx; 1359 1360 if (!GetClassInfoExW(g_hInst, L"MSCTFIME UI", &wcx)) 1361 { 1362 ZeroMemory(&wcx, sizeof(wcx)); 1363 wcx.cbSize = sizeof(WNDCLASSEXW); 1364 wcx.cbWndExtra = UI_GWLP_SIZE; 1365 wcx.hIcon = LoadIconW(0, (LPCWSTR)IDC_ARROW); 1366 wcx.hInstance = g_hInst; 1367 wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); 1368 wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); 1369 wcx.style = CS_IME | CS_GLOBALCLASS; 1370 wcx.lpfnWndProc = UIWndProc; 1371 wcx.lpszClassName = L"MSCTFIME UI"; 1372 if (!RegisterClassExW(&wcx)) 1373 return FALSE; 1374 } 1375 1376 if (!GetClassInfoExW(g_hInst, L"MSCTFIME Composition", &wcx)) 1377 { 1378 ZeroMemory(&wcx, sizeof(wcx)); 1379 wcx.cbSize = sizeof(WNDCLASSEXW); 1380 wcx.cbWndExtra = UICOMP_GWLP_SIZE; 1381 wcx.hIcon = NULL; 1382 wcx.hInstance = g_hInst; 1383 wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_IBEAM); 1384 wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); 1385 wcx.style = CS_IME | CS_HREDRAW | CS_VREDRAW; 1386 wcx.lpfnWndProc = UIComposition::CompWndProc; 1387 wcx.lpszClassName = L"MSCTFIME Composition"; 1388 if (!RegisterClassExW(&wcx)) 1389 return FALSE; 1390 } 1391 1392 return TRUE; 1393 } 1394 1395 /// @implemented 1396 VOID UnregisterImeClass(VOID) 1397 { 1398 WNDCLASSEXW wcx; 1399 1400 GetClassInfoExW(g_hInst, L"MSCTFIME UI", &wcx); 1401 UnregisterClassW(L"MSCTFIME UI", g_hInst); 1402 DestroyIcon(wcx.hIcon); 1403 DestroyIcon(wcx.hIconSm); 1404 1405 GetClassInfoExW(g_hInst, L"MSCTFIME Composition", &wcx); 1406 UnregisterClassW(L"MSCTFIME Composition", g_hInst); 1407 DestroyIcon(wcx.hIcon); 1408 DestroyIcon(wcx.hIconSm); 1409 } 1410