1438 lines
36 KiB
C++
1438 lines
36 KiB
C++
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved
|
|
|
|
#include "Private.h"
|
|
#include "Globals.h"
|
|
#include "BaseWindow.h"
|
|
#include "CandidateWindow.h"
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCandidateWindow::CCandidateWindow(_In_ CANDWNDCALLBACK pfnCallback, _In_ void *pv, _In_ CCandidateRange *pIndexRange, _In_ BOOL isStoreAppMode)
|
|
{
|
|
_currentSelection = 0;
|
|
|
|
_SetTextColor(CANDWND_ITEM_COLOR, GetSysColor(COLOR_WINDOW)); // text color is black
|
|
_SetFillColor((HBRUSH)(COLOR_WINDOW+1));
|
|
|
|
_pIndexRange = pIndexRange;
|
|
|
|
_pfnCallback = pfnCallback;
|
|
_pObj = pv;
|
|
|
|
_pShadowWnd = nullptr;
|
|
|
|
_cyRow = CANDWND_ROW_WIDTH;
|
|
_cxTitle = 0;
|
|
|
|
_pVScrollBarWnd = nullptr;
|
|
|
|
_wndWidth = 0;
|
|
|
|
_dontAdjustOnEmptyItemPage = FALSE;
|
|
|
|
_isStoreAppMode = isStoreAppMode;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCandidateWindow::~CCandidateWindow()
|
|
{
|
|
_ClearList();
|
|
_DeleteShadowWnd();
|
|
_DeleteVScrollBarWnd();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _Create
|
|
//
|
|
// CandidateWinow is the top window
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CCandidateWindow::_Create(ATOM atom, _In_ UINT wndWidth, _In_opt_ HWND parentWndHandle)
|
|
{
|
|
BOOL ret = FALSE;
|
|
_wndWidth = wndWidth;
|
|
|
|
ret = _CreateMainWindow(atom, parentWndHandle);
|
|
if (FALSE == ret)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
ret = _CreateBackGroundShadowWindow();
|
|
if (FALSE == ret)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
ret = _CreateVScrollWindow();
|
|
if (FALSE == ret)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
_ResizeWindow();
|
|
|
|
Exit:
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CCandidateWindow::_CreateMainWindow(ATOM atom, _In_opt_ HWND parentWndHandle)
|
|
{
|
|
_SetUIWnd(this);
|
|
|
|
if (!CBaseWindow::_Create(atom,
|
|
WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
|
|
WS_BORDER | WS_POPUP,
|
|
NULL, 0, 0, parentWndHandle))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CCandidateWindow::_CreateBackGroundShadowWindow()
|
|
{
|
|
_pShadowWnd = new (std::nothrow) CShadowWindow(this);
|
|
if (_pShadowWnd == nullptr)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!_pShadowWnd->_Create(Global::AtomShadowWindow,
|
|
WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_LAYERED,
|
|
WS_DISABLED | WS_POPUP, this))
|
|
{
|
|
_DeleteShadowWnd();
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CCandidateWindow::_CreateVScrollWindow()
|
|
{
|
|
BOOL ret = FALSE;
|
|
|
|
SHELL_MODE shellMode = _isStoreAppMode ? STOREAPP : DESKTOP;
|
|
CScrollBarWindowFactory* pFactory = CScrollBarWindowFactory::Instance();
|
|
_pVScrollBarWnd = pFactory->MakeScrollBarWindow(shellMode);
|
|
|
|
if (_pVScrollBarWnd == nullptr)
|
|
{
|
|
_DeleteShadowWnd();
|
|
goto Exit;
|
|
}
|
|
|
|
_pVScrollBarWnd->_SetUIWnd(this);
|
|
|
|
if (!_pVScrollBarWnd->_Create(Global::AtomScrollBarWindow, WS_EX_TOPMOST | WS_EX_TOOLWINDOW, WS_CHILD, this))
|
|
{
|
|
_DeleteVScrollBarWnd();
|
|
_DeleteShadowWnd();
|
|
goto Exit;
|
|
}
|
|
|
|
ret = TRUE;
|
|
|
|
Exit:
|
|
pFactory->Release();
|
|
return ret;
|
|
}
|
|
|
|
void CCandidateWindow::_ResizeWindow()
|
|
{
|
|
SIZE size = {0, 0};
|
|
|
|
_cxTitle = max(_cxTitle, size.cx + 2 * GetSystemMetrics(SM_CXFRAME));
|
|
|
|
int candidateListPageCnt = _pIndexRange->Count();
|
|
CBaseWindow::_Resize(0, 0, _cxTitle, _cyRow * candidateListPageCnt);
|
|
|
|
RECT rcCandRect = {0, 0, 0, 0};
|
|
_GetClientRect(&rcCandRect);
|
|
|
|
int letf = rcCandRect.right - GetSystemMetrics(SM_CXVSCROLL) * 2 - CANDWND_BORDER_WIDTH;
|
|
int top = rcCandRect.top + CANDWND_BORDER_WIDTH;
|
|
int width = GetSystemMetrics(SM_CXVSCROLL) * 2;
|
|
int height = rcCandRect.bottom - rcCandRect.top - CANDWND_BORDER_WIDTH * 2;
|
|
|
|
_pVScrollBarWnd->_Resize(letf, top, width, height);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _Move
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_Move(int x, int y)
|
|
{
|
|
CBaseWindow::_Move(x, y);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _Show
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_Show(BOOL isShowWnd)
|
|
{
|
|
if (_pShadowWnd)
|
|
{
|
|
_pShadowWnd->_Show(isShowWnd);
|
|
}
|
|
CBaseWindow::_Show(isShowWnd);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _SetTextColor
|
|
// _SetFillColor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID CCandidateWindow::_SetTextColor(_In_ COLORREF crColor, _In_ COLORREF crBkColor)
|
|
{
|
|
_crTextColor = _AdjustTextColor(crColor, crBkColor);
|
|
_crBkColor = crBkColor;
|
|
}
|
|
|
|
VOID CCandidateWindow::_SetFillColor(_In_ HBRUSH hBrush)
|
|
{
|
|
_brshBkColor = hBrush;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _WindowProcCallback
|
|
//
|
|
// Cand window proc.
|
|
//----------------------------------------------------------------------------
|
|
|
|
const int PageCountPosition = 1;
|
|
const int StringPosition = 4;
|
|
|
|
LRESULT CALLBACK CCandidateWindow::_WindowProcCallback(_In_ HWND wndHandle, UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_CREATE:
|
|
{
|
|
HDC dcHandle = nullptr;
|
|
|
|
dcHandle = GetDC(wndHandle);
|
|
if (dcHandle)
|
|
{
|
|
HFONT hFontOld = (HFONT)SelectObject(dcHandle, Global::defaultlFontHandle);
|
|
GetTextMetrics(dcHandle, &_TextMetric);
|
|
|
|
_cxTitle = _TextMetric.tmMaxCharWidth * _wndWidth;
|
|
SelectObject(dcHandle, hFontOld);
|
|
ReleaseDC(wndHandle, dcHandle);
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
case WM_DESTROY:
|
|
_DeleteShadowWnd();
|
|
return 0;
|
|
|
|
case WM_WINDOWPOSCHANGED:
|
|
{
|
|
WINDOWPOS* pWndPos = (WINDOWPOS*)lParam;
|
|
|
|
// move shadow
|
|
if (_pShadowWnd)
|
|
{
|
|
_pShadowWnd->_OnOwnerWndMoved((pWndPos->flags & SWP_NOSIZE) == 0);
|
|
}
|
|
|
|
// move v-scroll
|
|
if (_pVScrollBarWnd)
|
|
{
|
|
_pVScrollBarWnd->_OnOwnerWndMoved((pWndPos->flags & SWP_NOSIZE) == 0);
|
|
}
|
|
|
|
_FireMessageToLightDismiss(wndHandle, pWndPos);
|
|
}
|
|
break;
|
|
|
|
case WM_WINDOWPOSCHANGING:
|
|
{
|
|
WINDOWPOS* pWndPos = (WINDOWPOS*)lParam;
|
|
|
|
// show/hide shadow
|
|
if (_pShadowWnd)
|
|
{
|
|
if ((pWndPos->flags & SWP_HIDEWINDOW) != 0)
|
|
{
|
|
_pShadowWnd->_Show(FALSE);
|
|
}
|
|
|
|
// don't go behaind of shadow
|
|
if (((pWndPos->flags & SWP_NOZORDER) == 0) && (pWndPos->hwndInsertAfter == _pShadowWnd->_GetWnd()))
|
|
{
|
|
pWndPos->flags |= SWP_NOZORDER;
|
|
}
|
|
|
|
_pShadowWnd->_OnOwnerWndMoved((pWndPos->flags & SWP_NOSIZE) == 0);
|
|
}
|
|
|
|
// show/hide v-scroll
|
|
if (_pVScrollBarWnd)
|
|
{
|
|
if ((pWndPos->flags & SWP_HIDEWINDOW) != 0)
|
|
{
|
|
_pVScrollBarWnd->_Show(FALSE);
|
|
}
|
|
|
|
_pVScrollBarWnd->_OnOwnerWndMoved((pWndPos->flags & SWP_NOSIZE) == 0);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_SHOWWINDOW:
|
|
// show/hide shadow
|
|
if (_pShadowWnd)
|
|
{
|
|
_pShadowWnd->_Show((BOOL)wParam);
|
|
}
|
|
|
|
// show/hide v-scroll
|
|
if (_pVScrollBarWnd)
|
|
{
|
|
_pVScrollBarWnd->_Show((BOOL)wParam);
|
|
}
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
{
|
|
HDC dcHandle = nullptr;
|
|
PAINTSTRUCT ps;
|
|
|
|
dcHandle = BeginPaint(wndHandle, &ps);
|
|
_OnPaint(dcHandle, &ps);
|
|
_DrawBorder(wndHandle, CANDWND_BORDER_WIDTH*2);
|
|
EndPaint(wndHandle, &ps);
|
|
}
|
|
return 0;
|
|
|
|
case WM_SETCURSOR:
|
|
{
|
|
POINT cursorPoint;
|
|
|
|
GetCursorPos(&cursorPoint);
|
|
MapWindowPoints(NULL, wndHandle, &cursorPoint, 1);
|
|
|
|
// handle mouse message
|
|
_HandleMouseMsg(HIWORD(lParam), cursorPoint);
|
|
}
|
|
return 1;
|
|
|
|
case WM_MOUSEMOVE:
|
|
case WM_LBUTTONDOWN:
|
|
case WM_MBUTTONDOWN:
|
|
case WM_RBUTTONDOWN:
|
|
case WM_LBUTTONUP:
|
|
case WM_MBUTTONUP:
|
|
case WM_RBUTTONUP:
|
|
{
|
|
POINT point;
|
|
|
|
POINTSTOPOINT(point, MAKEPOINTS(lParam));
|
|
|
|
// handle mouse message
|
|
_HandleMouseMsg(uMsg, point);
|
|
}
|
|
// we processes this message, it should return zero.
|
|
return 0;
|
|
|
|
case WM_MOUSEACTIVATE:
|
|
{
|
|
WORD mouseEvent = HIWORD(lParam);
|
|
if (mouseEvent == WM_LBUTTONDOWN ||
|
|
mouseEvent == WM_RBUTTONDOWN ||
|
|
mouseEvent == WM_MBUTTONDOWN)
|
|
{
|
|
return MA_NOACTIVATE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_POINTERACTIVATE:
|
|
return PA_NOACTIVATE;
|
|
|
|
case WM_VSCROLL:
|
|
_OnVScroll(LOWORD(wParam), HIWORD(wParam));
|
|
return 0;
|
|
}
|
|
|
|
return DefWindowProc(wndHandle, uMsg, wParam, lParam);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _HandleMouseMsg
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_HandleMouseMsg(_In_ UINT mouseMsg, _In_ POINT point)
|
|
{
|
|
switch (mouseMsg)
|
|
{
|
|
case WM_MOUSEMOVE:
|
|
_OnMouseMove(point);
|
|
break;
|
|
case WM_LBUTTONDOWN:
|
|
_OnLButtonDown(point);
|
|
break;
|
|
case WM_LBUTTONUP:
|
|
_OnLButtonUp(point);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _OnPaint
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_OnPaint(_In_ HDC dcHandle, _In_ PAINTSTRUCT *pPaintStruct)
|
|
{
|
|
SetBkMode(dcHandle, TRANSPARENT);
|
|
|
|
HFONT hFontOld = (HFONT)SelectObject(dcHandle, Global::defaultlFontHandle);
|
|
|
|
FillRect(dcHandle, &pPaintStruct->rcPaint, _brshBkColor);
|
|
|
|
UINT currentPageIndex = 0;
|
|
UINT currentPage = 0;
|
|
|
|
if (FAILED(_GetCurrentPage(¤tPage)))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
_AdjustPageIndex(currentPage, currentPageIndex);
|
|
|
|
_DrawList(dcHandle, currentPageIndex, &pPaintStruct->rcPaint);
|
|
|
|
cleanup:
|
|
SelectObject(dcHandle, hFontOld);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _OnLButtonDown
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_OnLButtonDown(POINT pt)
|
|
{
|
|
RECT rcWindow = {0, 0, 0, 0};;
|
|
_GetClientRect(&rcWindow);
|
|
|
|
int cyLine = _cyRow;
|
|
|
|
UINT candidateListPageCnt = _pIndexRange->Count();
|
|
UINT index = 0;
|
|
int currentPage = 0;
|
|
|
|
if (FAILED(_GetCurrentPage(¤tPage)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Hit test on list items
|
|
index = *_PageIndex.GetAt(currentPage);
|
|
|
|
for (UINT pageCount = 0; (index < _candidateList.Count()) && (pageCount < candidateListPageCnt); index++, pageCount++)
|
|
{
|
|
RECT rc = {0, 0, 0, 0};
|
|
|
|
rc.left = rcWindow.left;
|
|
rc.right = rcWindow.right - GetSystemMetrics(SM_CXVSCROLL) * 2;
|
|
rc.top = rcWindow.top + (pageCount * cyLine);
|
|
rc.bottom = rcWindow.top + ((pageCount + 1) * cyLine);
|
|
|
|
if (PtInRect(&rc, pt) && _pfnCallback)
|
|
{
|
|
SetCursor(LoadCursor(NULL, IDC_HAND));
|
|
_currentSelection = index;
|
|
_pfnCallback(_pObj, CAND_ITEM_SELECT);
|
|
return;
|
|
}
|
|
}
|
|
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
|
|
if (_pVScrollBarWnd)
|
|
{
|
|
RECT rc = {0, 0, 0, 0};
|
|
|
|
_pVScrollBarWnd->_GetClientRect(&rc);
|
|
MapWindowPoints(_GetWnd(), _pVScrollBarWnd->_GetWnd(), &pt, 1);
|
|
|
|
if (PtInRect(&rc, pt))
|
|
{
|
|
_pVScrollBarWnd->_OnLButtonDown(pt);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _OnLButtonUp
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_OnLButtonUp(POINT pt)
|
|
{
|
|
if (nullptr == _pVScrollBarWnd)
|
|
{
|
|
return;
|
|
}
|
|
|
|
RECT rc = {0, 0, 0, 0};
|
|
_pVScrollBarWnd->_GetClientRect(&rc);
|
|
MapWindowPoints(_GetWnd(), _pVScrollBarWnd->_GetWnd(), &pt, 1);
|
|
|
|
if (_IsCapture())
|
|
{
|
|
_pVScrollBarWnd->_OnLButtonUp(pt);
|
|
}
|
|
else if (PtInRect(&rc, pt))
|
|
{
|
|
_pVScrollBarWnd->_OnLButtonUp(pt);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _OnMouseMove
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_OnMouseMove(POINT pt)
|
|
{
|
|
RECT rcWindow = {0, 0, 0, 0};
|
|
|
|
_GetClientRect(&rcWindow);
|
|
|
|
RECT rc = {0, 0, 0, 0};
|
|
|
|
rc.left = rcWindow.left;
|
|
rc.right = rcWindow.right - GetSystemMetrics(SM_CXVSCROLL) * 2;
|
|
|
|
rc.top = rcWindow.top;
|
|
rc.bottom = rcWindow.bottom;
|
|
|
|
if (PtInRect(&rc, pt))
|
|
{
|
|
SetCursor(LoadCursor(NULL, IDC_HAND));
|
|
return;
|
|
}
|
|
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
|
|
if (_pVScrollBarWnd)
|
|
{
|
|
_pVScrollBarWnd->_GetClientRect(&rc);
|
|
MapWindowPoints(_GetWnd(), _pVScrollBarWnd->_GetWnd(), &pt, 1);
|
|
|
|
if (PtInRect(&rc, pt))
|
|
{
|
|
_pVScrollBarWnd->_OnMouseMove(pt);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _OnVScroll
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_OnVScroll(DWORD dwSB, _In_ DWORD nPos)
|
|
{
|
|
switch (dwSB)
|
|
{
|
|
case SB_LINEDOWN:
|
|
_SetSelectionOffset(+1);
|
|
_InvalidateRect();
|
|
break;
|
|
case SB_LINEUP:
|
|
_SetSelectionOffset(-1);
|
|
_InvalidateRect();
|
|
break;
|
|
case SB_PAGEDOWN:
|
|
_MovePage(+1, FALSE);
|
|
_InvalidateRect();
|
|
break;
|
|
case SB_PAGEUP:
|
|
_MovePage(-1, FALSE);
|
|
_InvalidateRect();
|
|
break;
|
|
case SB_THUMBPOSITION:
|
|
_SetSelection(nPos, FALSE);
|
|
_InvalidateRect();
|
|
break;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _DrawList
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_DrawList(_In_ HDC dcHandle, _In_ UINT iIndex, _In_ RECT *prc)
|
|
{
|
|
int pageCount = 0;
|
|
int candidateListPageCnt = _pIndexRange->Count();
|
|
|
|
int cxLine = _TextMetric.tmAveCharWidth;
|
|
int cyLine = max(_cyRow, _TextMetric.tmHeight);
|
|
int cyOffset = (cyLine == _cyRow ? (cyLine-_TextMetric.tmHeight)/2 : 0);
|
|
|
|
RECT rc;
|
|
|
|
const size_t lenOfPageCount = 16;
|
|
for (;
|
|
(iIndex < _candidateList.Count()) && (pageCount < candidateListPageCnt);
|
|
iIndex++, pageCount++)
|
|
{
|
|
WCHAR pageCountString[lenOfPageCount] = {'\0'};
|
|
CCandidateListItem* pItemList = nullptr;
|
|
|
|
rc.top = prc->top + pageCount * cyLine;
|
|
rc.bottom = rc.top + cyLine;
|
|
|
|
rc.left = prc->left + PageCountPosition * cxLine;
|
|
rc.right = prc->left + StringPosition * cxLine;
|
|
|
|
// Number Font Color And BK
|
|
SetTextColor(dcHandle, CANDWND_NUM_COLOR);
|
|
SetBkColor(dcHandle, GetSysColor(COLOR_3DHIGHLIGHT));
|
|
|
|
StringCchPrintf(pageCountString, ARRAYSIZE(pageCountString), L"%d", (LONG)*_pIndexRange->GetAt(pageCount));
|
|
ExtTextOut(dcHandle, PageCountPosition * cxLine, pageCount * cyLine + cyOffset, ETO_OPAQUE, &rc, pageCountString, lenOfPageCount, NULL);
|
|
|
|
rc.left = prc->left + StringPosition * cxLine;
|
|
rc.right = prc->right;
|
|
|
|
// Candidate Font Color And BK
|
|
if (_currentSelection != iIndex)
|
|
{
|
|
SetTextColor(dcHandle, _crTextColor);
|
|
SetBkColor(dcHandle, GetSysColor(COLOR_3DHIGHLIGHT));
|
|
}
|
|
else
|
|
{
|
|
SetTextColor(dcHandle, CANDWND_SELECTED_ITEM_COLOR);
|
|
SetBkColor(dcHandle, CANDWND_SELECTED_BK_COLOR);
|
|
}
|
|
|
|
pItemList = _candidateList.GetAt(iIndex);
|
|
ExtTextOut(dcHandle, StringPosition * cxLine, pageCount * cyLine + cyOffset, ETO_OPAQUE, &rc, pItemList->_ItemString.Get(), (DWORD)pItemList->_ItemString.GetLength(), NULL);
|
|
}
|
|
for (; (pageCount < candidateListPageCnt); pageCount++)
|
|
{
|
|
rc.top = prc->top + pageCount * cyLine;
|
|
rc.bottom = rc.top + cyLine;
|
|
|
|
rc.left = prc->left + PageCountPosition * cxLine;
|
|
rc.right = prc->left + StringPosition * cxLine;
|
|
|
|
FillRect(dcHandle, &rc, (HBRUSH)(COLOR_3DHIGHLIGHT+1));
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _DrawBorder
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void CCandidateWindow::_DrawBorder(_In_ HWND wndHandle, _In_ int cx)
|
|
{
|
|
RECT rcWnd;
|
|
|
|
HDC dcHandle = GetWindowDC(wndHandle);
|
|
|
|
GetWindowRect(wndHandle, &rcWnd);
|
|
// zero based
|
|
OffsetRect(&rcWnd, -rcWnd.left, -rcWnd.top);
|
|
|
|
HPEN hPen = CreatePen(PS_DOT, cx, CANDWND_BORDER_COLOR);
|
|
HPEN hPenOld = (HPEN)SelectObject(dcHandle, hPen);
|
|
HBRUSH hBorderBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
|
|
HBRUSH hBorderBrushOld = (HBRUSH)SelectObject(dcHandle, hBorderBrush);
|
|
|
|
Rectangle(dcHandle, rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom);
|
|
|
|
SelectObject(dcHandle, hPenOld);
|
|
SelectObject(dcHandle, hBorderBrushOld);
|
|
DeleteObject(hPen);
|
|
DeleteObject(hBorderBrush);
|
|
ReleaseDC(wndHandle, dcHandle);
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _AddString
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_AddString(_Inout_ CCandidateListItem *pCandidateItem, _In_ BOOL isAddFindKeyCode)
|
|
{
|
|
DWORD_PTR dwItemString = pCandidateItem->_ItemString.GetLength();
|
|
const WCHAR* pwchString = nullptr;
|
|
if (dwItemString)
|
|
{
|
|
pwchString = new (std::nothrow) WCHAR[ dwItemString ];
|
|
if (!pwchString)
|
|
{
|
|
return;
|
|
}
|
|
memcpy((void*)pwchString, pCandidateItem->_ItemString.Get(), dwItemString * sizeof(WCHAR));
|
|
}
|
|
|
|
DWORD_PTR itemWildcard = pCandidateItem->_FindKeyCode.GetLength();
|
|
const WCHAR* pwchWildcard = nullptr;
|
|
if (itemWildcard && isAddFindKeyCode)
|
|
{
|
|
pwchWildcard = new (std::nothrow) WCHAR[ itemWildcard ];
|
|
if (!pwchWildcard)
|
|
{
|
|
if (pwchString)
|
|
{
|
|
delete [] pwchString;
|
|
}
|
|
return;
|
|
}
|
|
memcpy((void*)pwchWildcard, pCandidateItem->_FindKeyCode.Get(), itemWildcard * sizeof(WCHAR));
|
|
}
|
|
|
|
CCandidateListItem* pLI = nullptr;
|
|
pLI = _candidateList.Append();
|
|
if (!pLI)
|
|
{
|
|
if (pwchString)
|
|
{
|
|
delete [] pwchString;
|
|
pwchString = nullptr;
|
|
}
|
|
if (pwchWildcard)
|
|
{
|
|
delete [] pwchWildcard;
|
|
pwchWildcard = nullptr;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (pwchString)
|
|
{
|
|
pLI->_ItemString.Set(pwchString, dwItemString);
|
|
}
|
|
if (pwchWildcard)
|
|
{
|
|
pLI->_FindKeyCode.Set(pwchWildcard, itemWildcard);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _ClearList
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_ClearList()
|
|
{
|
|
for (UINT index = 0; index < _candidateList.Count(); index++)
|
|
{
|
|
CCandidateListItem* pItemList = nullptr;
|
|
pItemList = _candidateList.GetAt(index);
|
|
delete [] pItemList->_ItemString.Get();
|
|
delete [] pItemList->_FindKeyCode.Get();
|
|
}
|
|
_currentSelection = 0;
|
|
_candidateList.Clear();
|
|
_PageIndex.Clear();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _SetScrollInfo
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_SetScrollInfo(_In_ int nMax, _In_ int nPage)
|
|
{
|
|
CScrollInfo si;
|
|
si.nMax = nMax;
|
|
si.nPage = nPage;
|
|
si.nPos = 0;
|
|
|
|
if (_pVScrollBarWnd)
|
|
{
|
|
_pVScrollBarWnd->_SetScrollInfo(&si);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _GetCandidateString
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD CCandidateWindow::_GetCandidateString(_In_ int iIndex, _Outptr_result_maybenull_z_ const WCHAR **ppwchCandidateString)
|
|
{
|
|
CCandidateListItem* pItemList = nullptr;
|
|
|
|
if (iIndex < 0 )
|
|
{
|
|
*ppwchCandidateString = nullptr;
|
|
return 0;
|
|
}
|
|
|
|
UINT index = static_cast<UINT>(iIndex);
|
|
|
|
if (index >= _candidateList.Count())
|
|
{
|
|
*ppwchCandidateString = nullptr;
|
|
return 0;
|
|
}
|
|
|
|
pItemList = _candidateList.GetAt(iIndex);
|
|
if (ppwchCandidateString)
|
|
{
|
|
*ppwchCandidateString = pItemList->_ItemString.Get();
|
|
}
|
|
return (DWORD)pItemList->_ItemString.GetLength();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _GetSelectedCandidateString
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD CCandidateWindow::_GetSelectedCandidateString(_Outptr_result_maybenull_ const WCHAR **ppwchCandidateString)
|
|
{
|
|
CCandidateListItem* pItemList = nullptr;
|
|
|
|
if (_currentSelection >= _candidateList.Count())
|
|
{
|
|
*ppwchCandidateString = nullptr;
|
|
return 0;
|
|
}
|
|
|
|
pItemList = _candidateList.GetAt(_currentSelection);
|
|
if (ppwchCandidateString)
|
|
{
|
|
*ppwchCandidateString = pItemList->_ItemString.Get();
|
|
}
|
|
return (DWORD)pItemList->_ItemString.GetLength();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _SetSelectionInPage
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CCandidateWindow::_SetSelectionInPage(int nPos)
|
|
{
|
|
if (nPos < 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
UINT pos = static_cast<UINT>(nPos);
|
|
|
|
if (pos >= _candidateList.Count())
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
int currentPage = 0;
|
|
if (FAILED(_GetCurrentPage(¤tPage)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
_currentSelection = *_PageIndex.GetAt(currentPage) + nPos;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _MoveSelection
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CCandidateWindow::_MoveSelection(_In_ int offSet, _In_ BOOL isNotify)
|
|
{
|
|
if (_currentSelection + offSet >= _candidateList.Count())
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
_currentSelection += offSet;
|
|
|
|
_dontAdjustOnEmptyItemPage = TRUE;
|
|
|
|
if (_pVScrollBarWnd && isNotify)
|
|
{
|
|
_pVScrollBarWnd->_ShiftLine(offSet, isNotify);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _SetSelection
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CCandidateWindow::_SetSelection(_In_ int selectedIndex, _In_ BOOL isNotify)
|
|
{
|
|
if (selectedIndex == -1)
|
|
{
|
|
selectedIndex = _candidateList.Count() - 1;
|
|
}
|
|
|
|
if (selectedIndex < 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
int candCnt = static_cast<int>(_candidateList.Count());
|
|
if (selectedIndex >= candCnt)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
_currentSelection = static_cast<UINT>(selectedIndex);
|
|
|
|
BOOL ret = _AdjustPageIndexForSelection();
|
|
|
|
if (_pVScrollBarWnd && isNotify)
|
|
{
|
|
_pVScrollBarWnd->_ShiftPosition(selectedIndex, isNotify);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _SetSelection
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void CCandidateWindow::_SetSelection(_In_ int nIndex)
|
|
{
|
|
_currentSelection = nIndex;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _MovePage
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CCandidateWindow::_MovePage(_In_ int offSet, _In_ BOOL isNotify)
|
|
{
|
|
if (offSet == 0)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
int currentPage = 0;
|
|
int selectionOffset = 0;
|
|
int newPage = 0;
|
|
|
|
if (FAILED(_GetCurrentPage(¤tPage)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
newPage = currentPage + offSet;
|
|
if ((newPage < 0) || (newPage >= static_cast<int>(_PageIndex.Count())))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// If current selection is at the top of the page AND
|
|
// we are on the "default" page border, then we don't
|
|
// want adjustment to eliminate empty entries.
|
|
//
|
|
// We do this for keeping behavior inline with downlevel.
|
|
if (_currentSelection % _pIndexRange->Count() == 0 &&
|
|
_currentSelection == *_PageIndex.GetAt(currentPage))
|
|
{
|
|
_dontAdjustOnEmptyItemPage = TRUE;
|
|
}
|
|
|
|
selectionOffset = _currentSelection - *_PageIndex.GetAt(currentPage);
|
|
_currentSelection = *_PageIndex.GetAt(newPage) + selectionOffset;
|
|
_currentSelection = _candidateList.Count() > _currentSelection ? _currentSelection : _candidateList.Count() - 1;
|
|
|
|
// adjust scrollbar position
|
|
if (_pVScrollBarWnd && isNotify)
|
|
{
|
|
_pVScrollBarWnd->_ShiftPage(offSet, isNotify);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _SetSelectionOffset
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CCandidateWindow::_SetSelectionOffset(_In_ int offSet)
|
|
{
|
|
if (_currentSelection + offSet >= _candidateList.Count())
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL fCurrentPageHasEmptyItems = FALSE;
|
|
BOOL fAdjustPageIndex = TRUE;
|
|
|
|
_CurrentPageHasEmptyItems(&fCurrentPageHasEmptyItems);
|
|
|
|
int newOffset = _currentSelection + offSet;
|
|
|
|
// For SB_LINEUP and SB_LINEDOWN, we need to special case if CurrentPageHasEmptyItems.
|
|
// CurrentPageHasEmptyItems if we are on the last page.
|
|
if ((offSet == 1 || offSet == -1) &&
|
|
fCurrentPageHasEmptyItems && _PageIndex.Count() > 1)
|
|
{
|
|
int iPageIndex = *_PageIndex.GetAt(_PageIndex.Count() - 1);
|
|
// Moving on the last page and last page has empty items.
|
|
if (newOffset >= iPageIndex)
|
|
{
|
|
fAdjustPageIndex = FALSE;
|
|
}
|
|
// Moving across page border.
|
|
else if (newOffset < iPageIndex)
|
|
{
|
|
fAdjustPageIndex = TRUE;
|
|
}
|
|
|
|
_dontAdjustOnEmptyItemPage = TRUE;
|
|
}
|
|
|
|
_currentSelection = newOffset;
|
|
|
|
if (fAdjustPageIndex)
|
|
{
|
|
return _AdjustPageIndexForSelection();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _GetPageIndex
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCandidateWindow::_GetPageIndex(UINT *pIndex, _In_ UINT uSize, _Inout_ UINT *puPageCnt)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (uSize > _PageIndex.Count())
|
|
{
|
|
uSize = _PageIndex.Count();
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
if (pIndex)
|
|
{
|
|
for (UINT i = 0; i < uSize; i++)
|
|
{
|
|
*pIndex = *_PageIndex.GetAt(i);
|
|
pIndex++;
|
|
}
|
|
}
|
|
|
|
*puPageCnt = _PageIndex.Count();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _SetPageIndex
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCandidateWindow::_SetPageIndex(UINT *pIndex, _In_ UINT uPageCnt)
|
|
{
|
|
uPageCnt;
|
|
|
|
_PageIndex.Clear();
|
|
|
|
for (UINT i = 0; i < uPageCnt; i++)
|
|
{
|
|
UINT *pLastNewPageIndex = _PageIndex.Append();
|
|
if (pLastNewPageIndex != nullptr)
|
|
{
|
|
*pLastNewPageIndex = *pIndex;
|
|
pIndex++;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _GetCurrentPage
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCandidateWindow::_GetCurrentPage(_Inout_ UINT *pCurrentPage)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pCurrentPage == nullptr)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
*pCurrentPage = 0;
|
|
|
|
if (_PageIndex.Count() == 0)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
goto Exit;
|
|
}
|
|
|
|
if (_PageIndex.Count() == 1)
|
|
{
|
|
*pCurrentPage = 0;
|
|
goto Exit;
|
|
}
|
|
|
|
UINT i = 0;
|
|
for (i = 1; i < _PageIndex.Count(); i++)
|
|
{
|
|
UINT uPageIndex = *_PageIndex.GetAt(i);
|
|
|
|
if (uPageIndex > _currentSelection)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
*pCurrentPage = i - 1;
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _GetCurrentPage
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCandidateWindow::_GetCurrentPage(_Inout_ int *pCurrentPage)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
UINT needCastCurrentPage = 0;
|
|
|
|
if (nullptr == pCurrentPage)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
*pCurrentPage = 0;
|
|
|
|
hr = _GetCurrentPage(&needCastCurrentPage);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
hr = UIntToInt(needCastCurrentPage, pCurrentPage);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _AdjustPageIndexForSelection
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CCandidateWindow::_AdjustPageIndexForSelection()
|
|
{
|
|
UINT candidateListPageCnt = _pIndexRange->Count();
|
|
UINT* pNewPageIndex = nullptr;
|
|
UINT newPageCnt = 0;
|
|
|
|
if (_candidateList.Count() < candidateListPageCnt)
|
|
{
|
|
// no needed to restruct page index
|
|
return TRUE;
|
|
}
|
|
|
|
// B is number of pages before the current page
|
|
// A is number of pages after the current page
|
|
// uNewPageCount is A + B + 1;
|
|
// A is (uItemsAfter - 1) / candidateListPageCnt + 1 ->
|
|
// (_CandidateListCount - _currentSelection - CandidateListPageCount - 1) / candidateListPageCnt + 1->
|
|
// (_CandidateListCount - _currentSelection - 1) / candidateListPageCnt
|
|
// B is (uItemsBefore - 1) / candidateListPageCnt + 1 ->
|
|
// (_currentSelection - 1) / candidateListPageCnt + 1
|
|
// A + B is (_CandidateListCount - 2) / candidateListPageCnt + 1
|
|
|
|
BOOL isBefore = _currentSelection;
|
|
BOOL isAfter = _candidateList.Count() > _currentSelection + candidateListPageCnt;
|
|
|
|
// only have current page
|
|
if (!isBefore && !isAfter)
|
|
{
|
|
newPageCnt = 1;
|
|
}
|
|
// only have after pages; just count the total number of pages
|
|
else if (!isBefore && isAfter)
|
|
{
|
|
newPageCnt = (_candidateList.Count() - 1) / candidateListPageCnt + 1;
|
|
}
|
|
// we are at the last page
|
|
else if (isBefore && !isAfter)
|
|
{
|
|
newPageCnt = 2 + (_currentSelection - 1) / candidateListPageCnt;
|
|
}
|
|
else if (isBefore && isAfter)
|
|
{
|
|
newPageCnt = (_candidateList.Count() - 2) / candidateListPageCnt + 2;
|
|
}
|
|
|
|
pNewPageIndex = new (std::nothrow) UINT[ newPageCnt ];
|
|
if (pNewPageIndex == nullptr)
|
|
{
|
|
return FALSE;
|
|
}
|
|
pNewPageIndex[0] = 0;
|
|
UINT firstPage = _currentSelection % candidateListPageCnt;
|
|
if (firstPage && newPageCnt > 1)
|
|
{
|
|
pNewPageIndex[1] = firstPage;
|
|
}
|
|
|
|
for (UINT i = firstPage ? 2 : 1; i < newPageCnt; ++i)
|
|
{
|
|
pNewPageIndex[i] = pNewPageIndex[i - 1] + candidateListPageCnt;
|
|
}
|
|
|
|
_SetPageIndex(pNewPageIndex, newPageCnt);
|
|
|
|
delete [] pNewPageIndex;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _AdjustTextColor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
COLORREF _AdjustTextColor(_In_ COLORREF crColor, _In_ COLORREF crBkColor)
|
|
{
|
|
if (!Global::IsTooSimilar(crColor, crBkColor))
|
|
{
|
|
return crColor;
|
|
}
|
|
else
|
|
{
|
|
return crColor ^ RGB(255, 255, 255);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _CurrentPageHasEmptyItems
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCandidateWindow::_CurrentPageHasEmptyItems(_Inout_ BOOL *hasEmptyItems)
|
|
{
|
|
int candidateListPageCnt = _pIndexRange->Count();
|
|
UINT currentPage = 0;
|
|
|
|
if (FAILED(_GetCurrentPage(¤tPage)))
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
if ((currentPage == 0 || currentPage == _PageIndex.Count()-1) &&
|
|
(_PageIndex.Count() > 0) &&
|
|
(*_PageIndex.GetAt(currentPage) > (UINT)(_candidateList.Count() - candidateListPageCnt)))
|
|
{
|
|
*hasEmptyItems = TRUE;
|
|
}
|
|
else
|
|
{
|
|
*hasEmptyItems = FALSE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _FireMessageToLightDismiss
|
|
// fire EVENT_OBJECT_IME_xxx to let LightDismiss know about IME window.
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateWindow::_FireMessageToLightDismiss(_In_ HWND wndHandle, _In_ WINDOWPOS *pWndPos)
|
|
{
|
|
if (nullptr == pWndPos)
|
|
{
|
|
return;
|
|
}
|
|
|
|
BOOL isShowWnd = ((pWndPos->flags & SWP_SHOWWINDOW) != 0);
|
|
BOOL isHide = ((pWndPos->flags & SWP_HIDEWINDOW) != 0);
|
|
BOOL needResize = ((pWndPos->flags & SWP_NOSIZE) == 0);
|
|
BOOL needMove = ((pWndPos->flags & SWP_NOMOVE) == 0);
|
|
BOOL needRedraw = ((pWndPos->flags & SWP_NOREDRAW) == 0);
|
|
|
|
if (isShowWnd)
|
|
{
|
|
NotifyWinEvent(EVENT_OBJECT_IME_SHOW, wndHandle, OBJID_CLIENT, CHILDID_SELF);
|
|
}
|
|
else if (isHide)
|
|
{
|
|
NotifyWinEvent(EVENT_OBJECT_IME_HIDE, wndHandle, OBJID_CLIENT, CHILDID_SELF);
|
|
}
|
|
else if (needResize || needMove || needRedraw)
|
|
{
|
|
if (IsWindowVisible(wndHandle))
|
|
{
|
|
NotifyWinEvent(EVENT_OBJECT_IME_CHANGE, wndHandle, OBJID_CLIENT, CHILDID_SELF);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
HRESULT CCandidateWindow::_AdjustPageIndex(_Inout_ UINT & currentPage, _Inout_ UINT & currentPageIndex)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
UINT candidateListPageCnt = _pIndexRange->Count();
|
|
|
|
currentPageIndex = *_PageIndex.GetAt(currentPage);
|
|
|
|
BOOL hasEmptyItems = FALSE;
|
|
if (FAILED(_CurrentPageHasEmptyItems(&hasEmptyItems)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (FALSE == hasEmptyItems)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (TRUE == _dontAdjustOnEmptyItemPage)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
UINT tempSelection = _currentSelection;
|
|
|
|
// Last page
|
|
UINT candNum = _candidateList.Count();
|
|
UINT pageNum = _PageIndex.Count();
|
|
|
|
if ((currentPageIndex > candNum - candidateListPageCnt) && (pageNum > 0) && (currentPage == (pageNum - 1)))
|
|
{
|
|
_currentSelection = candNum - candidateListPageCnt;
|
|
|
|
_AdjustPageIndexForSelection();
|
|
|
|
_currentSelection = tempSelection;
|
|
|
|
if (FAILED(_GetCurrentPage(¤tPage)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
currentPageIndex = *_PageIndex.GetAt(currentPage);
|
|
}
|
|
// First page
|
|
else if ((currentPageIndex < candidateListPageCnt) && (currentPage == 0))
|
|
{
|
|
_currentSelection = 0;
|
|
|
|
_AdjustPageIndexForSelection();
|
|
|
|
_currentSelection = tempSelection;
|
|
}
|
|
|
|
_dontAdjustOnEmptyItemPage = FALSE;
|
|
hr = S_OK;
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
void CCandidateWindow::_DeleteShadowWnd()
|
|
{
|
|
if (nullptr != _pShadowWnd)
|
|
{
|
|
delete _pShadowWnd;
|
|
_pShadowWnd = nullptr;
|
|
}
|
|
}
|
|
|
|
void CCandidateWindow::_DeleteVScrollBarWnd()
|
|
{
|
|
if (nullptr != _pVScrollBarWnd)
|
|
{
|
|
delete _pVScrollBarWnd;
|
|
_pVScrollBarWnd = nullptr;
|
|
}
|
|
} |