📄 listviewctrlex.cpp
字号:
break;
case HDN_DIVIDERDBLCLICKW:
case HDN_DIVIDERDBLCLICKA:
if (m_bKeepLabelLeft &&
(pNMHdr->iItem > 0 && IndexToOrder(pNMHdr->iItem) == 0 ||
pNMHdr->iItem == 0 && IndexToOrder(pNMHdr->iItem) > 0))
{
// calculate needed column width
int nOptWidth = 0;
for (int nItem = m_pListCtrl->GetItemCount(); --nItem >= 0;)
{
int nWidth =
m_pListCtrl->GetStringWidth(
m_pListCtrl->GetItemText(nItem, pNMHdr->iItem));
if (nWidth > nOptWidth) nOptWidth = nWidth;
}
if (pNMHdr->iItem > 0)
{
// add space for state icon and small icon
CRect rcSubItem;
if (GetRealSubItemRect(0, pNMHdr->iItem, LVIR_BOUNDS, rcSubItem))
{
CRect rcLabel;
if (GetRealSubItemRect(0, pNMHdr->iItem, 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;
m_pListCtrl->SetColumnWidth(pNMHdr->iItem, nOptWidth);
return true;
}
break;
default:
break;
}
return false;
}
/*** List control gains input focus ******************************************/
void CListBase::OnSetFocus()
{
ASSERT(m_pListCtrl);
// manually set focus state so that custom drawing will function properly
int nItem = m_pListCtrl->GetNextItem(-1, LVNI_SELECTED);
if (nItem >= 0) m_pListCtrl->SetItemState(nItem, LVIS_FOCUSED, LVIS_FOCUSED);
}
/*** System colors have been changed *****************************************/
void CListBase::OnSysColorChange()
{
ASSERT(m_pListCtrl);
ASSERT(m_pListCtrl->GetHeaderCtrl());
// update color of sort icon
m_imglstSortIcons.DeleteImageList ();
m_bmpUpArrow.DeleteObject ();
m_bmpDownArrow.DeleteObject ();
CreateSortIcons ();
m_pListCtrl->GetHeaderCtrl()->SetImageList(&m_imglstSortIcons);
SetSortIcon ();
// force update of column colors
m_bColorSortColumn = !m_bColorSortColumn;
ColorSortColumn(!m_bColorSortColumn);
}
/*** Assigns an image list to a list control *********************************/
CImageList* CListBase::SetImageList(CImageList* pImageList, int nImageList)
{
ASSERT(m_pListCtrl);
ASSERT(m_pListCtrl->GetHeaderCtrl());
CImageList* pimglstPrev =
m_pListCtrl->CListCtrl::SetImageList(pImageList, nImageList);
if (nImageList == LVSIL_SMALL)
{
// restore image list with sort icons because default behavior is that the
// header control shares its image list with the small icon list of the
// list control
m_pListCtrl->GetHeaderCtrl()->SetImageList(&m_imglstSortIcons);
}
return pimglstPrev;
}
/*** Private member functions ************************************************/
/*** Create image list with sort icons ***************************************/
void CListBase::CreateSortIcons()
{
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));
}
/*** Get all attributes of a given item or subitem ***************************/
LVITEM* CListBase::GetLVITEM(int nItem, int nSubItem) const
{
ASSERT(m_pListCtrl);
LVITEM* pItem = new LVITEM;
pItem->mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
pItem->iItem = nItem;
pItem->iSubItem = nSubItem;
pItem->stateMask = ~0U;
// enlarge text buffer gradually until it's large enough
for (int nLen = 128; nLen += nLen;)
{
pItem->cchTextMax = nLen;
pItem->pszText = new TCHAR[nLen];
if (!m_pListCtrl->GetItem(pItem))
{
delete[] pItem->pszText;
delete pItem;
return 0;
}
if (static_cast<int>(_tcslen(pItem->pszText)) < nLen-3) break;
// ^
// reserve extra space for two additional dots
// to be added by "MakeShortString"
delete[] pItem->pszText;
}
return pItem;
}
/*** 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 of subitem 0
if (m_pListCtrl->GetSubItemRect(iItem, 0, LVIR_ICON, rcIcon))
{
CRect rcSubItem0; // rectangle bounding subitem 0
if (GetRealSubItemRect(iItem, 0, LVIR_BOUNDS, rcSubItem0))
if (IndexToOrder(0) > 0 && m_bKeepLabelLeft)
{
int nIndex = OrderToIndex(0);
if (GetRealSubItemRect(iItem, nIndex, LVIR_BOUNDS, ref))
{
int nSmallIconXOff = rcIcon.left - rcSubItem0.left;
ref.left += nSmallIconXOff;
ref.right = ref.left + rcIcon.Width();
// clip rectangle at right edge if necessary
int nWidth = m_pListCtrl->GetColumnWidth(nIndex);
if (nSmallIconXOff + ref.Width() >= nWidth)
ref.right = ref.left - nSmallIconXOff + nWidth - 1;
return true;
}
}
else
{
// clip rectangle at right edge if necessary
if (rcIcon.right > rcSubItem0.right)
rcIcon.right = rcSubItem0.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->left += m_nIconXOff;
pRect->right = rcSmallIcon.left - 1;
// clip at right column border
int nWidth = rcSubItem.Width();
if (pRect->right >= rcSubItem.left + rcSubItem.Width())
pRect->right = pRect->left + nWidth - 1;
return true;
}
}
return false;
}
/*** 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);
if (m_pListCtrl->GetStyle() & LVS_OWNERDRAWFIXED ||
m_pListCtrl->GetExtendedStyle() & 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);
}
}
}
/*** Truncate too long listview control entry and append three ***************/
void CListBase::MakeShortString(CDC* pDC, CString& strText, int nColumnLen)
const
{
LPCTSTR psz3Dots = _T("...");
int nTextLen = strText.GetLength();
if (nTextLen > 0 && pDC->GetTextExtent(strText).cx > nColumnLen)
{
const int nAddLen = pDC->GetTextExtent(psz3Dots, 3).cx;
int i;
for (i = nTextLen-1; i > 0; i--)
if (pDC->GetTextExtent(strText, i).cx + nAddLen <= nColumnLen) break;
if (i > 0)
{
strText.Delete(i, nTextLen-i);
strText += psz3Dots;
}
else
{
// if one character and three dots are to wide, decrease the dot count
int n1stLen = pDC->GetTextExtent(strText, 1).cx;
int i;
for (i = 2; i > 0; i--)
if (n1stLen + pDC->GetTextExtent(psz3Dots, i).cx <= nColumnLen)
break;
strText.Delete(1, nTextLen-1);
if (i > 0) strText += CString(psz3Dots, i);
}
}
}
/*** Return the index of a subitem, based in its order in the header control */
int CListBase::OrderToIndex(int nOrder)
{
ASSERT(m_pListCtrl);
ASSERT(m_pListCtrl->GetHeaderCtrl());
return m_pListCtrl->GetHeaderCtrl()->OrderToIndex(nOrder);
}
/*** Display or hide sort icon on column to be sorted ************************/
void CListBase::SetSortIcon()
{
ASSERT(m_pListCtrl);
CHeaderCtrl* pHeaderCtrl = m_pListCtrl->GetHeaderCtrl();
ASSERT(pHeaderCtrl);
int nCols = pHeaderCtrl->GetItemCount();
for (int col = 0; col < nCols; col++)
{
HDITEM hdrItem;
hdrItem.mask = HDI_FORMAT | HDI_IMAGE;
pHeaderCtrl->GetItem(col, &hdrItem);
if (m_bSortIconEnabled && m_nSortColumn - 1 == col)
{
hdrItem.iImage = m_nUpArrow;
hdrItem.fmt = hdrItem.fmt & HDF_JUSTIFYMASK |
HDF_IMAGE | HDF_STRING | HDF_BITMAP_ON_RIGHT;
}
else if (m_bSortIconEnabled && -m_nSortColumn - 1 == col)
{
hdrItem.iImage = m_nDownArrow;
hdrItem.fmt = hdrItem.fmt & HDF_JUSTIFYMASK |
HDF_IMAGE | HDF_STRING | HDF_BITMAP_ON_RIGHT;
}
else
hdrItem.fmt = hdrItem.fmt & HDF_JUSTIFYMASK | HDF_STRING;
pHeaderCtrl->SetItem(col, &hdrItem);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -