首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >CListCtrl自绘「建议收藏」

CListCtrl自绘「建议收藏」

作者头像
全栈程序员站长
发布2022-09-09 20:48:34
发布2022-09-09 20:48:34
1.9K0
举报

大家好,又见面了,我是你们的朋友全栈君。

CListCtrl自绘有3种方法:

第一种:使用WM_ERASEBKGND消息 + NM_CUSTOMDRAW消息配合自绘

WM_ERASEBKGND消息中绘制背景色,比如偶数行为灰色,奇数行为白色。

NM_CUSTOMDRAW消息中设置字体的背景色和字体颜色。

好处:保留了控件大多数的原有属性。不需要自己去输出每一个项目的字体。可以非常方便的设置背景色,以及文字的颜色。缺点:不能设置选中行颜色。

使用到2个数据结构:

typedef struct tagNMLVCUSTOMDRAW { NMCUSTOMDRAW nmcd; // 包含客户自绘控件信息的结构 COLORREF clrText; // 列表视图显示文字的颜色 COLORREF clrTextBk; // 列表视图显示文字的背景颜色 } NMLVCUSTOMDRAW, *LPNMLVCUSTOMDRAW; NMCUSTOMDRAW 结构的定义如下: typedef struct tagNMCUSTOMDRAWI { NMHDR hdr; // 含有通知信息的NMHDR结构 DWORD dwDrawStage; // 目前绘制的步骤 HDC hdc; // 设备上下文句柄 RECT rc; // 绘制的区域 DWORD dwItemSpec; // 绘制项的说明 UINT uItemState; // 当前项的状态 LPARAM lItemlParam; // 应用程序定义的数据 } NMCUSTOMDRAW, FAR * LPNMCUSTOMDRAW

//先定义2个变量

COLORREF m_colRow1;

COLORREF m_colRow2;

1、添加WM_ERASEBKGND小心

BOOL CColoredListCtrl::OnEraseBkgnd(CDC* pDC) //重载 { CRect rect; CColoredListCtrl::GetClientRect(rect); POINT mypoint; CBrush brush0(m_colRow1); // 颜色1的画笔 CBrush brush1(m_colRow2); // 颜色2的画笔 int chunk_height=GetCountPerPage(); // 得到每页的记录数 pDC->FillRect(&rect,&brush1); // 先用颜色1填充整个客户区 for (int i=0;i<=chunk_height;i++) { GetItemPosition(i,&mypoint); // 得到第i项的位置 rect.top=mypoint.y ; GetItemPosition(i+1,&mypoint); rect.bottom=mypoint.y; pDC->FillRect(&rect,i %2 ? &brush1 : &brush0); // 根据索引的奇偶不同用不同的画刷 } brush0.DeleteObject(); // 删除画笔 brush1.DeleteObject(); return FALSE; }

2、手动添加消息NM_CUSTOMDRAW响应函数

afx_msg void OnCustomDraw( NMHDR * pNotifyStruct, LRESULT * pResult );

ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)

void CColoredListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) { *pResult=0; LPNMLVCUSTOMDRAW lplvcd=(LPNMLVCUSTOMDRAW)pNMHDR; int iRow=lplvcd->nmcd.dwItemSpec; // 需要绘画的列表项的索引 switch(lplvcd->nmcd.dwDrawStage) // 绘画阶段 {

case CDDS_PREPAINT : // 在绘画前阶段 { *pResult=CDRF_NOTIFYITEMDRAW; // 返回列表项绘画通知 return; } case CDDS_ITEMPREPAINT: // 在列表项的绘画前阶段 { lplvcd->clrText=RGB(0,0,0); *pResult=CDRF_NOTIFYSUBITEMDRAW; // 返回子列表项绘画通知 return; } case CDDS_SUBITEM|CDDS_PREPAINT | CDDS_ITEM:// 绘画列表项或子项 { if(iRow %2) { lplvcd->clrTextBk=m_colRow2; // 奇数项的背景为颜色2 } else { lplvcd->clrTextBk=m_colRow1; // 偶数项的背景为颜色1 } *pResult=CDRF_DODEFAULT; // 控件完成自绘画,不再发送NM_CUSTOMDRAW通知 return; } }

}

第二种:重载WM_PAINT消息,全部自己绘制。新手不推荐。

第三种:重载虚函数virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);将列表的Own Draw Fixel勾上。优点是全部由自己控制,包括字体,字体颜色。背景色,选中色,缺点:有点复杂。

这里面的一个重要的数据结构是:DRAWITEMSTRUCT,参考MSDN

DRAWITEMSTRUCT

This structure provides information that the owner window must have to determine how to paint an owner-drawn control or menu item.

代码语言:javascript
复制
typedef struct tagDRAWITEMSTRUCT { 
UINT CtlType; 
UINT CtlID; 
UINT itemID; 
UINT itemAction; 
UINT itemState; 
HWND hwndItem; 
HDC hDC; 
RECT rcItem; 
ULONG_PTR itemData; 
} DRAWITEMSTRUCT; 

我们需要使用到的是ItemID,就是行号,rcItem就是行矩形。

要想知道列号,建立一个CHeaderCtrl*指针,然后就能知道有多少列了。

要想知道某一项的矩形,比如行1,列2的矩形。直接使用GetSubItem(1,2)就可以了。

比如:

void CListCtrlRack::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {

CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CRect rcItem = lpDrawItemStruct->rcItem; CString strText = “”; CFont* pFont = GetFont(); // if ((lpDrawItemStruct->itemState&ODS_FOCUS)) //如果是选中行 { // int nMode = pDC->SetBkMode(TRANSPARENT); rcItem = lpDrawItemStruct->rcItem; rcItem.bottom -= 1; pDC->FillSolidRect(rcItem,RGB(0,255,255)); } else if(lpDrawItemStruct->itemID % 2) //如果是偶数行 { rcItem = lpDrawItemStruct->rcItem; rcItem.bottom -= 1; pDC->FillSolidRect(rcItem,RGB(200,200,200)); } else //如果是奇数行 { rcItem = lpDrawItemStruct->rcItem; rcItem.bottom -= 1; pDC->FillSolidRect(rcItem,RGB(255,255,255)); } lpDrawItemStruct->itemData = LB_SETITEMDATA ; pDC->SelectObject(pFont); for(int i=0;i<GetHeaderCtrl()->GetItemCount();i++) { strText = GetItemText(lpDrawItemStruct->itemID,i); GetSubItemRect(lpDrawItemStruct->itemID,i,LVIR_BOUNDS,rcItem); rcItem.bottom -=1; rcItem.left +=5; pDC->DrawText(strText,strText.GetLength(),&rcItem,DT_LEFT|DT_SINGLELINE|DT_VCENTER); }

}

采用方法3制作的效果如图:可以自己设置字体,设置字体颜色,让列表更好看。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/152494.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • DRAWITEMSTRUCT
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档