📄 listviewctrlex.cpp
字号:
reinterpret_cast<ITEM_DATA*>(
lvItem.lParam)->m_apLVItem[nColumn];
pLVItem->iItem = nItem;
pLVItem->iSubItem = nColumn;
m_pListCtrl->SetItem(pLVItem);
}
}
}
m_pListCtrl->SetColumnWidth(nColumn,
m_aColumnData[nColumn]->m_nWidth);
}
}
}
else
if (m_aColumnData[nColumn]->m_bVisible)
{
// hide column
int nPhysicalColumn = GetPhysicalIndex(nColumn);
m_aColumnData[nColumn]->m_nWidth =
m_pListCtrl->GetColumnWidth(nColumn);
m_pListCtrl->DefWindowProc(LVM_DELETECOLUMN, nPhysicalColumn, 0);
m_aColumnData[nColumn]->m_bVisible = false;
}
}
/*** Private member functions ************************************************/
/*** Compare function for sorting of list view control ***********************/
int CALLBACK CListBase::CompareFunc(LPARAM lParam1, LPARAM lParam2,
LPARAM lParamSort)
{
CListBase* pThis = reinterpret_cast<CListBase*>(lParamSort);
return pThis->m_pfnLVCompare(reinterpret_cast<ITEM_DATA*>(lParam1)->m_lParam,
reinterpret_cast<ITEM_DATA*>(lParam2)->m_lParam,
pThis->m_lParamSort);
}
/*** Create image list with sort icons ***************************************/
void CListBase::CreateSortIcons()
{
if (!m_imglstSortIcons.m_hImageList)
{
COLORMAP cm = {RGB(0, 0, 0), GetSysColor(COLOR_GRAYTEXT)};
m_imglstSortIcons.Create (9, 5, ILC_COLOR24 | ILC_MASK, 2, 0);
m_bmpUpArrow.LoadMappedBitmap(IDB_HDRUP, 0, &cm, 1);
m_nUpArrow = m_imglstSortIcons.Add(&m_bmpUpArrow, RGB(255, 255, 255));
m_bmpDownArrow.LoadMappedBitmap(IDB_HDRDOWN, 0, &cm, 1);
m_nDownArrow = m_imglstSortIcons.Add(&m_bmpDownArrow, RGB(255, 255, 255));
}
}
/*** Draw the entire item (called if window has style LVS_OWNERDRAWFIXED) ****/
void CListBase::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
ASSERT(m_pListCtrl);
LVITEM* pItem = GetLVITEM(lpDrawItemStruct->itemID);
DWORD dwStyle = m_pListCtrl->GetStyle();
bool bAlwaysSelected = pItem->state & LVIS_SELECTED &&
(dwStyle & LVS_SHOWSELALWAYS) != 0;
bool bLVHasFocus = m_pListCtrl->GetFocus() == m_pListCtrl;
bool bItemHasFocus = pItem->state & LVIS_FOCUSED && bLVHasFocus;
bool bSelected = (pItem->state & LVIS_SELECTED) != 0;
bool bReallySelected = bSelected && bLVHasFocus;
bool bFullRowSelected = (m_dwExtendedStyle & LVS_EX_FULLROWSELECT) != 0;
CRect rcItem; // rectangle bounding complete item
m_pListCtrl->GetItemRect(pItem->iItem, rcItem, LVIR_BOUNDS);
CRect rcSubItem0; // rectangle bounding subitem 0
GetRealSubItemRect(pItem->iItem, 0, LVIR_BOUNDS, rcSubItem0);
CRect rcLabel; // rectangle bounding item label
GetRealSubItemRect(pItem->iItem, 0, LVIR_LABEL, rcLabel);
CRect rcSelection; // rectangle bounding selection
if (bFullRowSelected)
{
rcSelection = rcItem;
if (IndexToOrder(0) == 0 || m_bKeepLabelLeft)
{
rcSelection.left = rcLabel.left;
int nWidthOfCol0 =
static_cast<int>(
m_pListCtrl->DefWindowProc(LVM_GETCOLUMNWIDTH, OrderToIndex(0), 0));
if (rcSelection.left > nWidthOfCol0) rcSelection.left = nWidthOfCol0;
}
}
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CBrush brushHiLite;
DWORD dwNormalText = GetSysColor(COLOR_WINDOWTEXT);
DWORD dwHiLiteBk = 0;
if (bReallySelected)
{
dwHiLiteBk =
pItem->iItem == m_nHotItem ? m_dwHotLite : GetSysColor(COLOR_HIGHLIGHT);
brushHiLite.CreateSolidBrush(dwHiLiteBk);
}
else if (bAlwaysSelected)
{
dwHiLiteBk = GetSysColor(COLOR_3DFACE);
brushHiLite.CreateSolidBrush(dwHiLiteBk);
}
CFont* pfontPrev = 0;
CFont* pfontHotUnderlined = 0;
bool bHotUnderlining = false;
if (m_dwExtendedStyle & LVS_EX_TWOCLICKACTIVATE &&
(bSelected || bAlwaysSelected) ||
(m_dwExtendedStyle & (LVS_EX_UNDERLINEHOT | LVS_EX_ONECLICKACTIVATE)) ==
(LVS_EX_UNDERLINEHOT | LVS_EX_ONECLICKACTIVATE) &&
pItem->iItem == m_nHotItem)
{
CFont* pFont = m_pListCtrl->GetFont();
LOGFONT logFont;
if (pFont->GetLogFont(&logFont))
{
logFont.lfUnderline = TRUE;
pfontHotUnderlined = new CFont;
pfontHotUnderlined->CreateFontIndirect(&logFont);
pfontPrev = pDC->SelectObject(pfontHotUnderlined);
bHotUnderlining = true;
}
}
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH;
// display all subitems
int nIndex;
for (int nColumn = 0;
m_pListCtrl->DefWindowProc(LVM_GETCOLUMN,
nIndex = OrderToIndex(nColumn),
reinterpret_cast<LPARAM>(&lvc));
nColumn++)
{
LVITEM* pSubItem = nIndex > 0 ? GetLVITEM(pItem->iItem, nIndex) : pItem;
CRect rcSubItem; // rectangle bounding subitem
CRect rcText; // output rectangle
int nAbsSortColumn = abs(m_nSortColumn) - 1;
// background color of current column
DWORD dwBkColor = m_bColorSortColumn &&
m_nSortColumn != 0 &&
m_aColumnData[nAbsSortColumn]->m_bVisible &&
nIndex == GetPhysicalIndex(nAbsSortColumn) ?
m_dwColSortColor : m_pListCtrl->GetBkColor();
CBrush brushBk(dwBkColor);
// consider column margins
if (nColumn > 0)
{
// move output rectangle over next column
rcSubItem.left = rcSubItem.right;
rcSubItem.right += lvc.cx;
}
else
{
rcSubItem = rcItem;
rcSubItem.right = rcSubItem.left + lvc.cx;
}
if (nIndex == 0 && !m_bKeepLabelLeft || nColumn == 0 && m_bKeepLabelLeft)
{
rcText = rcLabel;
rcText.left += m_nFirstColXOff;
rcText.right -= nIndex > 0 ? m_nNextColXOff : m_nFirstColXOff;
}
else
{
rcText = rcSubItem;
rcText.left += m_nNextColXOff;
rcText.right -= m_nNextColXOff;
// take subitem image into consideration
if (!m_bKeepLabelLeft &&
nIndex > 0 &&
m_dwExtendedStyle & LVS_EX_SUBITEMIMAGES &&
pSubItem->iImage)
{
CRect rcIcon;
if (m_pListCtrl->GetSubItemRect(pItem->iItem, nIndex, LVIR_ICON,
rcIcon)) rcText.left += rcIcon.Width();
}
}
int nLabelWidth = GetLabelWidth(pDC, pSubItem, rcText.Width());
bool bHiLite = false;
if (bReallySelected ||
bAlwaysSelected ||
bItemHasFocus && !bFullRowSelected)
if (nIndex == 0 && nColumn != 0 && !m_bKeepLabelLeft && !bFullRowSelected
||
nColumn == 0 && (m_bKeepLabelLeft || nIndex == 0))
{
// calculate selection area
CRect rcSubItemSelection(rcLabel);
if (!bFullRowSelected)
{
int nFormat = nIndex == 0 && nColumn == 0 || !m_bKeepLabelLeft ?
m_nFormatOfSubItem0 : lvc.fmt & LVCFMT_JUSTIFYMASK;
switch (nFormat)
{
case LVCFMT_LEFT:
rcSubItemSelection.right =
rcSubItemSelection.left +
m_nFirstColXOff + nLabelWidth + m_nNextColXOff;
break;
case LVCFMT_RIGHT:
rcSubItemSelection.left =
rcSubItemSelection.right -
m_nFirstColXOff - nLabelWidth - m_nNextColXOff;
break;
case LVCFMT_CENTER:
{
int nSelectionWidth =
m_nNextColXOff + nLabelWidth + m_nNextColXOff;
rcSubItemSelection.left =
rcLabel.left + (rcLabel.Width() - nSelectionWidth) / 2;
rcSubItemSelection.right =
rcSubItemSelection.left + nSelectionWidth;
break;
}
default:
ASSERT(false);
break;
}
if (rcSubItemSelection.left < rcLabel.left)
rcSubItemSelection.left = rcLabel.left;
if (rcSubItemSelection.right > rcLabel.right)
rcSubItemSelection.right = rcLabel.right;
rcSelection = rcSubItemSelection;
}
if (bReallySelected || bAlwaysSelected)
{
if (rcSubItemSelection.left > rcSubItem.left)
{
// fill area left from selection with background color
CRect rc(rcSubItem);
rc.right = rcSubItemSelection.left-1;
CBrush brush(dwBkColor);
pDC->FillRect(rc, &brushBk);
}
// fill selection area with highlight color
pDC->FillRect(rcSubItemSelection, &brushHiLite);
// fill area right from selection with background color
if (rcSubItemSelection.right < rcSubItem.right)
{
CRect rc(rcSubItem);
rc.left = rcSubItemSelection.right+1;
CBrush brush(dwBkColor);
pDC->FillRect(rc, &brushBk);
}
pDC->SetBkColor (dwHiLiteBk);
pDC->SetTextColor(
bReallySelected ? GetSysColor(COLOR_HIGHLIGHTTEXT) :
bHotUnderlining ? m_dwHotLite :
dwNormalText);
bHiLite = true;
}
}
else
if (bFullRowSelected)
{
pDC->FillRect (rcSubItem, &brushHiLite);
pDC->SetBkColor (dwHiLiteBk);
pDC->SetTextColor(
bReallySelected ? GetSysColor(COLOR_HIGHLIGHTTEXT) :
bHotUnderlining ? m_dwHotLite :
dwNormalText);
bHiLite = true;
}
if (!bHiLite)
{
pDC->FillRect (rcSubItem, &brushBk);
pDC->SetBkColor (dwBkColor);
pDC->SetTextColor(bHotUnderlining ? m_dwHotLite : dwNormalText);
}
if (!m_bKeepLabelLeft && nIndex == 0 ||
m_bKeepLabelLeft && nColumn == 0)
{
CRect rcIcon;
if (GetStateIconRect(pItem->iItem, rcIcon))
DrawStateIcon(pDC, pItem, rcIcon);
}
if (!m_bKeepLabelLeft &&
(nIndex == 0 ||
m_dwExtendedStyle & LVS_EX_SUBITEMIMAGES && pSubItem->iImage > 0) ||
m_bKeepLabelLeft && nColumn == 0)
{
CRect rcIcon;
if (GetRealSubItemRect(pItem->iItem, m_bKeepLabelLeft ? 0 : nIndex,
LVIR_ICON, rcIcon))
{
LVITEM* pLogicalItem;
NMLVDISPINFO lvDispInfo;
if (dwStyle & LVS_OWNERDATA)
{
lvDispInfo.hdr.hwndFrom = m_pListCtrl->m_hWnd;
lvDispInfo.hdr.idFrom = m_pListCtrl->GetDlgCtrlID();
lvDispInfo.hdr.code = LVN_GETDISPINFO;
lvDispInfo.item.mask = LVIF_IMAGE;
lvDispInfo.item.iItem = pItem->iItem;
lvDispInfo.item.iSubItem = 0;
OnGetdispinfo(&lvDispInfo.hdr);
pLogicalItem = &lvDispInfo.item;
}
else
pLogicalItem =
reinterpret_cast<ITEM_DATA*>(pItem->lParam)->m_apLVItem[0];
// take state of the physical item!
pLogicalItem->state = pItem->state;
pLogicalItem->stateMask = pItem->stateMask;
DrawSmallIcon(pDC, pLogicalItem, rcIcon);
pLogicalItem->state = 0;
pLogicalItem->stateMask = 0;
}
}
pSubItem->iSubItem = GetLogicalIndex(pSubItem->iSubItem);
lvc.iSubItem = pSubItem->iSubItem;
DrawSubItemText(pDC, pSubItem, &lvc, rcText);
if (nIndex > 0)
{
delete[] pSubItem->pszText;
delete pSubItem;
}
}
if (bHotUnderlining)
{
pDC->SelectObject(pfontPrev);
delete pfontHotUnderlined;
}
delete[] pItem->pszText;
delete pItem;
// If item has focus draw focus rectangle
if (bItemHasFocus)
{
pDC->SetTextColor (dwNormalText);
pDC->DrawFocusRect(rcSelection);
}
}
/*** Calculate width of item or subitem label ********************************/
int CListBase::GetLabelWidth(CDC* pDC, LVITEM* pItem, int nMaxWidth) const
{
if (nMaxWidth > 0 && *pItem->pszText)
return
__min(pDC->GetTextExtent(pItem->pszText,
static_cast<int>(_tcslen(pItem->pszText))).cx,
nMaxWidth);
else
return 0;
}
/*** Retrieve for a given physical column number the logical column number ***/
int CListBase::GetLogicalIndex(int nPhysicalIndex) const
{
INT_PTR nColumnCount = m_aColumnData.GetSize();
for (int i = 0; i < nColumnCount; i++)
if (m_aColumnData[i]->m_bVisible)
{
if (i == nPhysicalIndex) return nPhysicalIndex;
}
else
nPhysicalIndex++;
ASSERT(false);
return -1;
}
/*** Retrieve for a given physical column order the logical column order *****/
int CListBase::GetLogicalOrder(int nPhysicalOrder) const
{
for (int i = 0; i <= nPhysicalOrder; i++)
for (INT_PTR j = m_aColumnData.GetUpperBound(); j >= 0; j--)
if (m_aColumnData[j]->m_nOrder == i)
{
if (m_aColumnData[j]->m_bVisible)
{
if (i == nPhysicalOrder) return nPhysicalOrder;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -