CListCtrl 的自绘

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

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

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

typedef struct tagNMLVCUSTOMDRAW
{
NMCUSTOMDRAW nmcd; // 包含客户自绘控件信息的结构
COLORREF clrText; // 列表视图显示文字的颜色
COLORREF clrTextBk; // 列表视图显示文字的背景色
} 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;

    http://shuiyuan2004.com.blog.163.com/blog/static/910905342009420115140854/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值