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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Java中的数据类型详解——boolean类型

    Java中的数据类型详解——boolean类型BooleanTest01.java/* 1、在java语言中boolean类型只有两个值,没有其他值: true和false。 不像c或者c++,c语言中1和0也可以表示布尔类型。 2、boolean类型在实际开发中使用在哪里呢? 使用在逻辑判断当中,通常放在条件的位置上(充当条件)。*/publicclassBooleanTest01{ publicstaticvoidmain(String[]args){ //错误:不兼容的类型:int无法转换为boole

    2022年7月8日
    65
  • oracle表字段为汉字,依据拼音排序

    oracle表字段为汉字,依据拼音排序

    2021年9月16日
    67
  • TiDB建库建用户及授权

    TiDB建库建用户及授权

    2021年4月22日
    160
  • SecureCRTPortable链接ip(虚拟机)(图文详解)

    SecureCRTPortable链接ip(虚拟机)(图文详解)【确定虚拟机ip地址】可参考:https://blog.csdn.net/weixin_44727274/article/details/107265723SecureCRTPortable是个绿色文件,下载安装包,解压即可使用。虚拟机开启下,双击打开,建立快速连接:设置完成后,点击【链接】输入密码后,…

    2022年5月26日
    36
  • mysql存储过程菜鸟教程_mysql存储过程实例详解

    mysql存储过程菜鸟教程_mysql存储过程实例详解详细实例全⾯解析SQL存储过程存储过程(StoredProcedure),是⼀组为了完成特定功能的SQL语句,类似⼀门程序设计语⾔,也包括了数据类、流程控制、输⼊和输出和它⾃⼰的函数库。存储过程可以说是⼀个记录集,它是由⼀些T-SQL语句组成的代码块,这些T-SQL语句代码像⼀个⽅法⼀样实现⼀些功能(对单表或多表的增删改查),然后再给这个代码块取⼀个名字,在⽤到这个功能的时候调⽤他就⾏了。…

    2022年10月5日
    4
  • 如何区别标准POE交换机和非标POE交换机[通俗易懂]

    如何区别标准POE交换机和非标POE交换机[通俗易懂]通俗的说,POE交换机就是支持网线供电的交换机,其不但可以实现普通交换机的数据传输功能还能同时对网络终端进行供电。那么,我们该如何来区别如何区别标准POE交换机和非标POE交换机呢?接下来我们就跟随飞畅科技的小编一起来详细看看吧!一、什么是POE交换机PoE供电交换机是指能够通过网线为远端受电终端提供网络供电的交换机,包含网络交换机和PoE供电两个功能,是PoE供电系统中比较常见的供电设备。二、POE交换机的分类1、标准POE交换机符合IEEE802.3af、802.3at标准,就是标准P..

    2022年10月4日
    7

发表回复

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

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