📄 listviewctrlex.cpp
字号:
}
else
nPhysicalOrder++;
break;
}
ASSERT(false);
return -1;
}
/*** Get all attributes of a given physical item or subitem ******************/
LVITEM* CListBase::GetLVITEM(int nItem, int nSubItem) const
{
ASSERT(m_pListCtrl);
LVITEM* pItem = new LVITEM;
pItem->mask = LVIF_IMAGE | LVIF_STATE | LVIF_TEXT | LVIF_PARAM;
pItem->iItem = nItem;
pItem->iSubItem = nSubItem;
pItem->stateMask = ~0U;
// enlarge text buffer gradually until it's large enough
for (int nLen = 128;; nLen += nLen)
{
LPTSTR pszText = new TCHAR[nLen];
pItem->cchTextMax = nLen;
pItem->pszText = pszText;
if (m_pListCtrl->DefWindowProc(LVM_GETITEM, 0,
reinterpret_cast<LPARAM>(pItem)))
{
if (pItem->pszText != pszText)
{
// Windows hasn't used our buffer!
_tcsncpy(pszText, pItem->pszText, nLen-1);
pszText[nLen-1] = _T('\0');
pItem->pszText = pszText;
}
}
else
{
delete[] pszText;
delete pItem;
return 0;
}
if (static_cast<int>(_tcslen(pItem->pszText)) < nLen-1) break;
delete[] pItem->pszText;
}
return pItem;
}
/*** Returns the physical index of a given column index **********************/
int CListBase::GetPhysicalIndex(int nColumnIndex) const
{
int nIndex = 0;
for (int i = 0; i < nColumnIndex; i++)
if (m_aColumnData[i]->m_bVisible) nIndex++;
return nIndex;
}
/*** Returns the physical order of a given column order **********************/
int CListBase::GetPhysicalOrder(int nColumnOrder) const
{
int nOrder = 0;
for (int i = 0; i < nColumnOrder; i++)
for (INT_PTR j = m_aColumnData.GetUpperBound(); j >= 0; j--)
if (m_aColumnData[j]->m_nOrder == i)
{
if (m_aColumnData[j]->m_bVisible) nOrder++;
break;
}
return nOrder;
}
/*** Calculates the bounding rectangle of a subitem. ***/
/*** Difference to GetSubItemRect: ***/
/*** If the bounding rectangle of subitem 0 is requested, the function ***/
/*** returns the bounding rectangle of the label including the icons only, ***/
/*** not the bounding rectangle of the whole item. ***/
bool CListBase::GetRealSubItemRect(int iItem, int iSubItem, int nArea,
CRect& ref)
{
ASSERT(m_pListCtrl);
ASSERT(iSubItem >= 0);
switch (nArea)
{
case LVIR_BOUNDS:
if (m_pListCtrl->GetSubItemRect(iItem, iSubItem, LVIR_BOUNDS, ref))
if (iSubItem == 0)
{
CRect rcLabel;
if (m_pListCtrl->GetSubItemRect(iItem, 0, LVIR_LABEL, rcLabel))
{
ref.right = rcLabel.right;
int nOrder = IndexToOrder(0);
if (nOrder > 0)
{
// The left edge of subitem 0 is identical with the right edge of
// the subitem left of subitem 0.
CRect rcSubItem;
if (m_pListCtrl->GetSubItemRect(iItem, OrderToIndex(nOrder - 1),
LVIR_BOUNDS, rcSubItem))
{
ref.left = rcSubItem.right;
return true;
}
}
else
return true;
}
}
else
return true;
break;
case LVIR_ICON:
{
CRect rcIcon; // rectangle bounding small icon
if (m_pListCtrl->GetSubItemRect(iItem, iSubItem, LVIR_ICON, rcIcon))
{
CRect rcSubItem; // rectangle bounding subitem
if (GetRealSubItemRect(iItem, iSubItem, LVIR_BOUNDS, rcSubItem))
if (m_bKeepLabelLeft && iSubItem == 0 && IndexToOrder(0) > 0)
{
int nIndex = OrderToIndex(0);
if (GetRealSubItemRect(iItem, nIndex, LVIR_BOUNDS, ref))
{
int nSmallIconXOff = rcIcon.left - rcSubItem.left;
ref.left += nSmallIconXOff;
ref.right = ref.left + rcIcon.Width();
// clip rectangle at right edge if necessary
INT_PTR nWidth =
m_pListCtrl->DefWindowProc(LVM_GETCOLUMNWIDTH, nIndex, 0);
if (nSmallIconXOff + ref.Width() >= nWidth)
ref.right = ref.left - nSmallIconXOff + nWidth - 1;
return true;
}
}
else if ( m_bKeepLabelLeft && iSubItem == 0 ||
!m_bKeepLabelLeft && iSubItem >= 0)
{
// clip rectangle at right edge if necessary
if (rcIcon.right > rcSubItem.right)
rcIcon.right = rcSubItem.right;
ref = rcIcon;
return true;
}
}
break;
}
case LVIR_LABEL:
{
CRect rcLabel; // rectangle bounding label of subitem 0
if (m_pListCtrl->GetSubItemRect(iItem, 0, LVIR_LABEL, rcLabel))
{
CRect rcSubItem0; // rectangle bounding subitem 0
if (GetRealSubItemRect(iItem, 0, LVIR_BOUNDS, rcSubItem0))
if (IndexToOrder(0) > 0 && m_bKeepLabelLeft)
{
if (GetRealSubItemRect(iItem, OrderToIndex(0), LVIR_BOUNDS, ref))
{
ref.left += rcLabel.left - rcSubItem0.left;
return true;
}
}
else
{
ref = rcLabel;
return true;
}
}
break;
}
default:
ASSERT(false);
break;
}
return false;
}
/*** Retrieves the bounding rectangle for the state icon of an item **********/
bool CListBase::GetStateIconRect(int nItem, LPRECT pRect)
{
CRect rcSubItem;
if (GetRealSubItemRect(nItem, m_bKeepLabelLeft ? OrderToIndex(0) : 0,
LVIR_BOUNDS, rcSubItem))
{
CRect rcSmallIcon;
if (GetRealSubItemRect(nItem, 0, LVIR_ICON, rcSmallIcon))
{
*pRect = rcSubItem;
pRect->right = rcSmallIcon.left;
if (rcSmallIcon.right > rcSmallIcon.left) pRect->right--;
// calculate x-offset of state icon
if (!m_bIconXOffCalculated)
{
ASSERT(m_pListCtrl);
CImageList* pImageList = m_pListCtrl->GetImageList(LVSIL_STATE);
if (pImageList)
{
// retrieve width of state icon
IMAGEINFO ii = {0, 0, 0, 0};
if (pImageList->GetImageInfo(0, &ii))
{
int nXOff = pRect->right - (ii.rcImage.right - ii.rcImage.left) -
pRect->left;
if (nXOff < 0)
m_nIconXOff = 0;
else if (nXOff < 4)
m_nIconXOff = nXOff;
else
m_nIconXOff = 4;
}
else
m_nIconXOff = 4;
}
else
m_nIconXOff = 4;
m_bIconXOffCalculated = true;
}
pRect->left += m_nIconXOff;
// clip at right column border
int nWidth = rcSubItem.Width();
if (pRect->right >= rcSubItem.left + nWidth)
pRect->right = pRect->left - m_nIconXOff + nWidth - 1;
return true;
}
}
return false;
}
/*** Return the order in the header control of a subitem, based on its index */
int CListBase::IndexToOrder(int nIndex)
{
ASSERT(m_pListCtrl);
ASSERT(m_pListCtrl->GetHeaderCtrl());
HDITEM headerItem = {HDI_ORDER};
return m_pListCtrl->GetHeaderCtrl()->GetItem(nIndex, &headerItem) ?
headerItem.iOrder : -1;
}
/*** Invalidate client area not covered by list control items ****************/
void CListBase::InvalidateNonItemArea()
{
ASSERT(m_pListCtrl);
int nTopIndex = m_pListCtrl->GetTopIndex();
if (nTopIndex >= 0)
{
// update coloring of sort column
CRect rectHdrItem;
ASSERT(m_pListCtrl->GetHeaderCtrl());
if (m_pListCtrl->GetHeaderCtrl()->GetItemRect(
abs(m_nSortColumn) - 1, rectHdrItem))
{
// erase area above top item
CRect rectThis;
m_pListCtrl->GetClientRect(rectThis);
CRect rectItem;
m_pListCtrl->GetItemRect(nTopIndex, rectItem, LVIR_BOUNDS);
CRect rectToBeErased(rectThis.left, rectHdrItem.bottom,
rectThis.right, rectItem.top);
m_pListCtrl->InvalidateRect(rectToBeErased);
// erase area below bottom item
m_pListCtrl->GetItemRect(m_pListCtrl->GetItemCount() - 1, rectItem,
LVIR_BOUNDS);
if (rectItem.bottom < rectThis.bottom)
{
rectToBeErased.top = rectItem.bottom;
rectToBeErased.bottom = rectThis.bottom;
}
m_pListCtrl->InvalidateRect(rectToBeErased);
}
}
}
/*** Rejustify first column of listview control to enable a right- ***********/
/*** justified or centerd first column ***********/
void CListBase::JustifyFirstColumn(int nFormat)
{
ASSERT(m_pListCtrl);
m_nFormatOfSubItem0 = nFormat;
if (m_pListCtrl->GetStyle() & LVS_OWNERDRAWFIXED ||
m_dwExtendedStyle & LVS_EX_FULLROWSELECT)
{
CHeaderCtrl* pHeaderCtrl = m_pListCtrl->GetHeaderCtrl();
ASSERT(pHeaderCtrl);
HDITEM hdrItem;
hdrItem.mask = HDI_FORMAT;
if (pHeaderCtrl->GetItem(0, &hdrItem))
{
hdrItem.fmt =
hdrItem.fmt & ~HDF_JUSTIFYMASK | nFormat & HDF_JUSTIFYMASK;
pHeaderCtrl->SetItem(0, &hdrItem);
}
}
}
/*** A column header has been clicked ****************************************/
BOOL CListBase::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult)
{
NMLISTVIEW* pNMListView = reinterpret_cast<NMLISTVIEW*>(pNMHDR);
int nAbsSortColumn = abs(m_nSortColumn);
pNMListView->iSubItem = GetLogicalIndex(pNMListView->iSubItem);
if (nAbsSortColumn > 0)
if (pNMListView->iSubItem == nAbsSortColumn-1)
m_nSortColumn = -m_nSortColumn;
else
m_nSortColumn = pNMListView->iSubItem + 1;
else
m_nSortColumn = pNMListView->iSubItem + 1;
SetSortIcon();
*pResult = 0;
return FALSE;
}
/*** An item in the column selection menu has been selected ******************/
BOOL CListBase::OnCommand(WPARAM wParam)
{
if (HIWORD(wParam) == 0)
ShowColumn(static_cast<int>(wParam), !m_aColumnData[wParam]->m_bVisible);
return TRUE;
}
/*** The user has right clicked the mouse ************************************/
void CListBase::OnContextMenu(CWnd* pWnd)
{
ASSERT(m_pListCtrl);
if (pWnd == m_pListCtrl->GetHeaderCtrl())
if (m_nColumnHidingAllowed)
{
CMenu menu;
if (menu.CreatePopupMenu())
{
for (INT_PTR i = m_aColumnData.GetUpperBound(); i >= 0; i--)
menu.InsertMenu(0,
MF_BYPOSITION |
(m_aColumnData[i]->m_bVisible ? MF_CHECKED : MF_UNCHECKED) |
(m_aColumnData[i]->m_bHidingAllowed ? 0 : MF_GRAYED) |
MF_STRING, i, m_aColumnData[i]->m_pLVColumn->pszText);
CPoint pt(0, 0);
GetCursorPos (&pt);
menu.TrackPopupMenu(TPM_LEFTALIGN, pt.x, pt.y, m_pListCtrl, 0);
}
}
}
/*** A list view (sub)item will be drawn *************************************/
void CListBase::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
ASSERT(m_pListCtrl);
ASSERT(m_pListCtrl->GetHeaderCtrl());
NMLVCUSTOMDRAW* pNMLVCustomDraw = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
switch (pNMLVCustomDraw->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYITEMDRAW;
break;
case CDDS_ITEMPREPAINT:
*pResult = CDRF_NOTIFYSUBITEMDRAW;
break;
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -