现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

CListCtrl 的customdraw和ownerdraw

2012-09-07 06:55 工业·编程 ⁄ 共 18196字 ⁄ 字号 暂无评论

自行绘制 ClistCtrl 的列表项,可以利用列表框的 NM_CUSTOMDRAW 消息,该消息由控件向它的父窗口发送,告诉父窗口它的绘图操作。

    如果绘图操作不需要父窗口参与,可以使用该控件的 ON_NOTIFY_REFLECT 宏处理它的 NM_CUSTOMDRAW 消息。

    它的处理函数的参数中包含 NMHDR,在 CUSTOMDRAW 的通知下 NMHDR 可以被转换成为 NMLVCUSTOMDRAW 结构,该结构包含了列表控件中需要自绘区域的全部信息:

typedef struct tagNMLVCUSTOMDRAW
{
NMCUSTOMDRAW   nmcd;                // 包含客户自绘控件信息的结构
COLORREF             clrText;              // 列表视图显示文字的颜色
COLORREF             clrTextBk;          // 列表视图显示文字的背景色
} NMLVCUSTOMDRAW, *LPNMLVCUSTOMDRAW;

typedef struct tagNMLVCUSTOMDRAW
{
NMCUSTOMDRAW nmcd;
COLORREF clrText;                     //列表视图显示文字的颜色
COLORREF clrTextBk;                 //列表视图显示文字的背景色
#if (_WIN32_IE >= 0x0400)
int iSubItem;                             //子项编号
#endif
#if (_WIN32_WINNT >= 0x501)
DWORD dwItemType;               //

    // Item custom draw
COLORREF clrFace;                   //
int iIconEffect;
int iIconPhase;
int iPartId;
int iStateId;

    // Group Custom Draw
RECT rcText;
UINT uAlign;      // Alignment. Use LVGA_HEADER_CENTER, LVGA_HEADER_RIGHT, LVGA_HEADER_LEFT
#endif
} NMLVCUSTOMDRAW, *LPNMLVCUSTOMDRAW;

NMCUSTOMDRAW 结构定义如下:

typedef struct tagNMCUSTOMDRAWINFO
{
NMHDR     hdr;                     // 含有通知信息的 NMHDR 结构
DWORD   dwDrawStage;       // 目前绘制的步骤
HDC         hdc;                     // 设备上下文句柄
RECT        rc;                       // 绘制的区域
DWORD    dwItemSpec;        // 绘制项的说明
UINT        uItemState;          // 当前项的状态
LPARAM   lItemlParam           // 应用程序定义的数据
} NMCUSTOMDRAW, FAR * LPNMCUSTOMDRAW;

    NMLVCUSTOMDRAW.nmcd.dwDrawStage 字段,它主要包含以下几个枚举值:

  • CDDS_PREPAINT:表示在绘画前阶段。
  • CDDS_ITEMPREPAINT:表示在列表项的绘画前阶段。
  • CDDS_SUBITEM:表示绘制子项。
  • CDDS_ITEM:表示要绘制项的信息已经可用。

    自绘时,可以通过处理以上几个绘画阶段的通知来实现。

