CListCtrl自绘「建议收藏」

CListCtrl自绘「建议收藏」CListCtrl自绘有3种方法:第一种:使用WM_ERASEBKGND消息+NM_CUSTOMDRAW消息配合自绘WM_ERASEBKGND消息中绘制背景色,比如偶数行为灰色,奇数行为白色。NM_CUSTOMDRAW消息中设置字体的背景色和字体颜色。好处:保留了控件大多数的原有属性。不需要自己去输出每一个项目的字体。可以非常方便的设置背景色,以及文字的颜色。缺点:不能设置选中

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

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.

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制作的效果如图:可以自己设置字体,设置字体颜色,让列表更好看。

 

 CListCtrl自绘「建议收藏」

CListCtrl自绘「建议收藏」

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 在线聊天系统源码

    在线聊天系统源码在线聊天系统:https://www.lmcjl.com/index/program/view在线聊天系统系统采用了Lumen为框架,通过Nodejs实现在线多客服对多用户的对接。配置信息:linux(centos系统或者是ubuntu系统)+php7+mysql+nodejs演示地址:https://www.lmcjl.com/index/program/view解释id…

  • influxdb基本操作_一个数据库只有一个内模式

    influxdb基本操作_一个数据库只有一个内模式安装aptinstallinfluxdbinfluxdb-client<ip>:8083#web<ip>:8086#httpapi复制代码influxDB中独有的一些概念Point由时间戳(time)、数据(field)和标签(tags)组成time:每条数据记录的时间,也是数据库自动生成的主索引fields:各种记录的值…

    2022年10月30日
  • Spatial Transformer Networks(STN)详解

    Spatial Transformer Networks(STN)详解目录1、STN的作用1.1灵感来源1.2什么是STN?2、STN网络架构![在这里插入图片描述](https://img-blog.csdnimg.cn/20190908104416274.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L…

    2022年10月10日
  • SpringCloud微服务架构分析

    SpringCloud微服务架构分析微服务框架微服务是一种架构风格,一个大型复杂软件应用应该由一个或多个微服务组成。系统中的各个微服务都可以被独立部署,每个服务仅关注于完成一件任务就行了,在所有情况下,每个任务都代表着一个小的业务能力。微服务架构其实就是一种架构风格,我们将整个项目划分为多个独立的小项目,也就是我们俗称的微服务,可以理解为每个微服务都单独处理某个功能模块,可以独立开发、测试、部署、监控和扩展,甚至可以用不同的编程语言开发它们。它有利于我们平时项目的开发,解决了一体化架构项目难以扩展,开发周期长,故障级联等问题…

  • RC522(RFID模块)实践总结

    此次使用RC522模块和S50卡实现近场通讯功能(开发板与RC522通讯方式为硬件SPI),就实践过程中的一些知识点进行总结:RC522模块和M1卡要点介绍;驱动代码;出现问题及解决方法;1.RC522模块和M1卡要点介绍:MFRC522简化功能框图;MFRC522与主机SPI通讯引脚配置;MFRC522与M1卡的通讯原理;M1卡存储结构与指令;MFRC522简化功能框图…

  • Centos7单节点部署RabbitMQ

    Centos7单节点部署RabbitMQ

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号