分享

MFC list control 奇偶行颜色不同设置

 学海无涯GL 2013-10-21

假设你的List Control 放在窗口XXX上,ID号是IDC_FILELIST , 那么在类视图中找到窗口XXX对应的类CXXXDlg.cpp ,右键属性 然后选择 添加事件 那个图标,

找到IDC_FILELIST 添加NM_CUSTOMDRAW 消息

然后在OnNMCustomdrawFilelist()函数中添加如下代码:

void CXXXDlg::OnNMCustomdrawFilelist(NMHDR *pNMHDR, LRESULT *pResult)

{

//LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);

// TODO: Add your control notification handler code here

*pResult = 0;


NMLVCUSTOMDRAW* pNMCD = (NMLVCUSTOMDRAW*)(pNMHDR);


if(CDDS_PREPAINT == pNMCD->nmcd.dwDrawStage)

{

*pResult = CDRF_NOTIFYITEMDRAW;

}

else if (CDDS_ITEMPREPAINT == pNMCD->nmcd.dwDrawStage)

{

*pResult = CDRF_NOTIFYSUBITEMDRAW;

}

else if((CDDS_ITEMPREPAINT|CDDS_SUBITEM)==pNMCD->nmcd.dwDrawStage)

{

COLORREF  clrNewTextColor, clrNewBkColor;

int nItem = static_cast<int>(pNMCD->nmcd.dwItemSpec);

if(nItem %2)

{

clrNewTextColor = RGB(0,0,0);

clrNewBkColor = RGB(204,255,255);

}

else

{

clrNewTextColor = RGB(0,0,0);

clrNewBkColor = RGB(255,255,255);

}


pNMCD->clrText = clrNewTextColor;

pNMCD->clrTextBk = clrNewBkColor;

*pResult = CDRF_DODEFAULT ;

}

}

其中涉及到NMLVCUSTOMDRAW和NMCUSTOMDRAW  这个两个结构体,他们的原型如下:

typedef struct tagNMLVCUSTOMDRAW 

NMCUSTOMDRAW   nmcd;                // 包含客户自绘控件信息的结构 

COLORREF             clrText;              // 列表视图显示文字的颜色 

COLORREF             clrTextBk;          // 列表视图显示文字的背景色 

} NMLVCUSTOMDRAW, *LPNMLVCUSTOMDRAW;


typedef struct tagNMCUSTOMDRAWINFO {

NMHDR hdr; //是一个包含NM_CUSTOMDRAW 这个通知消息的NMHDR结构体的句柄

DWORD dwDrawStage; //指定当前的绘制阶段,共有四个阶段,注释附后

HDC hdc; // 一个指向控件设备上下文的DC句柄,通过这个hdc可以操作任何GDI函数

RECT rc; //指定绘制的矩形区域

DWORD dwItemSpec; //绘制项的说明

UINT uItemState; //当前项的状态

LPARAM lItemlParam //应用程序定义的数据

} NMCUSTOMDRAW, FAR * LPNMCUSTOMDRAW;


上面涉及到的NMHDR结构

typedef struct tagNMHDR { 

HWND hwndFrom; //指向控件放送消息的窗口句柄

UINT idFrom;  //控件发送消息的标识符

UINT code; //通知代码,不支持NM_RCLICK和NM_RDBCLICK通知代码

} NMHDR;


NMLVCUSTOMDRAW.nmcd.dwDrawStage字段主要包含如下4种枚举类型:

CDDS_POSTERASE: 表示在擦除循环结束之后的阶段

CDDS_POSTPAINT:表示在绘画循环结束之后的阶段

CDDS_PREERASE: 表示在擦除循环开始之前的阶段

CDDS_PREPAINT: 表示在绘画前阶段


指定上面的某个阶段可用的值如下:

CDDS_ITEMPREPAINT:表示在列表项的绘画前阶段

CDDS_ITEMPOSTPAINT: 表示在列表项的绘画后阶段

CDDS_ITEMPOSTERASE: 表示在列表项的擦除后阶段

CDDS_ITEMPREERASE: 表示在列表项的擦除前阶段

CDDS_ITEM:表示要绘制项的信息已经可用。




dwDrawStage是用来指定当前绘制的阶段的,那么就是说单一的NM_CUSTOMDRAW处理在每个绘制阶段都进行调用。那么怎么知道当前要绘制的是哪个阶段呢? 或者说绘制了当前阶段之后,下一个阶段是对哪个阶段进行绘制呢?

这就是通过设置NM_CUSTOMDRAW消息函数的第二个参数pResult来完成。事实上,如果不对pResult值进行设置,那么当初始阶段的CDDS_PREPAINT调用函数之后,NM_CUSTOMDRAW消息函数就不再被调用了,因为你没有传递给它下一个阶段是要绘制操作哪个阶段。

