📄 candui.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include <windows.h>
#include <imm.h>
#include "uipriv.h"
#include "sipapi.h"
/**********************************************************************/
/* SetScrBarInfo() */
/**********************************************************************/
void SetScrBarInfo(HWND hScrBar, int nMin, int nMax, UINT nPage, int nPos)
{
SCROLLINFO si;
si.cbSize= sizeof(SCROLLINFO);
si.fMask= SIF_PAGE | SIF_POS | SIF_RANGE;
si.nMin = nMin;
si.nMax = nMax;
si.nPage= nPage;
si.nPos = nPos;
SetScrollInfo(hScrBar, SB_CTL, &si, TRUE);
return;
}
BOOL IsSIPOn()
{
SIPINFO sSipInfo;
sSipInfo.cbSize = sizeof(SIPINFO);
sSipInfo.dwImDataSize = 0;
sSipInfo.pvImData = NULL;
if (SipGetInfo(&sSipInfo) && (sSipInfo.fdwFlags & SIPF_ON))
return TRUE;
return FALSE;
}
/**********************************************************************/
/* CalcCandSize() */
/**********************************************************************/
void CalcCandSize(HWND hCandWnd)
{
LPUIPRIV lpUIPriv;
lpUIPriv = (LPUIPRIV)GetWindowLong(hCandWnd, IMMGWL_PRIVATE);
if (g_sImeUIG.bAutoCandAccel && IsSIPOn()) {
g_sImeUIG.nCandLineWi = g_sImeUIG.nCandCharWi + CAND_TEXTMARGIN * 2;
lpUIPriv->rcCandText.left = 0;
}
else {
g_sImeUIG.nCandLineWi = g_sImeUIG.nCandCharWi*2 + CAND_TEXTMARGIN * 2;
lpUIPriv->rcCandText.left = g_sImeUIG.nCandCharWi;
}
lpUIPriv->rcCandText.bottom = g_sImeUIG.nCandDy[lpUIPriv->lpCandList->dwPageSize];
lpUIPriv->rcFraction.top = lpUIPriv->rcCandText.bottom;
lpUIPriv->rcFraction.bottom = lpUIPriv->rcFraction.top + lpUIPriv->nFracHi;
if (lpUIPriv->lpCandList->dwCount > lpUIPriv->lpCandList->dwPageSize) {
// This means we need scroll bar in candidate window
lpUIPriv->fdwUIFlags |= UI_CAND_DO_SCROLL;
SetScrBarInfo(lpUIPriv->hScrBar, 0, lpUIPriv->lpCandList->dwCount - 1,
lpUIPriv->lpCandList->dwPageSize,
lpUIPriv->lpCandList->dwPageStart);
if (g_sImeUIG.nCandLineWi + g_sImeUIG.cxVScroll < lpUIPriv->nFracWi) {
lpUIPriv->rcCandText.right = lpUIPriv->nFracWi - g_sImeUIG.cxVScroll;
g_sImeUIG.nCandDx = (lpUIPriv->rcCandText.right - lpUIPriv->rcCandText.left -
- g_sImeUIG.nCandCharWi) / 2 + ((g_sImeUIG.bAutoCandAccel && IsSIPOn()) ? 0 : g_sImeUIG.nCandCharWi);
lpUIPriv->rcFraction.right = lpUIPriv->nFracWi;
} else {
lpUIPriv->rcCandText.right = g_sImeUIG.nCandLineWi;
g_sImeUIG.nCandDx = CAND_TEXTMARGIN + ((g_sImeUIG.bAutoCandAccel && IsSIPOn()) ? 0 : g_sImeUIG.nCandCharWi);
lpUIPriv->rcFraction.right = g_sImeUIG.nCandLineWi + g_sImeUIG.cxVScroll;
}
lpUIPriv->nCandWi = lpUIPriv->rcFraction.right + g_sImeUIG.cxBorder * 2;
} else {
// We don't need scroll bar here
lpUIPriv->fdwUIFlags &= ~(UI_CAND_DO_SCROLL);
if (g_sImeUIG.nCandLineWi < lpUIPriv->nFracWi) {
lpUIPriv->rcCandText.right = lpUIPriv->nFracWi;
g_sImeUIG.nCandDx = (lpUIPriv->nFracWi-g_sImeUIG.nCandCharWi) / 2 + ((g_sImeUIG.bAutoCandAccel && IsSIPOn()) ? 0 : g_sImeUIG.nCandCharWi);
lpUIPriv->rcFraction.right = lpUIPriv->nFracWi;
} else {
lpUIPriv->rcCandText.right = g_sImeUIG.nCandLineWi;
g_sImeUIG.nCandDx = CAND_TEXTMARGIN + ((g_sImeUIG.bAutoCandAccel && IsSIPOn()) ? 0 : g_sImeUIG.nCandCharWi);
lpUIPriv->rcFraction.right = g_sImeUIG.nCandLineWi;
}
lpUIPriv->nCandWi = lpUIPriv->rcFraction.right + g_sImeUIG.cxBorder * 2;
}
RETAILMSG(1,(TEXT("g_sImeUIG.nCandDx = %d\n"), g_sImeUIG.nCandDx));
lpUIPriv->nCandHi = lpUIPriv->rcFraction.bottom + g_sImeUIG.cyBorder * 2;
return;
}
// to avoid SIP region
BOOL CheckRectForSIP(LPRECT lprcRect)
{
SIPINFO sSipInfo;
RECT rcScr;
RECT rcTmp1, rcTmp2;
sSipInfo.cbSize = sizeof(SIPINFO);
sSipInfo.dwImDataSize = 0;
sSipInfo.pvImData = NULL;
if (SipGetInfo(&sSipInfo)) {
if (!SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScr, 0))
return FALSE;
// SIP can have minus coordinate. so let's get real display position
if (!IntersectRect(&rcTmp1, &sSipInfo.rcSipRect, &rcScr))
return FALSE;
// now check the given RECT is overlapped with SIP
if (!IntersectRect(&rcTmp2, lprcRect, &rcTmp1))
return FALSE;
// now they are overlapped.
// but need to check that SIP is higher than the given rect.
// if it is, there is no meaning to change candidate list position.
if (rcTmp2.top > sSipInfo.rcSipRect.top)
return FALSE;
return TRUE;
}
return FALSE;
}
/**********************************************************************/
/* AdjustCandWnd() */
/**********************************************************************/
void AdjustCandWnd(HWND hCandWnd, POINT ptNew)
{
LPUIPRIV lpUIPriv;
int nAvailTextHi;
DWORD dwPageSize; // Available page size
RECT rect;
BOOL bSipOverlapped=FALSE;
lpUIPriv = (LPUIPRIV)GetWindowLong(hCandWnd, IMMGWL_PRIVATE);
if (!lpUIPriv->lpCandList) {
return;
}
ptNew.x = ptNew.x < 0 ? 0 : ptNew.x;
ptNew.y = ptNew.y < 0 ? 0 : ptNew.y;
nAvailTextHi = g_sImeUIG.rcWorkArea.bottom - ptNew.y
- lpUIPriv->nFracHi - g_sImeUIG.cyBorder * 2;
nAvailTextHi = nAvailTextHi < 0 ? 0 : nAvailTextHi;
rect.left = ptNew.x;
rect.top = ptNew.y;
rect.right = ptNew.x + g_sImeUIG.nCandLineWi;
rect.bottom = ptNew.y + g_sImeUIG.nCandLineHi*lpUIPriv->dwPageSize + lpUIPriv->nFracHi + g_sImeUIG.cyBorder * 2;
bSipOverlapped = CheckRectForSIP(&rect);
dwPageSize = (DWORD)nAvailTextHi / g_sImeUIG.nCandLineHi;
if ((dwPageSize >= lpUIPriv->dwPageSize) && !bSipOverlapped) {
dwPageSize = lpUIPriv->dwPageSize;
} else if ((dwPageSize >= MIN_PAGESIZE) && !bSipOverlapped) {
dwPageSize = MIN_PAGESIZE;
} else {
#if 1 // Use new way to calculate candidate window position.
// We will calculate the space above composition window and
// try to meet MIN_PAGESIZE.
// If there is still not enough space, candidate window will
// locate above the composition window.
// * bug 4251.
nAvailTextHi = ptNew.y - lpUIPriv->nCompHi - g_sImeUIG.rcWorkArea.top -
lpUIPriv->nFracHi - g_sImeUIG.cyBorder;
nAvailTextHi = nAvailTextHi < 0 ? 0 : nAvailTextHi;
dwPageSize = (DWORD)nAvailTextHi / g_sImeUIG.nCandLineHi;
if (dwPageSize >= lpUIPriv->dwPageSize ) {
dwPageSize = lpUIPriv->dwPageSize;
} else if (dwPageSize < MIN_PAGESIZE) {
dwPageSize = MIN_PAGESIZE;
} else {
}
ptNew.y = lpUIPriv->ptComp.y - g_sImeUIG.nCandDy[dwPageSize] -
lpUIPriv->nFracHi - g_sImeUIG.cyBorder;
#else // Still keep the old way for reference and backup (in case).
int nyCand;
nyCand = lpUIPriv->ptComp.y - g_sImeUIG.nCandDy[lpUIPriv->dwPageSize] -
lpUIPriv->nFracHi - g_sImeUIG.cyBorder;
if (nyCand >= g_sImeUIG.rcWorkArea.top) {
ptNew.y = nyCand;
dwPageSize = lpUIPriv->dwPageSize;
} else {
dwPageSize = MIN_PAGESIZE;
}
#endif
}
if (dwPageSize != lpUIPriv->lpCandList->dwPageSize) {
lpUIPriv->lpCandList->dwPageSize = dwPageSize;
CalcCandSize(hCandWnd);
SetWindowPos(hCandWnd, NULL, 0, 0,
lpUIPriv->nCandWi, lpUIPriv->nCandHi,
SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
SetWindowPos(lpUIPriv->hScrBar, NULL,
lpUIPriv->rcCandText.right, lpUIPriv->rcCandText.top,
g_sImeUIG.cxVScroll, (lpUIPriv->rcCandText.bottom - lpUIPriv->rcCandText.top),
SWP_NOACTIVATE|SWP_NOZORDER);
InvalidateRect(hCandWnd, NULL, FALSE);
}
if (ptNew.x + lpUIPriv->nCandWi > g_sImeUIG.rcWorkArea.right) {
ptNew.x = g_sImeUIG.rcWorkArea.right - lpUIPriv->nCandWi;
}
if (ptNew.x != lpUIPriv->ptCand.x ||
ptNew.y != lpUIPriv->ptCand.y) {
lpUIPriv->ptCand = ptNew;
SetWindowPos(hCandWnd, NULL, ptNew.x, ptNew.y, 0, 0,
SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
}
return;
}
/**********************************************************************/
/* OnCandCreate() */
/**********************************************************************/
static __inline
LRESULT OnCandCreate(HWND hCandWnd, LPCREATESTRUCT lpCS)
{
HWND hUIWnd;
LPUIPRIV lpUIPriv;
HIMC hIMC;
hUIWnd = GetWindow(hCandWnd, GW_OWNER);
if (!hUIWnd) {
return -1L;
}
lpUIPriv = (LPUIPRIV)GetWindowLong(hUIWnd, IMMGWL_PRIVATE);
if (!lpUIPriv) {
return -1L;
}
SetWindowLong(hCandWnd, IMMGWL_PRIVATE, (LONG)lpUIPriv);
hIMC = (HIMC)GetWindowLong(hUIWnd, IMMGWL_IMC);
if (!lpUIPriv) {
return -1L;
}
SetWindowLong(hCandWnd, IMMGWL_IMC, (LONG)hIMC);
if (lpCS->style & CLS_FRACTION) {
lpUIPriv->fdwUIFlags |= UI_CAND_FRACTION;
lpUIPriv->nFracWi = g_sImeUIG.nCandFracWi;
lpUIPriv->nFracHi = g_sImeUIG.nCandFracHi;
} else {
lpUIPriv->fdwUIFlags &= ~(UI_CAND_FRACTION);
lpUIPriv->nFracWi = lpUIPriv->nFracHi = 0;
}
lpUIPriv->ptCand.x = lpCS->x;
lpUIPriv->ptCand.y = lpCS->y;
lpUIPriv->nCandWi = lpCS->cx;
lpUIPriv->nCandHi = lpCS->cy;
lpUIPriv->rcCandText.left = g_sImeUIG.nCandCharWi;
lpUIPriv->rcCandText.top = 0;
lpUIPriv->rcCandText.right = lpCS->cx + g_sImeUIG.nCandCharWi;
lpUIPriv->rcCandText.bottom = lpCS->cy;
lpUIPriv->rcFraction.left = 0;
lpUIPriv->rcFraction.right = lpCS->cx;
lpUIPriv->rcFraction.top = lpUIPriv->rcFraction.bottom = lpCS->cy;
if (!lpUIPriv->hScrBar) {
lpUIPriv->hScrBar = CreateWindow(
TEXT("scrollbar"), NULL, WS_CHILD|SBS_VERT,
lpUIPriv->rcCandText.right, lpUIPriv->rcCandText.top,
g_sImeUIG.cxVScroll, lpCS->cy,
hCandWnd, (HMENU)1, lpUIPriv->hInst, NULL);
}
return 0L;
}
/**********************************************************************/
/* OnCandDestroy() */
/**********************************************************************/
static __inline
LRESULT OnCandDestroy(HWND hCandWnd)
{
LPUIPRIV lpUIPriv;
lpUIPriv = (LPUIPRIV)GetWindowLong(hCandWnd, IMMGWL_PRIVATE);
lpUIPriv->hCandWnd = (HWND)NULL;
if (lpUIPriv->hScrBar) {
DestroyWindow(lpUIPriv->hScrBar);
lpUIPriv->hScrBar = (HWND)NULL;
}
if (g_sImeUIG.hFracFont) {
DeleteObject(g_sImeUIG.hFracFont);
g_sImeUIG.hFracFont = NULL;
}
return 0L;
}
/**********************************************************************/
/* DrawCandLine() */
/**********************************************************************/
void DrawCandLine(HDC hDC, LPUIPRIV lpUIPriv, DWORD dwIndex, BOOL fSelected)
{
LPCANDIDATELIST lpCandList = lpUIPriv->lpCandList;
DWORD dwStart, dwEnd;
int i;
RECT rcCandLine;
TCHAR szCandStr[2] = {0};
RECT rcAccel;
TCHAR szAccelStr[2] = {0};
dwStart = lpCandList->dwPageStart;
dwEnd = dwStart + lpCandList->dwPageSize;
dwEnd = dwEnd > lpCandList->dwCount ? lpCandList->dwCount : dwEnd;
if (dwIndex > dwEnd) {
return;
}
i = dwIndex - dwStart;
if (fSelected) {
SetBkColor(hDC, g_sImeUIG.crHighlight);
SetTextColor(hDC, g_sImeUIG.crHighlightText);
} else {
SetBkColor(hDC, g_sImeUIG.crWindow);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -