📄 listviewctrlex.cpp
字号:
{
ASSERT( m_pListCtrl );
if( nItem >= m_pListCtrl->CListCtrl::GetItemCount() || nItem < 0 ) return FALSE;
CItemData* pData = reinterpret_cast<CItemData*>( m_pListCtrl->CListCtrl::GetItemData(nItem) );
ASSERT( pData );
return pData->GetBold();
}
/*** 设置或获取项的重要标记状态 ***/
void CListBase::SetRedFlagItem( int nItem, BOOL bRedFlag )
{
ASSERT( m_pListCtrl );
if( nItem >= m_pListCtrl->CListCtrl::GetItemCount() || nItem < 0 ) return ;
CItemData* pData = reinterpret_cast<CItemData*>( m_pListCtrl->CListCtrl::GetItemData(nItem) );
ASSERT( pData );
if( pData->GetRedFlag() != bRedFlag )
{
pData->SetRedFlag( bRedFlag );
m_pListCtrl->CListCtrl::RedrawItems( nItem,nItem );
}
}
BOOL CListBase::GetRedFlagItem( int nItem )
{
ASSERT( m_pListCtrl );
if( nItem >= m_pListCtrl->CListCtrl::GetItemCount() || nItem < 0 ) return FALSE;
CItemData* pData = reinterpret_cast<CItemData*>( m_pListCtrl->CListCtrl::GetItemData(nItem) );
ASSERT( pData );
return pData->GetRedFlag();
}
/*** A column header has been clicked ****************************************/
BOOL CListBase::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = reinterpret_cast<NM_LISTVIEW*>(pNMHDR);
int nSortColumn = pNMListView->iSubItem + 1;
if (nSortColumn == abs(m_nSortColumn))
m_nSortColumn = -m_nSortColumn;
else
m_nSortColumn = nSortColumn;
SetSortIcon();
*pResult = 0;
return FALSE;
}
/*** 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:
if (m_bColorSortColumn)
{
pNMLVCustomDraw->clrTextBk =
pNMLVCustomDraw->iSubItem + 1 == abs(m_nSortColumn) ?
m_dwColSortColor : m_pListCtrl->GetBkColor();
*pResult = CDRF_NEWFONT;
}
else
*pResult = CDRF_DODEFAULT;
if (pNMLVCustomDraw->iSubItem == 0) *pResult |= CDRF_NOTIFYPOSTPAINT;
break;
case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
{
// special treatment for first column:
// fill empty area left of text label
ASSERT(pNMLVCustomDraw->iSubItem == 0);
CRect rect;
m_pListCtrl->GetHeaderCtrl()->GetItemRect(0, rect);
int nColumnWidth = rect.Width();
int nLeftX = rect.left - m_pListCtrl->GetScrollPos(SB_HORZ);
bool bFirstColumn = rect.left == 0;
bool bHasFocus = m_pListCtrl->GetFocus() == m_pListCtrl;
m_pListCtrl->GetItemRect(static_cast<int>(
pNMLVCustomDraw->nmcd.dwItemSpec), rect, LVIR_LABEL);
CDC* pDC = CDC::FromHandle(pNMLVCustomDraw->nmcd.hdc);
CBrush brushColColor;
int nSortColumn = abs(m_nSortColumn);
DWORD dwExStyle = m_pListCtrl->GetExtendedStyle();
bool bFullRowSelect = (dwExStyle & LVS_EX_FULLROWSELECT) != 0;
LVITEM item;
item.mask = LVIF_IMAGE | LVIF_STATE;
item.iItem = static_cast<int>(pNMLVCustomDraw->nmcd.dwItemSpec);
item.iSubItem = 0;
item.stateMask = LVIS_SELECTED | LVIS_FOCUSED | LVIS_STATEIMAGEMASK;
m_pListCtrl->GetItem(&item);
if (!bFirstColumn &&
bFullRowSelect &&
item.state & LVIS_SELECTED &&
bHasFocus)
// create brush with highlight color
brushColColor.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
else if (!bFirstColumn &&
bFullRowSelect &&
item.state & LVIS_SELECTED &&
m_pListCtrl->GetStyle() & LVS_SHOWSELALWAYS)
// create brush with highlight (nonfocus) color
brushColColor.CreateSolidBrush(GetSysColor(COLOR_3DFACE));
else if (m_bColorSortColumn && nSortColumn == 1)
// create brush with sort color
brushColColor.CreateSolidBrush(m_dwColSortColor);
else
// create brush with normal background color
brushColColor.CreateSolidBrush(m_pListCtrl->GetBkColor());
// select new brush and save previous brush
CBrush* pbrushPrev = pDC->SelectObject(&brushColColor);
// color area left of text label
pDC->PatBlt(nLeftX, rect.top, __min(rect.left, rect.right) - nLeftX,
rect.Height(), PATCOPY);
if (nColumnWidth > m_nIconXOff)
{
// draw state icon
CImageList* pimglst = m_pListCtrl->GetImageList(LVSIL_STATE);
if (pimglst)
{
int nImage = (item.state & LVIS_STATEIMAGEMASK) >> 12;
if (nImage > 0)
{
IMAGEINFO imgInfo;
// image indices are zero-based
if (pimglst->GetImageInfo(--nImage, &imgInfo) &&
GetStateIconRect(item.iItem, rect))
pimglst->DrawIndirect(
pDC, nImage, rect.TopLeft(),
CSize(__min(rect.Width(),
imgInfo.rcImage.right - imgInfo.rcImage.left),
__min(rect.Height(),
imgInfo.rcImage.bottom - imgInfo.rcImage.top)),
CPoint(0, 0),
item.state & LVIS_SELECTED && bHasFocus ?
ILD_SELECTED : ILD_NORMAL,
SRCCOPY, CLR_NONE);
}
}
// draw small icon
pimglst = m_pListCtrl->GetImageList(LVSIL_SMALL);
if (pimglst)
if (item.iImage > 0)
{
IMAGEINFO imgInfo;
if (pimglst->GetImageInfo(item.iImage, &imgInfo) &&
m_pListCtrl->GetItemRect(item.iItem, rect, LVIR_ICON))
{
int nIconOffset = rect.left - nLeftX;
if (nColumnWidth > nIconOffset)
pimglst->DrawIndirect(
pDC, item.iImage, rect.TopLeft(),
CSize(__min(nColumnWidth - nIconOffset,
imgInfo.rcImage.right - imgInfo.rcImage.left),
__min(rect.Height(),
imgInfo.rcImage.bottom - imgInfo.rcImage.top)),
CPoint(0, 0),
item.state & LVIS_SELECTED && bHasFocus ?
ILD_SELECTED : ILD_NORMAL,
SRCCOPY, CLR_NONE);
}
}
}
// restore previous brush
pDC->SelectObject(pbrushPrev);
*pResult = CDRF_DODEFAULT;
break;
}
default:
*pResult = CDRF_DODEFAULT;
break;
}
}
/*** The background will be erased *******************************************/
bool CListBase::OnEraseBkgnd(CDC* pDC)
{
ASSERT(m_pListCtrl);
if (m_bColorSortColumn)
{
CRect rect;
if (!m_pListCtrl->GetHeaderCtrl()->GetItemRect(
abs(m_nSortColumn) - 1, rect)) return false;
int nXScrlOff = m_pListCtrl->GetScrollPos(SB_HORZ);
int nLeftX = rect.left - nXScrlOff;
int nRightX = rect.right - nXScrlOff;
pDC->GetClipBox(&rect); // get area to be erased
if (nLeftX < rect.right && nRightX > rect.left)
{
CBrush brushNormalColor(m_pListCtrl->GetBkColor());
CBrush brushSortColor(m_dwColSortColor);
CBrush* pbrushPrev = 0;
if (nLeftX > rect.left)
{
// select brush with normal background color and save default brush
pbrushPrev = pDC->SelectObject(&brushNormalColor);
// erase area left from sort column with normal background color
pDC->PatBlt(rect.left, rect.top, nLeftX - rect.left, rect.Height(),
PATCOPY);
}
// select brush with sort color and save default brush
if (pbrushPrev)
pDC->SelectObject(&brushSortColor);
else
pbrushPrev = pDC->SelectObject(&brushSortColor);
// erase area inside sort column with sort color
if (nLeftX < rect.left)
if (nRightX < rect.right)
pDC->PatBlt(rect.left, rect.top, nRightX - rect.left,
rect.Height(), PATCOPY);
else
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(),
PATCOPY);
else
if (nRightX < rect.right)
pDC->PatBlt(nLeftX, rect.top, nRightX - nLeftX, rect.Height(),
PATCOPY);
else
pDC->PatBlt(nLeftX, rect.top, rect.right - nLeftX, rect.Height(),
PATCOPY);
if (nRightX < rect.right)
{
// select brush with normal background color
pDC->SelectObject(&brushNormalColor);
// color area right from sort column
pDC->PatBlt(nRightX, rect.top, rect.right - nRightX, rect.Height(),
PATCOPY);
}
// restore previous brush
pDC->SelectObject(pbrushPrev);
return true;
}
else
return false;
}
else
return false;
}
/*** A key has been pressed *************************************************/
bool CListBase::OnKeyDown(UINT nChar)
{
ASSERT(m_pListCtrl);
switch (nChar)
{
// Numpad-Plus
case VK_ADD:
// Ctrl-Numpad-Plus --> set optimum width for all columns
if (m_bControl && m_bKeepLabelLeft && IndexToOrder(0) > 0)
{
LVCOLUMN lvc;
lvc.mask = LVCF_FMT;
int nIndex;
for (int nColumn = 0;
m_pListCtrl->GetColumn(nIndex = OrderToIndex(nColumn), &lvc);
nColumn++)
{
int nOptWidth;
if (nIndex == 0 || nColumn == 0)
{
// calculate needed column width
nOptWidth = 0;
for (int nItem = m_pListCtrl->GetItemCount(); --nItem >= 0;)
{
int nWidth =
m_pListCtrl->GetStringWidth(
m_pListCtrl->GetItemText(nItem, nIndex));
if (nWidth > nOptWidth) nOptWidth = nWidth;
}
if (nIndex > 0)
{
// add space for state icon and small icon
CRect rcSubItem;
if (GetRealSubItemRect(0, nIndex, LVIR_BOUNDS, rcSubItem))
{
CRect rcLabel;
if (GetRealSubItemRect(0, nIndex, LVIR_LABEL, rcLabel))
nOptWidth += rcLabel.left - rcSubItem.left;
}
// add left offset
nOptWidth += m_nFirstColXOff;
}
else
// add left offset
nOptWidth += m_nNextColXOff;
// add right offset
nOptWidth += m_nNextColXOff;
}
else
nOptWidth = LVSCW_AUTOSIZE;
m_pListCtrl->SetColumnWidth(nIndex, nOptWidth);
}
return true;
}
break;
// Ctrl
case VK_CONTROL:
if (m_bKeepLabelLeft && IndexToOrder(0) > 0) return m_bControl = true;
break;
// All other keys
default:
break;
}
return false;
}
/*** A key has been released *************************************************/
void CListBase::OnKeyUp(UINT nChar)
{
if (nChar == VK_CONTROL) m_bControl = false;
}
/*** List control loses input focus ******************************************/
void CListBase::OnKillFocus()
{
ASSERT(m_pListCtrl);
// manually remove focus state so that custom drawing will function properly
int nItem = m_pListCtrl->GetNextItem(-1, LVNI_SELECTED);
if (nItem >= 0) m_pListCtrl->SetItemState(nItem, 0, LVIS_FOCUSED);
}
/*** The user double-clicks the left mouse button ****************************/
bool CListBase::OnLButtonDblClk(CPoint point)
{
ASSERT(m_pListCtrl);
if (m_pListCtrl->GetStyle() & LVS_OWNERDRAWFIXED)
{
UINT flags;
int nItem = HitTest(point, &flags);
if (nItem >= 0 &&
m_pListCtrl->GetExtendedStyle() & LVS_EX_CHECKBOXES &&
flags == LVHT_ONITEMSTATEICON)
{
m_pListCtrl->SetCheck(nItem, !m_pListCtrl->GetCheck(nItem));
return true;
}
else
return false;
}
else
return false;
}
/*** The user presses the left mouse button **********************************/
bool CListBase::OnLButtonDown(CPoint point)
{
ASSERT(m_pListCtrl);
if (m_pListCtrl->GetStyle() & LVS_OWNERDRAWFIXED)
{
UINT flags;
int nItem = HitTest(point, &flags);
if (nItem >= 0 &&
m_pListCtrl->GetExtendedStyle() & LVS_EX_CHECKBOXES &&
flags == LVHT_ONITEMSTATEICON)
{
m_pListCtrl->SetCheck(nItem, !m_pListCtrl->GetCheck(nItem));
return true;
}
else
return false;
}
else
return false;
}
/*** Divider in header control has been dragged ******************************/
bool CListBase::OnNotify(LPARAM lParam)
{
ASSERT(m_pListCtrl);
ASSERT(m_pListCtrl->GetHeaderCtrl());
NMHEADER* pNMHdr = reinterpret_cast<NMHEADER*>(lParam);
if (pNMHdr->hdr.hwndFrom == m_pListCtrl->GetHeaderCtrl()->m_hWnd)
switch (pNMHdr->hdr.code)
{
case HDN_ENDTRACKW:
case HDN_ENDTRACKA:
case HDN_ITEMCHANGEDW:
case HDN_ITEMCHANGEDA:
if (m_bColorSortColumn) InvalidateNonItemArea();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -