⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 candui.cpp

📁 基于Pocket PC的简体中文拼音输入法中的用户接口部分的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// 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 + -