从技术上来讲,只有两个阶段需要指定的绘制阶段(CDDS_PAREPAINT和CDDS_ITEMPREPAINT),因为它们影响着发送消息的内容。一般而言,通常只需在处理程序的最后指定代码将处理的绘制阶段。下面是用于指定所需要绘制阶段的值:

CDRF_DEFAULT :指示控件自行绘制。改值为默认值,不应该将它与其它值组合使用

CDRF_SKIPDEFAULT:用于指定控件根本不进行任何绘制

CDRF_NEWFONT:当代码更改绘制项/子项的字体时使用

CDRF_NOTIFYPOSTPAINT:使通知信息在控件或每个项/子项绘制后发送

CDRF_NOTIFYITEMDRAW:指出项(或子项)将进行绘制。注意,它下面的值与 CDRF_NOTIFYSUBITEMDRAW 相同

CDRF_NOTIFYSUBITEMDRAW:指出子项(或项)将进行绘制。注意,它下面的值与 CDRF_NOTIFYITEMDRAW 相同

CDRF_NOTIFYPOSTERASE:当删除控件后需要通知代码时使用

 

=========================================================================

自绘CListCtrl类 奇偶行颜色设置

  

//自绘CListCtrl类,重载虚函数DrawItem

void CNewListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
 // TODO: Add your code to draw the specified item
 ASSERT(lpDrawItemStruct->CtlType == ODT_LISTVIEW);
 CDC dc;
 dc.Attach(lpDrawItemStruct->hDC);
 ASSERT(NULL != dc.GetSafeHdc());
 // Save these value to restore them when done drawing.
 COLORREF crOldTextColor = dc.GetTextColor();
 COLORREF crOldBkColor = dc.GetBkColor();
 
 // If this item is selected, set the background color
 // and the text color to appropriate values. Also, erase
 // rect by filling it with the background color.
 if ((lpDrawItemStruct->itemAction | ODA_SELECT) &&
  (lpDrawItemStruct->itemState & ODS_SELECTED))
 {
  dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
  dc.SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
  dc.FillSolidRect(&lpDrawItemStruct->rcItem,
   ::GetSysColor(COLOR_HIGHLIGHT));
 }
 else
 {
  if(lpDrawItemStruct->itemID%2)
   dc.FillSolidRect(&lpDrawItemStruct->rcItem, RGB(128,128,128));
  else
   dc.FillSolidRect(&lpDrawItemStruct->rcItem, RGB(255,128,255));
 }
 
 // If this item has the focus, draw a red frame around the
 // item's rect.
 if ((lpDrawItemStruct->itemAction | ODA_FOCUS) &&
  (lpDrawItemStruct->itemState & ODS_FOCUS))
 {
  CBrush br(RGB(0, 0, 128));
  dc.FrameRect(&lpDrawItemStruct->rcItem, &br);
 }

 // Draw the text.
 CString strText(_T(""));
 CRect rcItem;

 for(int i=0; i<GetHeaderCtrl()->GetItemCount(); i++)
 {
  strText = GetItemText(lpDrawItemStruct->itemID, i);
  GetSubItemRect(lpDrawItemStruct->itemID, i, LVIR_LABEL, rcItem);
  rcItem.left += 5;
  dc.DrawText(
   strText,
   strText.GetLength(),
   &rcItem,
  DT_LEFT|DT_SINGLELINE|DT_VCENTER);
 }
 
 // Reset the background color and the text color back to their
 // original values.
 dc.SetTextColor(crOldTextColor);
 dc.SetBkColor(crOldBkColor);
 
 dc.Detach();
}

// 调用

CNewListCtrl m_list; // 类的成员变量

 

#define IDC_LIST 0x1101
 m_list.Create(WS_CHILD|WS_VISIBLE|WS_BORDER|WS_VSCROLL|WS_HSCROLL|LVS_OWNERDRAWFIXED, CRect(0, 0, 280, 280), this, IDC_LIST);
 m_list.ModifyStyle(0, LVS_REPORT|LVS_SINGLESEL);
 m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
 m_list.InsertColumn(0, _T("AAA"), LVCFMT_LEFT, 100);
 m_list.InsertColumn(1, _T("BBB"), LVCFMT_LEFT, 100);

 CString strText(_T(""));
 for(int i=0; i<20; i++)
 {
  m_list.InsertItem(i, _T(""));
  strText.Format(_T("%d - Hello, World!"), i+1);
  m_list.SetItemText(i, 0, strText);
  strText.Format(_T("%d - ABCDEFG"), i+1);
  m_list.SetItemText(i, 1, strText);
 }


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多