📄 listbox.cpp
字号:
{
//ignore focus, since all we care about is selection
return TRUE;
}
IVoIPDisplayItem* pItem = reinterpret_cast<IVoIPDisplayItem*>(
OnGetItemData(pDrawStruct->itemID)
);
if (!pItem)
{
ASSERT(0);
return TRUE;
}
RECT ItemRect = pDrawStruct->rcItem;
#endif
if (((HDC)m_ItemBackBuffer == NULL) ||
(RECTHEIGHT(pDrawStruct->rcItem) > RECTHEIGHT(m_ItemBackBuffer.Rect())))
{
m_ItemBackBuffer.End();
if (FAILED(
m_ItemBackBuffer.CreateCanvas(
NULL,
RECTWIDTH(ItemRect),
RECTHEIGHT(ItemRect)
)
))
{
return TRUE;
}
}
RECT DrawRectangle;
SetRect(
&DrawRectangle,
0,
0,
RECTWIDTH(ItemRect),
RECTHEIGHT(ItemRect)
);
//if the item is selected, have it set focus to the child controls first
if ((pDrawStruct->itemState & ODS_SELECTED) &&
CommonUtilities_t::HasParentalFocus(m_hwnd))
{
IVoIPDisplayControl* pControl;
if (FAILED(
pItem->QueryInterface(
IID_IVoIPDisplayControl,
reinterpret_cast<void**>(&pControl)
)
) ||
!pControl->SetFocus()
)
{
SetFocus(m_hwnd);
}
}
//Have the item draw into the back buffer
if (FAILED(
pItem->Draw(
m_ItemBackBuffer,
&DrawRectangle,
(pDrawStruct->itemState & ODS_SELECTED),
FALSE
)
))
{
return TRUE;
}
BitBlt(
pDrawStruct->hDC,
ItemRect.left,
ItemRect.top,
RECTWIDTH(ItemRect),
RECTHEIGHT(ItemRect),
m_ItemBackBuffer,
0,
0,
SRCCOPY
);
return TRUE;
}
/*------------------------------------------------------------------------------
ListBoxImpl_t::OnMeasureItem
Handles WM_MEASUREITEM
If this is a variable height listbox then we will be prompted to measure the
height of a specific item. We delegate that to the current item.
NOTE: This message MUST be forwarded from the parent if the listbox
is to handle the measuring of the items
------------------------------------------------------------------------------*/
LRESULT
ListBoxImpl_t::MeasureItem(
MEASUREITEMSTRUCT* pMeasureStruct
)
{
#ifdef VIRTUAL_LISTBOX
//Get the item to measure
IVoIPDisplayItem* pItem = reinterpret_cast<IVoIPDisplayItem*>(
OnGetItemData(Index)
);
if (!pItem)
{
ASSERT(0);
return FALSE;
}
RECT ClientRect = {0};
GetClientRect(m_hwnd, &ClientRect);
UINT ItemHeight;
//ask the item to get its height
if (!pItem->GetHeight(&ItemHeight))
{
//if the item doesn't know how to gets its height, set the default
ItemHeight = Layout_t::ListBoxDefaultItemHeight;
}
m_VariableHeight[Index] = ItemHeight;
#else
if (!pMeasureStruct)
{
return FALSE;
}
//Get the item to measure
IVoIPDisplayItem* pItem = reinterpret_cast<IVoIPDisplayItem*>(
OnGetItemData(pMeasureStruct->itemID)
);
if (!pItem)
{
ASSERT(0);
return FALSE;
}
RECT ClientRect;
GetClientRect(m_hwnd, &ClientRect);
pMeasureStruct->itemWidth = RECTWIDTH(ClientRect);
//ask the item to get its height
if (!pItem || !pItem->GetHeight(&pMeasureStruct->itemHeight))
{
//if the item doesn't know how to gets its height, set the default
pMeasureStruct->itemHeight = Layout_t::ListBoxDefaultItemHeight();
}
#endif
return TRUE;
}
LRESULT
ListBoxImpl_t::OnFindItem(
IVoIPDisplayItem* pItem
)
{
return DefWindowProc(LB_FINDSTRING, 0, (LPARAM)pItem);
}
/*------------------------------------------------------------------------------
ListBoxImpl_t::OnSetCtrlBkgd
Sent when a child control needs a background brush. The rule is, if the
item is selected it gets a white brush, if the item is NOT selected
it gets the standard LBBackground for this control
------------------------------------------------------------------------------*/
LRESULT
ListBoxImpl_t::OnSetControlBackground(
UINT Message,
HDC hdc,
HWND Control
)
{
//Read only controls are handled by the def window proc
SetBkMode(hdc, TRANSPARENT);
if (GlobalData_t::s_ListBoxBrush == NULL)
{
GlobalData_t::s_ListBoxBrush = CreateSolidBrush(Colors_t::ListBoxBackgroundColor());
ASSERT(GlobalData_t::s_ListBoxBrush);
}
if ((Message == WM_CTLCOLORSTATIC) &&
(GetWindowLong(Control, GWL_STYLE) & ES_READONLY))
{
return reinterpret_cast<LRESULT>(GlobalData_t::s_ListBoxBrush);
}
//otherwise we want drawing done transparently wrt the background
if (Control == GetFocus())
{
return reinterpret_cast<LRESULT>(GetStockObject(WHITE_BRUSH));
}
else
{
return reinterpret_cast<LRESULT>(GlobalData_t::s_ListBoxBrush);
}
}
/*------------------------------------------------------------------------------
ListBoxImpl_t::OnTimer
Shows a tool tip (if it needs to be shown)
------------------------------------------------------------------------------*/
LRESULT
ListBoxImpl_t::OnTimer(
)
{
if (
!m_CheckToolTip ||
(OnGetCount() <= 0) ||
((GetTickCount() - m_dwToolTipTimer) < c_cmsToolTipLag)
)
{
return 0;
}
int IndexToSelect;
RECT ItemRect;
RECT ToolTipRect;
RECT ClientRect;
UINT yTop = 0;
SIZE size = {0};
IndexToSelect = OnGetCurSel();
if (IndexToSelect == LB_ERR)
{
return 0;
}
GetClientRect(m_hwnd, &ClientRect);
OnGetItemRect(IndexToSelect, &ItemRect);
m_ToolTip.GetWindowMetrics(RECTWIDTH(ItemRect), &size);
yTop = ItemRect.bottom - (RECTHEIGHT(ItemRect)/2);
if ((yTop + size.cy) > ClientRect.bottom)
{
yTop = ItemRect.bottom - size.cy - (RECTHEIGHT(ItemRect)/2);
}
ToolTipRect.left = ItemRect.right - size.cx;
ToolTipRect.top = yTop;
ToolTipRect.right = ItemRect.right;
ToolTipRect.bottom = yTop + size.cy;
MoveWindow(
(HWND)m_ToolTip,
ToolTipRect.left,
ToolTipRect.top,
RECTWIDTH(ToolTipRect),
RECTHEIGHT(ToolTipRect),
FALSE
);
ShowWindow((HWND)m_ToolTip, SW_SHOW);
m_CheckToolTip = false;
return 0;
}
#ifdef AUTOMATION
//Automation helper functions
#define MAX_LB_TEXT MAX_PATH
#define MAX_LB_SUBTEXT_CT 8
LRESULT
ListBoxImpl_t::OnGetTextLen(
int Index
)
{
return MAX_LB_TEXT;
}
LRESULT
ListBoxImpl_t::OnGetText(
int Index,
__out_ecount(MAX_LB_TEXT) WCHAR* pBuffer
)
{
__try
{
WCHAR* pwchCopy = pBuffer;
WCHAR* pwchStart = pwchCopy;
IVoIPDisplayItem* pItem = NULL;
pItem = reinterpret_cast<IVoIPDisplayItem*>(OnGetItemData(Index));
if (!pItem)
{
return LB_ERR;
}
for (
int i = 0;
i < MAX_LB_SUBTEXT_CT && (pwchCopy - pwchStart) < MAX_LB_TEXT;
i++
)
{
if (pItem->GetSubItemText(
i,
pwchCopy,
MAX_LB_TEXT - (pwchCopy - pwchStart)
) != S_OK)
{
*pwchCopy = 0;
break;
}
else
{
pwchCopy += wcslen(pwchCopy);
if ((pwchCopy - pwchStart) < MAX_LB_TEXT)
{
*pwchCopy = STRING_DELIMITER;
pwchCopy++;
}
}
}
pwchStart[MAX_LB_TEXT - 1] = L'\0';
return (LRESULT)(INT)(pwchCopy - pwchStart);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
RETAILMSG(1, (L"Buffer not at least MAX_LB_TEXT chars in length! Call LB_GETTEXTLEN first!"));
return LB_ERR;
}
}
#endif
/*------------------------------------------------------------------------------
ListBoxImpl_t::OnSettingChange
Handels WM_SETTINGCHANGE passed from UIManager
if it is caused by the Sip panel changes, reposition the items accordingly
------------------------------------------------------------------------------*/
LRESULT
ListBoxImpl_t::OnSettingChange(
UINT Flag
)
{
switch (Flag)
{
case SPI_SETSIPINFO:
case SPI_SIPMOVE:
//Caused by Sip panel changes
RepositionDisplayItems();
return 0;
default:
return 0;
}
return 1;
}
/*------------------------------------------------------------------------------
ListBoxImpl_t::RepositionDisplayItems
Reposition each display items when there is some change caused by Sip panel
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
ListBoxImpl_t::RepositionDisplayItems(
void
)
{
int SelectedItem = OnGetCurSel();
int NewTop = OnGetTopIndex();
if ((SelectedItem == LB_ERR) || (NewTop == LB_ERR))
{
return S_FALSE;
}
RECT ItemRect;
RECT WindowRect;
bool NeedToReposition = false;
if (OnGetItemRect(SelectedItem, &ItemRect) == LB_ERR)
{
ASSERT(FALSE);
return E_FAIL;
}
//If the Sip panel is being on
if (Input_IsInputPanelVisible())
{
//Get the corresponding listbox new height by substracting listbox top from the
//Sip panel's top
GetWindowRect(m_hwnd, &WindowRect);
int ListBoxHeightWithInputPanel = Input_GetInputPanelTop() - WindowRect.top;
if (ListBoxHeightWithInputPanel < 0)
{
goto resize_back_to_original_size;
}
//if current item's bottom is greater than new height, then it is obscured by
//the sip panel, so we need to reposition those items
if (ItemRect.bottom > ListBoxHeightWithInputPanel)
{
NeedToReposition = true;
OnSetRedraw(FALSE);
NewTop = GetNewTopIndex(m_hwnd, SelectedItem, ListBoxHeightWithInputPanel);
//set the new top index
OnSetTopIndex(NewTop);
//Check if the top index is different than it is being just set
//it means we are at very last page
if ((NewTop != OnGetTopIndex())&&(!m_ListBoxHeightChanged))
{
//Shrink the list box window to a new height
if (!SetWindowPos(
m_hwnd,
NULL,
0,
0,
RECTWIDTH(WindowRect),
ListBoxHeightWithInputPanel,
SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW
))
{
ASSERT(FALSE);
return CommonUtilities_t::GetErrorFromWin32();
}
//Set the flag variable to be TRUE
m_ListBoxHeightChanged = true;
}
}
}
else
{
resize_back_to_original_size:
//If the sip panel is being OFF and the window has been shrinked
if (m_ListBoxHeightChanged)
{
NeedToReposition = true;
OnSetRedraw(FALSE);
GetWindowRect(m_hwnd, &WindowRect);
//restore the original window height
if (!SetWindowPos(
m_hwnd,
NULL,
0,
0,
RECTWIDTH(WindowRect),
m_OriginalHeight, //restore the original height (initialized on WM_CREATE)
SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW
))
{
ASSERT(FALSE);
return CommonUtilities_t::GetErrorFromWin32();
}
//reset the flag variable back to FALSE
m_ListBoxHeightChanged = false;
}
}
//If we need to reposition, set the new top index, and redraw
if (NeedToReposition)
{
OnSetTopIndex(NewTop);
OnSetRedraw(TRUE);
}
return S_OK;
}
/*------------------------------------------------------------------------------
ListBoxImpl_t::GetNextSelectableIndex
Helper function to get the index of the next selectable item
Parameters:
IndexToSelect : the index is currently selected
IsKeyUp: indicates if the Up key is pressed or not
Returns (int): the index of next selectable item, if there is something wrong
return LB_ERR
------------------------------------------------------------------------------*/
int
ListBoxImpl_t::GetNextSelectableIndex(
UINT IndexToSelect,
bool IsKeyUp
)
{
IVoIPDisplayItem* pItem = NULL;
int ItemCount = OnGetCount();
int IndexLoop = ItemCount;
pItem = (IVoIPDisplayItem *)OnGetItemData(IndexToSelect);
if (!pItem)
{
return LB_ERR;
}
while (!pItem->IsSelectable())
{
if ((IndexToSelect == 0) && IsKeyUp)
{
IndexToSelect = - 1;
}
else
{
IndexToSelect = IsKeyUp ? IndexToSelect - 1 : (IndexToSelect + 1) % ItemCount;
}
pItem = (IVoIPDisplayItem *)OnGetItemData(IndexToSelect);
if (!pItem)
{
return LB_ERR;
}
if (-- IndexLoop <= 0)
{
return LB_ERR;
}
}
return IndexToSelect;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -