📄 listctrlex.cpp
字号:
/******************************************************************************\
* file : ListCtrlEx.cpp
* created: 1997.09.22
*
* Zafir Anjum - Original author.
* Mark Findlay - IE4 fixes.
* Matthew Bells - Better TitleTips.
*
* description:
* A super CListControl.
* <P>features:
* <UL>
* <LI>Title Tip item expantion
* <LI>full row selection<BR>
* <I>Note:</I> this is also a feature in IE 4.0 with
* LVS_EX_FULLROWSELECT.
* <LI>notifies parent selection has changed
* <LI>supports column dragging (with IE4) which changes the column order
* </UL>
*
\******************************************************************************/
// ListCtrlEx.cpp : implementation of the CListCtrlEx class
#include "..\stdafx.h"
#include <assert.h>
#include "ListCtrlEx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx
IMPLEMENT_DYNCREATE(CListCtrlEx, CListCtrl)
BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
//{{AFX_MSG_MAP(CListCtrlEx)
ON_WM_PAINT()
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_KEYDOWN()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
ON_MESSAGE(LVM_SETTEXTCOLOR, OnSetTextColor)
ON_MESSAGE(LVM_SETTEXTBKCOLOR, OnSetTextBkColor)
ON_MESSAGE(LVM_SETBKCOLOR, OnSetBkColor)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx construction/destruction
CListCtrlEx::CListCtrlEx()
{
m_bFullRowSel = TRUE;
m_bClientWidthSel = FALSE;
m_clrText = ::GetSysColor(COLOR_WINDOWTEXT);
m_clrTextBk = ::GetSysColor(COLOR_WINDOW);
m_clrBkgnd = ::GetSysColor(COLOR_WINDOW);
}
CListCtrlEx::~CListCtrlEx()
{
}
// Make sure the control is owner drawn
BOOL CListCtrlEx::PreCreateWindow(CREATESTRUCT& cs)
{
// default is report view and full row selection
cs.style &= ~LVS_TYPEMASK;
cs.style |= LVS_REPORT | LVS_OWNERDRAWFIXED;
//m_bFullRowSel = TRUE;
return(CListCtrl::PreCreateWindow(cs));
}
BOOL CListCtrlEx::SetFullRowSel(BOOL bFullRowSel)
{
// no painting during change
LockWindowUpdate();
m_bFullRowSel = bFullRowSel;
BOOL bRet;
if (m_bFullRowSel)
bRet = ModifyStyle(0L, LVS_OWNERDRAWFIXED);
else
bRet = ModifyStyle(LVS_OWNERDRAWFIXED, 0L);
// repaint window if we are not changing view type
if (bRet && (GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
Invalidate();
// repaint changes
UnlockWindowUpdate();
return(bRet);
}
BOOL CListCtrlEx::GetFullRowSel()
{
return(m_bFullRowSel);
}
/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx drawing
/*
* DrawItem() is called by the framework whenever an item needs to be drawn
* for owner drawn controls.
* Note:
* <UL>
* <LI>LVS_SHOWSELALWAYS: non owner drawn controls show an item is
* highlighted when the control does not have focus with a different
* highlight color is (usually gray). This is not supported for
* this control.
* </UL>
*/
void CListCtrlEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
int iSavedDC = pDC->SaveDC(); // Save DC state
int iItem = lpDrawItemStruct->itemID;
// Get item image and state info
LV_ITEM lvi;
lvi.mask = LVIF_IMAGE | LVIF_STATE;
lvi.iItem = iItem;
lvi.iSubItem = 0;
lvi.stateMask = 0xFFFF; // get all state flags
GetItem(&lvi);
BOOL bHighlight = (
(lvi.state & LVIS_DROPHILITED) ||
((lvi.state & LVIS_SELECTED) && ((GetFocus() == this) || (GetStyle() & LVS_SHOWSELALWAYS)))
);
// Get rectangles for drawing
CRect rcBounds;
CRect rcLabel;
CRect rcIcon;
GetItemRect(iItem, rcBounds, LVIR_BOUNDS);
GetItemRect(iItem, rcLabel, LVIR_LABEL);
GetItemRect(iItem, rcIcon, LVIR_ICON);
CRect rcItem(rcBounds);
CString sLabel = GetItemText(iItem, 0);
// Labels are offset by a certain amount
// This offset is related to the width of a space character
int offset = pDC->GetTextExtent(_T(" "), 1 ).cx*2;
rcBounds.left = rcLabel.left;
CRect rcWnd;
GetClientRect(&rcWnd);
if(m_bClientWidthSel && rcBounds.right<rcWnd.right)
rcBounds.right = rcWnd.right;
// Draw the background
if(bHighlight)
{
pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
pDC->FillRect(rcBounds, &CBrush(::GetSysColor(COLOR_HIGHLIGHT)));
}
else
{
pDC->FillRect(rcBounds, &CBrush(m_clrTextBk));
}
// Set clip region
rcItem.right = rcItem.left + GetColumnWidth(0);
/*
CRgn rgn;
rgn.CreateRectRgnIndirect(&rcItem);
pDC->SelectClipRgn(&rgn);
rgn.DeleteObject();
*/
// Draw state icon
if(lvi.state & LVIS_STATEIMAGEMASK)
{
int nImage = ((lvi.state & LVIS_STATEIMAGEMASK)>>12) - 1;
CImageList* pImageList = GetImageList(LVSIL_STATE);
if(pImageList)
{
pImageList->Draw(pDC, nImage,
CPoint(rcItem.left, rcItem.top), ILD_TRANSPARENT);
}
}
// Draw normal and overlay icon
CImageList* pImageList = GetImageList(LVSIL_SMALL);
if(pImageList)
{
/*UINT nOvlImageMask = lvi.state & LVIS_OVERLAYMASK;
pImageList->Draw(pDC, lvi.iImage,
CPoint(rcIcon.left, rcIcon.top),
(bHighlight?ILD_BLEND50:0) | ILD_TRANSPARENT | nOvlImageMask );*/
//Do not draw overlay icon
pImageList->Draw(pDC, lvi.iImage,
CPoint(rcIcon.left, rcIcon.top),ILD_TRANSPARENT);
}
// Draw item label - Column 0
rcLabel.left += offset/2-1;
rcLabel.right -= offset;
pDC->DrawText(sLabel,-1,rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX
| DT_VCENTER | DT_END_ELLIPSIS);
// Draw labels for remaining columns
LV_COLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH;
/*
// set clip region
rcBounds.right = rcHighlight.right > rcBounds.right ? rcHighlight.right :
rcBounds.right;
rgn.CreateRectRgnIndirect(&rcBounds);
pDC->SelectClipRgn(&rgn);
*/
for(int nColumn = 1; GetColumn(nColumn, &lvc); nColumn++)
{
rcItem.left = rcItem.right;
rcItem.right += lvc.cx;
sLabel = GetItemText(iItem, nColumn);
// Get the text justification
UINT nJustify = DT_LEFT;
switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
{
case LVCFMT_RIGHT:
nJustify = DT_RIGHT;
break;
case LVCFMT_CENTER:
nJustify = DT_CENTER;
break;
default:
break;
}
rcLabel = rcItem;
rcLabel.left += offset;
rcLabel.right -= offset;
pDC->DrawText(sLabel, -1, rcLabel,
nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_END_ELLIPSIS);
}
// draw focus rectangle if item has focus
if ((lvi.state & LVIS_FOCUSED) && (GetFocus() == this))
pDC->DrawFocusRect(rcBounds);
pDC->RestoreDC(iSavedDC); // Restore DC.
}
/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx diagnostics
#ifdef _DEBUG
void CListCtrlEx::Dump(CDumpContext& dc) const
{
CListCtrl::Dump(dc);
dc << "m_bFullRowSel = " << m_bFullRowSel;
dc << "\n";
}
#endif //_DEBUG
/**
* @param iRow [in] row of cell
* @param iColunm [in] column of cell
* @return Rectangle corresponding to the given cell.
*/
CRect CListCtrlEx::GetCellRect(int iRow, int iColumn)const
{
// Make sure that the ListView is in LVS_REPORT
if((GetStyle() & LVS_TYPEMASK) != LVS_REPORT)
return CRect(0,0,0,0);
// Get the number of columns
{
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
int iColumnCount = pHeader->GetItemCount();
assert(iColumn < iColumnCount);
}
CRect rect;
GetItemRect(iRow, &rect, LVIR_BOUNDS);
// Now find the column
for(int colnum = 0; colnum < iColumn; colnum++)
{
rect.left += GetTrueColumnWidth(colnum);
}
// Found the column
rect.right = rect.left + GetTrueColumnWidth(iColumn);
RECT rectClient;
GetClientRect(&rectClient);
if(rect.right > rectClient.right)
rect.right = rectClient.right;
return rect;
}
/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -