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自绘「建议收藏」

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • matlab如何循环_左手转笔教程无限循环

    matlab如何循环_左手转笔教程无限循环循环输出变量代码fori=1:4iend其中1:4代表一个行向量1234,在matlab中,行向量的另外一个表示方法是[1234],即fori=1:4等价于fori=[1234],编写程序时牢记一个点:对于某次固定的迭代,i会从这个向量中取一个值,该值可以参与循环中的计算。运行输出i=1i=2i=3i=

    2022年10月6日
    4
  • UART和USART的区别

    UART和USART的区别UART定义  UART是一种通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输和接收。在嵌入式设计中,UART用于主机与辅助设备通信,如汽车音响与外接AP之间的通信,与PC机通信包括与监控调试器和其它器件,如EEPROM通信。  通用异步收发传输器(UniversalAsynchronousReceiver/Transmitter),通常称作UART,是一种异步收发传输…

    2022年5月12日
    45
  • 电子设计竞赛控制组——完整旋转倒立摆程序

    电子设计竞赛控制组——完整旋转倒立摆程序以前也想过要写博客,但是却一直没有付诸于实践,作为第一篇原创,我还是选择将以前电赛时的作品拿出来,毕竟当初可是花费了好多心血的,汗~旋转倒立摆是控制组校内赛练手的题目,需要对PID非常熟悉才能调好参数,以下代码是自己搭建好结构后调试出来的程序,其中的参数会根据不同的结构作出调整。结构组成:K60开发板(带液晶屏和按键),角度编码器,直流减速电机(带编码器),12V的电机驱动,金属摆臂,…

    2022年8月18日
    5
  • Linux设备树是什么?

    Linux设备树是什么?随着Linux的不断发展,基本上现在所有的驱动程序都是基于设备树的,而设备树到底是什么?有什么作用,Linux内核怎么通过设备树知道外设适配的。文本介绍了设备树、以及分享了一些设备树的基本语法、一些基本属性等,最后简单分析了设备匹配的基本流程

    2022年6月16日
    46
  • 网络推广100种方法有哪些_100种宣传方式

    网络推广100种方法有哪些_100种宣传方式一米软件发现网上很多人都在找网络推广100种方法,但 其实网站推广并不是方法越多越好,而是找到适合自己的方法为宜,下面一米软件就来给大家介绍下一些常用网站推广的方法。1、搜索引擎营销搜索引擎营销,这种方法一般是通过自建官网然后针对官网进行优化与更新,使得网站在搜索引擎中有一个好的排名。也有通过做付费推广,使得网站的某个关键词在搜索引擎中有个好的排名。2、自媒…

    2022年4月20日
    192
  • 950. 郁闷的出纳员(Splay树)「建议收藏」

    950. 郁闷的出纳员(Splay树)「建议收藏」OIER 公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。

    2022年8月9日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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