例子详细步骤:

  1. 利用 MFC AppWizard( exe ) 创建一个新工程 TestCListCtrl。在向导的第 ( 1 ) 步选择单文档模式,而后使用默认值来创建,最后获得一个支持文档视图的应用程序。
  2. 在 ClassView 中添加新的类 CCoolListCtrl,类型为 MFC Class,基类为CListCtrl。获得两个新文件 CCoolListCtrl.cpp 和 CCoolListCtrl.h。
  3. 在类 CCoolListCtrl 中添加成员变量 m_imagelist 用于存储图像列表。
  4. 添加 NM_CUSTOMDRAW 消息的处理函数 OnCustomDraw。

    CCoolListCtrl.h 文件中:
    afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);//消息函数声明

    CCoolListCtrl.cpp 文件中:
    // 消息映射宏中添加:ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)

    BEGIN_MESSAGE_MAP(CCoolListCtrl, CListCtrl)
    //{{AFX_MSG_MAP(CCoolListCtrl)
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    // 消息处理函数实现:

    /////////////////////////////////////////////////////////////////////////////
    // CCoolListCtrl message handlers

    void CCoolListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
    {
    // TODO: Add your control notification handler code here
    NMLVCUSTOMDRAW* pLVCD = reinterpret_cast <NMLVCUSTOMDRAW*> ( pNMHDR );

        *pResult = 0;
    // Request item-specific notifications if this is the
    // beginning of the paint cycle.

        if ( CDDS_PREPAINT  == pLVCD-> nmcd.dwDrawStage )
    {
    *pResult = CDRF_NOTIFYITEMDRAW;
    }
    else if ( CDDS_ITEMPREPAINT == pLVCD-> nmcd.dwDrawStage )
    {
    // This is the beginning of an item 's paint cycle.
    LVITEM rItem;
    int  nItem = static_cast <int> ( pLVCD-> nmcd.dwItemSpec );
    CDC* pDC = CDC::FromHandle ( pLVCD-> nmcd.hdc );
    COLORREF crBkgnd;
    BOOL bListHasFocus;
    CRect  rcItem;
    CRect  rcText;
    CString  sText;
    UINT uFormat;

            bListHasFocus = ( this->GetSafeHwnd() == ::GetFocus() );

            // Get the image index and selected/focused state of the
    // item being drawn.
    ZeroMemory ( &rItem, sizeof(LVITEM) );
    rItem.mask  = LVIF_IMAGE | LVIF_STATE;
    rItem.iItem = nItem;
    rItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
    this->GetItem ( &rItem );

            // Get the rect that holds the item 's icon.
    this->GetItemRect ( nItem, &rcItem, LVIR_ICON );

            // Draw the icon.
    uFormat = ILD_TRANSPARENT;

            if ( ( rItem.state & LVIS_SELECTED ) && bListHasFocus )
    uFormat |= ILD_FOCUS;

            m_imagelist.Draw ( pDC, rItem.iImage, rcItem.TopLeft(), uFormat );

            // Get the rect that bounds the text label.
    this->GetItemRect ( nItem, rcItem, LVIR_LABEL ); //把这行去掉就没有文字.

            // Draw the background of the list item. Colors are selected
    // according to the item 's state.

            if ( rItem.state & LVIS_SELECTED )
    {
    if ( bListHasFocus )
    {
    crBkgnd = GetSysColor ( COLOR_HIGHLIGHT );
    pDC-> SetTextColor ( GetSysColor ( COLOR_HIGHLIGHTTEXT ));
    }
    else
    {
    crBkgnd = GetSysColor ( COLOR_BTNFACE );
    pDC-> SetTextColor ( GetSysColor ( COLOR_BTNTEXT ));
    }
    }
    else
    {
    crBkgnd = GetSysColor ( COLOR_WINDOW );
    pDC-> SetTextColor ( GetSysColor ( COLOR_BTNTEXT ));
    }

            // Draw the background & prep the DC for the text drawing. Note
    // that the entire item RECT is filled in, so this emulates the full-
    // row selection style of normal lists.
    pDC-> FillSolidRect ( rcItem, crBkgnd );
    pDC-> SetBkMode ( TRANSPARENT );

            // Tweak the rect a bit for nicer-looking text alignment.
    rcText = rcItem;
    // Draw the text.
    sText = this->GetItemText ( nItem, 0 );

            pDC-> DrawText ( sText, CRect::CRect(rcText.left+3,rcText.top,rcText.right,rcText.bottom+60), DT_VCENTER );

            // Draw a focus rect around the item if necessary.
    if ( bListHasFocus && ( rItem.state & LVIS_FOCUSED ))
    {
    pDC-> DrawFocusRect ( rcItem );
    }

            *pResult = CDRF_SKIPDEFAULT; // We 've painted everything.
    }
    }

  5. 在视图类 CTestCListCtrlView 中添加成员变量 m_ListCtrl,类型为 CCoolListCtrl。
  6. 定义 WM_CREATE 消息的处理函数 CTestCListCtrlView ::Create,用于创建 CCoolListCtrl 控件,代码如下:

    //创建列表控件:自绘样式、没有列头部、处理通知
    m_ListCtrl.Create(LVS_OWNERDRAWFIXED | LVS_NOCOLUMNHEADER | LBS_NOTIFY, CRect(0,0,400,200), this, IDC_LISTCTRL );

    // 可以使用 m_ListCtrl.SetExtendedStyle 设置扩展样式

    // 用自己编写的函数设置图像列表

    m_ListCtrl.SetImagelist(IDB_IMAGE);  

    // 用自己编写的函数设置列表项的行高,方法见文章《CListCtrl行高的修改》
    m_ListCtrl.SetItemHeight(36);
    // 插入项

    m_ListCtrl.InsertItem(0, "Monroeville", 0); 
    m_ListCtrl.InsertItem(1, "Hartford", 1); 
    m_ListCtrl.InsertItem(2, "Redmond", 2);

  7. 设置图像列表的函数:首先将作为图像列表的bmp文件导入到工程资源中,uBitmap是其资源ID

    BOOL CCoolListCtrl::SetImagelist(UINT uBitmap)
    {
    m_imagelist.DeleteImageList();
    m_imagelist.Create(32, 32, ILC_COLOR24|ILC_MASK, 8, 1);
    CBitmap bitmap;
    bitmap.LoadBitmap(uBitmap);
    m_imagelist.Add(&bitmap, RGB(255,0,255));

        return TRUE;
    }

  8.     采用添加 NM_CUSTOMDRAW 消息的处理函数 OnCustomDraw 的方式来自绘,遇到了一点问题:

        创建 ClistCtrl 时使用 LVS_OWNERDRAWFIXED 样式的话,在OnCustomDraw 函数中:

    switch(pLVCD-> nmcd.dwDrawStage) //绘画阶段
    {

            case CDDS_PREPAINT:        //在绘画前阶段
    *pResult = CDRF_NOTIFYSUBITEMDRAW;          //返回列表项绘画通知
    break;
    case CDDS_ITEMPREPAINT:  //在列表项的绘画前阶段
    *pResult = CDRF_NOTIFYSUBITEMDRAW;          //返回子列表项绘画通知
    break;
    case CDDS_ITEMPREPAINT|CDDS_SUBITEM:          //绘画列表项或子项
    {
    int iCol = lplvcd->iSubItem;
    int iRow = lplvcd->nmcd.dwItemSpec;
    CString sItem = GetItemText(iRow, iCol);
    CRect rc;
    GetCellRect(iRow, iCol, LVIR_BOUNDS, rc);
    // get the device context.
    CDC *pDC= CDC::FromHandle(lplvcd->nmcd.hdc);
    // paint the text centered.
    pDC->DrawText(sItem , rc, DT_CENTER);
    *pResult= CDRF_SKIPDEFAULT;
    break;
    }
    default:
    *pResult = CDRF_DODEFAULT;// 控件完成自绘,不再发送 NM_CUSTOMDRAW 消息

           return ;

    }

    *pResult = CDRF_NOTIFYSUBITEMDRAW; 返回子列表项绘画通知时,弹出了错误:

    debug assertion failed

    program .....exe
    file :winctrl2.cpp
    line :547

    而且似乎进不了case CDDS_ITEMPREPAINT|CDDS_SUBITEM,不知何故。

    原来 CListCtrl 的派生类,使用 LVS_OWNERDRAWFIXED 的样式的话,必须重载 DrawItem 函数来绘制各项,否则就取消 LVS_OWNERDRAWFIXED 的样式。

    但取消 LVS_OWNERDRAWFIXED 的样式的话,就无法自行设置列表项的行高了。

    所以将 OnCustomDraw 换成重载 DrawItem 的方式。

    例如:

    void CCoolListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDIS) 
    {
    LVITEM   rItem;
    int      nItem = lpDIS->itemID;
    CDC*     pDC = CDC::FromHandle (lpDIS->hDC);
    //    COLORREF crBkgnd;
    BOOL     bListHasFocus;
    CRect    rcItem;
    CRect    rcCell;
    CRect    rcText;
    CString  sText;
    UINT     uFormat;

        LV_COLUMN lvc;
    ::ZeroMemory(&lvc, sizeof(lvc));
    lvc.mask = LVCF_WIDTH | LVCF_FMT; 
    int intColumnCount; 
    for (intColumnCount=0; GetColumn(intColumnCount, &lvc); intColumnCount++)
    {
    bListHasFocus = ( GetSafeHwnd() == ::GetFocus() );

            // Get the image index and selected/focused state of the
    // item being drawn.
    ZeroMemory ( &rItem, sizeof(LVITEM) );
    rItem.iSubItem = intColumnCount;
    rItem.mask  = LVIF_IMAGE | LVIF_STATE;
    rItem.iItem = nItem;
    rItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
    VERIFY(GetItem(&rItem));

            GetSubItemRect(lpDIS->itemID, intColumnCount,LVIR_BOUNDS, rcCell);    
    if (intColumnCount == 0)
    {
    rcItem = rcCell;
    rcCell.right = GetColumnWidth(0);

    // Draw the icon.
    uFormat = ILD_TRANSPARENT;
    if ( ( rItem.state & LVIS_SELECTED ) && bListHasFocus )
    uFormat |= ILD_FOCUS;

            // 居中绘画图标
    CPoint picPt;
    picPt.x = rcCell.left+(rcCell.Width()-32)/2;
    picPt.y = rcCell.top+(rcCell.Height()-32)/2;
    m_imagelist.Draw ( pDC, rItem.iImage, picPt, uFormat );

             // Tweak the rect a bit for nicer-looking text alignment.
    rcText = rcItem;
    // Draw the text.
    sText = this->GetItemText ( nItem, 0 );
    pDC-> DrawText ( sText, CRect::CRect(rcText.left+3,rcText.top,rcText.right,rcText.bottom+60), DT_VCENTER );

        }
    return ;
    }

以下是Ownerdraw方式的

/////////////////////////////////////////////////////////////////////////////
//   CListCtrlEx   window
class   CListCtrlEx   :   public   CListCtrl
{
public:
CListCtrlEx();
virtual   ~CListCtrlEx();
protected:
//当前是否为整行选择
BOOL m_bFullRowSel;
BOOL m_bClientWidthSel;
int m_cxClient;
int m_cxStateImageOffset;
COLORREF m_clrText;
COLORREF m_clrTextBk;
COLORREF m_clrBkgnd;
public:
//设定当前是否为整行选择状态
BOOL   SetFullRowSel(BOOL   bFillRowSel);
//获取当前是否为整行选择状态
BOOL   GetFullRowSel();
//{{AFX_VIRTUAL(CListCtrlEx)
public:
virtual   BOOL   PreCreateWindow(CREATESTRUCT&   cs);
protected:
virtual   void   DrawItem(LPDRAWITEMSTRUCT   lpDrawItemStruct);
//}}AFX_VIRTUAL
protected:
static   LPCTSTR   MakeShortString(CDC*   pDC,   LPCTSTR   lpszLong,   int   nColumnLen,   int   nOffset);
void   RepaintSelectedItems();
#ifdef   _DEBUG
virtual   void   Dump(CDumpContext&   dc)   const;
#endif
//{{AFX_MSG(CListCtrlEx)
afx_msg   LRESULT   OnSetImageList(WPARAM   wParam,   LPARAM   lParam);
afx_msg   LRESULT   OnSetTextColor(WPARAM   wParam,   LPARAM   lParam);
afx_msg   LRESULT   OnSetTextBkColor(WPARAM   wParam,   LPARAM   lParam);
afx_msg   LRESULT   OnSetBkColor(WPARAM   wParam,   LPARAM   lParam);
afx_msg   void   OnSize(UINT   nType,   int   cx,   int   cy);
afx_msg   void   OnPaint();
afx_msg   void   OnSetFocus(CWnd*   pOldWnd);
afx_msg   void   OnKillFocus(CWnd*   pNewWnd);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

//   ListCtrlEx.cpp   :   implementation   file
//
#include   "stdafx.h "
#include   "ListCtrlEx.h "
#ifdef   _DEBUG
#define   new   DEBUG_NEW
#undef   THIS_FILE
static   char   THIS_FILE[]   =   __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//   CListCtrlEx
CListCtrlEx::CListCtrlEx()
{
m_bFullRowSel   =   FALSE;
m_bClientWidthSel   =   TRUE;
m_cxClient   =   0;
m_cxStateImageOffset   =   0;
m_clrText   =   ::GetSysColor(COLOR_WINDOWTEXT);
m_clrTextBk   =   ::GetSysColor(COLOR_WINDOW);
m_clrBkgnd   =   ::GetSysColor(COLOR_WINDOW);
}
CListCtrlEx::~CListCtrlEx()
{
}
BEGIN_MESSAGE_MAP(CListCtrlEx,   CListCtrl)
//{{AFX_MSG_MAP(CListCtrlEx)
ON_WM_SIZE()
ON_WM_PAINT()
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_MESSAGE(LVM_SETIMAGELIST,   OnSetImageList)
ON_MESSAGE(LVM_SETTEXTCOLOR,   OnSetTextColor)
ON_MESSAGE(LVM_SETTEXTBKCOLOR,   OnSetTextBkColor)
ON_MESSAGE(LVM_SETBKCOLOR,   OnSetBkColor)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#ifdef   _DEBUG
void   CListCtrlEx::Dump(CDumpContext&   dc)   const
{
CListCtrl::Dump(dc);
dc   < <   "m_bFullRowSel   =   "   < <   (UINT)m_bFullRowSel;
dc   < <   "/n ";
dc   < <   "m_cxStateImageOffset   =   "   < <   m_cxStateImageOffset;
dc   < <   "/n ";
}
#endif   //_DEBUG
/////////////////////////////////////////////////////////////////////////////
//   CListCtrlEx   message   handlers
BOOL   CListCtrlEx::PreCreateWindow(CREATESTRUCT&   cs)
{
//默认当前为整行选择
cs.style   &=   ~LVS_TYPEMASK;
cs.style   |=   LVS_REPORT   |   LVS_OWNERDRAWFIXED;
m_bFullRowSel   =   TRUE;
return(CListCtrl::PreCreateWindow(cs));
}
BOOL   CListCtrlEx::SetFullRowSel(BOOL   bFullRowSel)
{
//在此函数执行期间,锁定当前窗口使其不充许刷新
LockWindowUpdate();
m_bFullRowSel   =   bFullRowSel;
BOOL   bRet;
if(m_bFullRowSel)
bRet   =   ModifyStyle(0L,   LVS_OWNERDRAWFIXED);
else
bRet   =   ModifyStyle(LVS_OWNERDRAWFIXED,   0L);
//如果当前没有改变窗口控件的类型,重刷当前窗口
if(bRet   &&   (GetStyle()   &   LVS_TYPEMASK)   ==   LVS_REPORT)
Invalidate();
//取消当前窗口不充许刷新的锁定
UnlockWindowUpdate();
return   bRet;
}
BOOL   CListCtrlEx::GetFullRowSel()
{
return   m_bFullRowSel;
}
//   offsets   for   first   and   other   columns
#define   OFFSET_FIRST         2
#define   OFFSET_OTHER         6
void   CListCtrlEx::DrawItem(LPDRAWITEMSTRUCT   lpDrawItemStruct)
{
CDC*   pDC   =   CDC::FromHandle(lpDrawItemStruct-> hDC);
CRect   rcItem(lpDrawItemStruct-> rcItem);
UINT   uiFlags   =   ILD_TRANSPARENT;
CImageList*   pImageList;
int   nItem   =   lpDrawItemStruct-> itemID;
BOOL   bFocus   =   (GetFocus()   ==   this);
COLORREF   clrTextSave,   clrBkSave;
COLORREF   clrImage   =   m_clrBkgnd;
static   _TCHAR   szBuff[MAX_PATH];
LPCTSTR   pszText;
//获取项数据
LV_ITEM   lvi;
lvi.mask   =   LVIF_TEXT   |   LVIF_IMAGE   |   LVIF_STATE;
lvi.iItem   =   nItem;
lvi.iSubItem   =   0;
lvi.pszText   =   szBuff;
lvi.cchTextMax   =   sizeof(szBuff);
lvi.stateMask   =   0xFFFF;//获取所有的状态标志
this-> GetItem(&lvi);
BOOL   bSelected   =   (bFocus   ||   (GetStyle()   &   LVS_SHOWSELALWAYS))   &&   lvi.state   &   LVIS_SELECTED;
bSelected   =   bSelected   ||   (lvi.state   &   LVIS_DROPHILITED);
//设定选中项的颜色
CRect   rcAllLabels;
this-> GetItemRect(nItem,   rcAllLabels,   LVIR_BOUNDS);
CRect   rcLabel;
this-> GetItemRect(nItem,   rcLabel,   LVIR_LABEL);
rcAllLabels.left   =   rcLabel.left;
if   (m_bClientWidthSel   &&   rcAllLabels.right <m_cxClient)
rcAllLabels.right   =   m_cxClient;
if   (bSelected)
{
clrTextSave   =   pDC-> SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
clrBkSave   =   pDC-> SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
pDC-> FillRect(rcAllLabels,   &CBrush(::GetSysColor(COLOR_HIGHLIGHT)));
}
else
pDC-> FillRect(rcAllLabels,   &CBrush(m_clrTextBk));
//设定图标的颜色和标志
if   (lvi.state   &   LVIS_CUT)
{
clrImage   =   m_clrBkgnd;
uiFlags   |=   ILD_BLEND50;
}
else   if(bSelected)
{
clrImage   =   ::GetSysColor(COLOR_HIGHLIGHT);
uiFlags   |=   ILD_BLEND50;
}
//绘制状态图标
UINT   nStateImageMask   =   lvi.state   &   LVIS_STATEIMAGEMASK;
if   (nStateImageMask)
{
int   nImage   =   (nStateImageMask> > 12)   -   1;
pImageList   =   this-> GetImageList(LVSIL_STATE);
if   (pImageList)
{
pImageList-> Draw(pDC,   nImage,
CPoint(rcItem.left,   rcItem.top),   ILD_TRANSPARENT);
}
}
//绘制默认的覆盖图标
CRect   rcIcon;
this-> GetItemRect(nItem,   rcIcon,   LVIR_ICON);
pImageList   =   this-> GetImageList(LVSIL_SMALL);
if   (pImageList)
{
UINT   nOvlImageMask=lvi.state   &   LVIS_OVERLAYMASK;
if   (rcItem.left <rcItem.right-1)
{
ImageList_DrawEx(pImageList-> m_hImageList,   lvi.iImage,
pDC-> m_hDC,rcIcon.left,rcIcon.top,   16,   16,
m_clrBkgnd,   clrImage,   uiFlags   |   nOvlImageMask);
}
}
//绘制项标签
this-> GetItemRect(nItem,   rcItem,   LVIR_LABEL);
rcItem.right   -=   m_cxStateImageOffset;
pszText   =   MakeShortString(pDC,   szBuff,
rcItem.right-rcItem.left,   2*OFFSET_FIRST);
rcLabel   =   rcItem;
rcLabel.left   +=   OFFSET_FIRST;
rcLabel.right   -=   OFFSET_FIRST;
pDC-> DrawText(pszText,-1,rcLabel,DT_LEFT   |   DT_SINGLELINE   |   DT_NOPREFIX   |   DT_NOCLIP   |   DT_VCENTER);
//绘制标签扩展列
LV_COLUMN   lvc;
lvc.mask   =   LVCF_FMT   |   LVCF_WIDTH;
for(int   nColumn   =   1;   this-> GetColumn(nColumn,   &lvc);   nColumn++)
{
rcItem.left   =   rcItem.right;
rcItem.right   +=   lvc.cx;
int   nRetLen   =   this-> GetItemText(nItem,   nColumn,
szBuff,   sizeof(szBuff));
if   (nRetLen   ==   0)
continue;
pszText   =   MakeShortString(pDC,   szBuff,
rcItem.right   -   rcItem.left,   2*OFFSET_OTHER);
UINT   nJustify   =   DT_LEFT;
if(pszText   ==   szBuff)
{
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_OTHER;
rcLabel.right   -=   OFFSET_OTHER;
pDC-> DrawText(pszText,   -1,   rcLabel,
nJustify   |   DT_SINGLELINE   |   DT_NOPREFIX   |   DT_NOCLIP   |   DT_VCENTER);
}
//绘制焦点框矩形
if   (lvi.state   &   LVIS_FOCUSED   &&   bFocus)
pDC-> DrawFocusRect(rcAllLabels);
//设定选中项的颜色
if   (bSelected)
{
pDC-> SetTextColor(clrTextSave);
pDC-> SetBkColor(clrBkSave);
}
}
LPCTSTR   CListCtrlEx::MakeShortString(CDC*   pDC,   LPCTSTR   lpszLong,   int   nColumnLen,   int   nOffset)
{
static   const   _TCHAR   szThreeDots[]   =   _T( "... ");
int   nStringLen   =   lstrlen(lpszLong);
if(nStringLen   ==   0   ||
(pDC-> GetTextExtent(lpszLong,   nStringLen).cx   +   nOffset)   <=   nColumnLen)
{
return(lpszLong);
}
static   _TCHAR   szShort[MAX_PATH];
lstrcpy(szShort,lpszLong);
int   nAddLen   =   pDC-> GetTextExtent(szThreeDots,sizeof(szThreeDots)).cx;
for(int   i   =   nStringLen-1;   i   >   0;   i--)
{
szShort[i]   =   0;
if((pDC-> GetTextExtent(szShort,   i).cx   +   nOffset   +   nAddLen)
<=   nColumnLen)
{
break;
}
}
lstrcat(szShort,   szThreeDots);
return(szShort);
}

void   CListCtrlEx::RepaintSelectedItems()
{
CRect   rcItem,   rcLabel;
int   nItem   =   this-> GetNextItem(-1,   LVNI_FOCUSED);
//当前没被选择项
if(nItem   !=   -1)
{
this-> GetItemRect(nItem,   rcItem,   LVIR_BOUNDS);
this-> GetItemRect(nItem,   rcLabel,   LVIR_LABEL);
rcItem.left   =   rcLabel.left;
InvalidateRect(rcItem,   FALSE);
}
//当前选择项是永远选择
if(!(GetStyle()   &   LVS_SHOWSELALWAYS))
{
for(nItem   =   this-> GetNextItem(-1,   LVNI_SELECTED);
nItem   !=   -1;   nItem   =   this-> GetNextItem(nItem,   LVNI_SELECTED))
{
this-> GetItemRect(nItem,   rcItem,   LVIR_BOUNDS);
this-> GetItemRect(nItem,   rcLabel,   LVIR_LABEL);
rcItem.left   =   rcLabel.left;
InvalidateRect(rcItem,   FALSE);
}
}
//刷新当前窗口
UpdateWindow();
}
LRESULT   CListCtrlEx::OnSetImageList(WPARAM   wParam,   LPARAM   lParam)
{
//   if   we 're   running   Windows   4,   there 's   no   need   to   offset   the
//   item   text   location
OSVERSIONINFO   info;
info.dwOSVersionInfoSize   =   sizeof(info);
VERIFY(::GetVersionEx(&info));
if(   (int)   wParam   ==   LVSIL_STATE   &&   info.dwMajorVersion   <   4)
{
int   cx,   cy;
if(::ImageList_GetIconSize((HIMAGELIST)lParam,   &cx,   &cy))
m_cxStateImageOffset   =   cx;
else
m_cxStateImageOffset   =   0;
}
return(Default());
}
LRESULT   CListCtrlEx::OnSetTextColor(WPARAM   wParam,   LPARAM   lParam)
{
m_clrText   =   (COLORREF)lParam;
return(Default());
}
LRESULT   CListCtrlEx::OnSetTextBkColor(WPARAM   wParam,   LPARAM   lParam)
{
m_clrTextBk   =   (COLORREF)lParam;
return(Default());
}
LRESULT   CListCtrlEx::OnSetBkColor(WPARAM   wParam,   LPARAM   lParam)
{
m_clrBkgnd   =   (COLORREF)lParam;
return(Default());
}
void   CListCtrlEx::OnSize(UINT   nType,   int   cx,   int   cy)
{
m_cxClient   =   cx;
CListCtrl::OnSize(nType,   cx,   cy);
}
void   CListCtrlEx::OnPaint()
{
//   in   full   row   select   mode,   we   need   to   extend   the   clipping   region
//   so   we   can   paint   a   selection   all   the   way   to   the   right
if   (m_bClientWidthSel   &&
(GetStyle()   &   LVS_TYPEMASK)   ==   LVS_REPORT   &&
GetFullRowSel())
{
CRect   rcAllLabels;
this-> GetItemRect(0,   rcAllLabels,   LVIR_BOUNDS);
if(rcAllLabels.right   <   m_cxClient)
{
//   need   to   call   BeginPaint   (in   CPaintDC   c-tor)
//   to   get   correct   clipping   rect
CPaintDC   dc(this);
CRect   rcClip;
dc.GetClipBox(rcClip);
rcClip.left   =   min(rcAllLabels.right-1,   rcClip.left);
rcClip.right   =   m_cxClient;
InvalidateRect(rcClip,   FALSE);
//   EndPaint   will   be   called   in   CPaintDC   d-tor
}
}
CListCtrl::OnPaint();
}
void   CListCtrlEx::OnSetFocus(CWnd*   pOldWnd)
{
CListCtrl::OnSetFocus(pOldWnd);
//   check   if   we   are   getting   focus   from   label   edit   box
if(pOldWnd!=NULL   &&   pOldWnd-> GetParent()==this)
return;
//   repaint   items   that   should   change   appearance
if(m_bFullRowSel   &&   (GetStyle()   &   LVS_TYPEMASK)==LVS_REPORT)
RepaintSelectedItems();
}
void   CListCtrlEx::OnKillFocus(CWnd*   pNewWnd)
{
CListCtrl::OnKillFocus(pNewWnd);
//   check   if   we   are   losing   focus   to   label   edit   box
if(pNewWnd   !=   NULL   &&   pNewWnd-> GetParent()   ==   this)
return;
//   repaint   items   that   should   change   appearance
if(m_bFullRowSel   &&   (GetStyle()   &   LVS_TYPEMASK)   ==   LVS_REPORT)
RepaintSelectedItems();
}

给我留言

留言无头像?