MSDN NM_CUSTOMDRAW (list view) 中文翻译

本文详细介绍了NM_CUSTOMDRAW通知在ListView控件中的作用,包括通知的发送方式、参数说明、返回值解释及注意事项。重点阐述了如何在不同状态下控制ListView的重绘操作,以及如何通过NM_CUSTOMDRAW通知进行自定义重绘行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NM_CUSTOMDRAW (list view) Notification

NM_CUSTOMDRAW(list view)通知


Sent by a list-view control to notify its parent windows about drawing operations. This notification is sent in the form of a WM_NOTIFY message.

list-view控件向其父窗口发送重绘操作的通知。这些通知以WM_NOTIFY消息的形式发送。

Syntax

NM_CUSTOMDRAW

    lpNMCustomDraw = (LPNMLVCUSTOMDRAW) lParam;

Parameters

lpNMCustomDraw

Pointer to a NMLVCUSTOMDRAW structure that contains information about the drawing operation. The first member of this structure, nmcd, is a pointer to an NMCUSTOMDRAW structure. The dwItemSpec member of the structure pointed to by nmcd contains the identifier of the item being drawn and the lItemlParam member contains its application-defined data.

包含重绘操作信息的NMLVCUSTOMDRAW结构体指针。Nmcd是此结构体的第一个成员,它是指向NMCUSTOMDRAW结构体的指针。Nmcd的结构体包含了正被重绘成员的标识符dwItemSpec和应用程序定义的数据lItemlParam

Return Value

The value your application can return depends on the current drawing stage. The dwDrawState member of the associated NMCUSTOMDRAW structure holds a value that specifies the drawing stage. You must return one of the following values.

程序的返回值可以根据当前的绘制阶段而定。NMCUSTOMDRAW结构体成员dwDrawState指定了一个代表当前状态的值。你必须返回下列这些值。

CDRF_DODEFAULT

The control will draw itself. It will not send any additional NM_CUSTOMDRAW messages for this paint cycle. This occurs when dwDrawState equals CDDS_PREPAINT.

控件将绘制自己。它将不再为循环绘画发送额外的NM_CUSTOMDRAW消息。当dwDrawStateCDDS_PREPAINT时将发生这种情况。

CDRF_DOERASE

Windows Vista. The control will not draw the focus rect around an item.

Windows Vista中,控件将不再绘制项目焦点周围的矩形。

CDRF_NOTIFYITEMDRAW

The control will notify the parent of any item-related drawing operations. It will send NM_CUSTOMDRAW notification messages before and after drawing items. This occurs when dwDrawState equals CDDS_PREPAINT.

控件将通知绘画操作给任何项目相关的父窗口。在重绘前后它将发送CUSTOMDRAW通知。当dwDrawStateCDDS_PREPAINT时将发生这种情况。

CDRF_NOTIFYITEMERASE

Windows NT 4.0 only. The control will notify the parent when an item will be erased. It will send NM_CUSTOMDRAW notification messages before and after erasing items. This occurs when dwDrawState equals CDDS_PREPAINT.

只对Windows NT 4.0有效。当控件要擦除一个项目时它将通知其父窗口。在重绘前后它将发送CUSTOMDRAW通知。当dwDrawStateCDDS_PREPAINT时将发生这种情况。

CDRF_NOTIFYPOSTERASE

The control will notify the parent after erasing an item. This occurs when dwDrawState equals CDDS_PREPAINT.

当控件擦除一个项目后它将通知其父窗口。当dwDrawStateCDDS_PREPAINT时将发生这种情况。

CDRF_NOTIFYPOSTPAINT

The control will notify the parent after painting an item. This occurs when dwDrawState equals CDDS_PREPAINT.

当控件重绘一个项目后它将通知其父窗口。当dwDrawStateCDDS_PREPAINT时将发生这种情况。

CDRF_NEWFONT

The application specified a new font for the item; the control will use the new font. For more information about changing fonts, see Changing fonts and colors. This occurs when dwDrawState equals CDDS_ITEMPREPAINT.

当应用程序为项目设定新字体,控件也将使用这个新字体。更多关于改变字体的信息请参考Changing fonts and colors。当dwDrawStateCDDS_ITEMPREPAINT时将发生这种情况。

CDRF_NOTIFYSUBITEMDRAW

Version 4.71. Your application will receive an NM_CUSTOMDRAW message with dwDrawState set to CDDS_ITEMPREPAINT | CDDS_SUBITEM before each list-view subitem is drawn. You can then specify font and color for each subitem separately or return CDRF_DODEFAULT for default processing. This occurs when dwDrawState equals CDDS_ITEMPREPAINT.

4.71版本。在list-view 子项目被重绘前应用程序将接收到NM_CUSTOMDRAW消息,而dwDrawState 被设置为 CDDS_ITEMPREPAINT | CDDS_SUBITEM。当dwDrawStateCDDS_ITEMPREPAINT时将发生这种情况。

CDRF_SKIPDEFAULT

The application drew the item manually. The control will not draw the item. This occurs when dwDrawState equals CDDS_ITEMPREPAINT.

应用程序手动重绘项目。控件不会绘制项目。当dwDrawStateCDDS_ITEMPREPAINT时将发生这种情况。

CDRF_SKIPPOSTPAINT

Windows Vista. The control will only paint the background.

Windows Vista中,控件将只绘制背景。

 

Remarks

Version 5.80. If you change the font by returning CDRF_NEWFONT, the list-view control might display clipped text. This behavior is necessary for backward compatibility with earlier versions of the common controls. If you want to change the font of a list-view control, you will get better results if you send a CCM_SETVERSION message with the wParam value set to 5 before adding any items to the control.

Version 5.80.如果你通过返回CDRF_NEWFONT改变字体,list-view控件可能会显示省略的文本信息。这样做主要是为了向后兼容早期的通用控件版本。如果你想改变list-view控件的字体,在给控件添加任何项目前发送CCM_SETVERSION消息并将wParam设为5,你将得到更好的结果。

Notification Requirements

Minimum DLL Version

comctl32.dll version 4.70 or later

Header

commctrl.h

Minimum operating systems

Windows 2000, Windows NT 4.0 with Internet Explorer 3.0, Windows 98, Windows 95 with Internet Explorer 3.0

 

<think>我们正在处理一个MFC编程问题,用户想要实现HDN_CUSTOMDRAW消息的处理函数。HDN_CUSTOMDRAW是HeaderControl发送的自定义绘制消息,允许我们自定义表头的绘制。根据MFC的消息映射机制,我们需要在对话框或视图类中添加消息映射和处理函数。步骤:1.在类声明中(通常在头文件中)声明消息处理函数。该函数应具有特定的签名,对于HDN_CUSTOMDRAW消息,处理函数应该类似于:afx_msgvoidOnHdnCustomDraw(NMHDR*pNMHDR,LRESULT*pResult);2.在类的消息映射表中添加对应的映射项。HDN_CUSTOMDRAW消息对应的映射宏是ON_NOTIFY,因为它是WM_NOTIFY消息的一种。3.在实现文件中定义该消息处理函数,并在其中编写自定义绘制逻辑。注意:HDN_CUSTOMDRAW消息是由表头控件(CHeaderCtrl)发送的,通常嵌入在CListCtrl(报告视图)或CListBox等控件中。因此,我们需要在拥有该表头控件的父窗口(比如对话框或视图)中处理此消息。下面是一个具体的实现步骤:###1.在头文件中声明消息处理函数在对话框类(假设为CMyDialog)的头文件中(如MyDialog.h)添加函数声明:```cpp//MyDialog.hclassCMyDialog:publicCDialogEx{//...其他代码protected:afx_msgvoidOnHdnCustomDraw(NMHDR*pNMHDR,LRESULT*pResult);DECLARE_MESSAGE_MAP()};```###2.在消息映射表中添加映射在对话框的实现文件(MyDialog.cpp)中,添加消息映射:```cppBEGIN_MESSAGE_MAP(CMyDialog,CDialogEx)//...其他消息映射ON_NOTIFY(HDN_CUSTOMDRAW,0,&CMyDialog::OnHdnCustomDraw)END_MESSAGE_MAP()```注意:上面的第二个参数是控件的ID。如果表头控件是另一个控件(如列表控件)的一部分,那么通常我们使用列表控件的ID。但是,由于表头控件是列表控件内部的,它发送的通知消息的ID实际上是列表控件的ID。然而,在ON_NOTIFY宏中,我们需要指定发送通知的控件的ID。这里有一个关键点:表头控件发送的HDN_CUSTOMDRAW消息,实际上是通过列表控件转发给父窗口的,所以这里应该填写列表控件的ID。如果我们的列表控件ID是IDC_LIST1,那么应该这样写:```cppON_NOTIFY(HDN_CUSTOMDRAW,IDC_LIST1,&CMyDialog::OnHdnCustomDraw)```但是,请注意,HDN_CUSTOMDRAW消息的通知代码是HDN_CUSTOMDRAW,它是由表头控件发送的,而表头控件本身没有单独的ID(它是列表控件的一部分)。在MFC中,当我们使用列表控件时,表头的通知消息会以列表控件的ID作为控件ID发送。因此,我们使用列表控件的ID。###3.实现消息处理函数在MyDialog.cpp中实现OnHdnCustomDraw函数:```cppvoidCMyDialog::OnHdnCustomDraw(NMHDR*pNMHDR,LRESULT*pResult){//将pNMHDR转换为指向NMCUSTOMDRAWNMCUSTOMDRAWHEADER的指针?//实际上,对于HDN_CUSTOMDRAW,它实际上是LPNMHEADER类型,但更具体的是LPNMCUSTOMDRAW?//注意:HDN_CUSTOMDRAW对应的结构体是NMCUSTOMDRAWHEADER(在MSDN中,它实际上是NMCUSTOMDRAW结构体的扩展,但用于表头)LPNMCUSTOMDRAWpNMCD=reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);*pResult=CDRF_DODEFAULT;//默认处理//根据绘制阶段进行处理switch(pNMCD->dwDrawStage){caseCDDS_PREPAINT://在绘制之前,请求自定义绘制每个项*pResult=CDRF_NOTIFYITEMDRAW;break;caseCDDS_ITEMPREPAINT://绘制每个项之前{//此时,pNMCD实际上是LPNMCUSTOMDRAWHEADER(即NMCUSTOMDRAW的扩展),但我们可以将其视为NMCUSTOMDRAW//如果要获取表头项的信息,我们需要使用NMCUSTOMDRAWHEADER结构,但注意MFC中可能没有直接定义这个结构,实际上在WindowsSDK中,它是NMCUSTOMDRAW结构,并且对于表头,没有额外的字段(除了NMCUSTOMDRAW的字段)。//但是,在表头的自定义绘制中,我们通常使用NMCUSTOMDRAW结构即可。//获取当前绘制的表头项的索引intiItem=static_cast<int>(pNMCD->dwItemSpec);//dwItemSpec是当前项的索引//示例:将第一项的背景色设置为红色if(iItem==0){//设置文本颜色::SetTextColor(pNMCD->hdc,RGB(255,255,255));//白色文本//设置背景颜色::SetBkColor(pNMCD->hdc,RGB(255,0,0));//红色背景}//告诉系统我们已处理了颜色,不再使用默认颜色*pResult=CDRF_NEWFONT;}break;}}```注意:上述代码中,我们处理了CDDS_PREPAINT和CDDS_ITEMPREPAINT阶段。在CDDS_PREPAINT阶段,我们返回CDRF_NOTIFYITEMDRAW,这样系统会在每个表头项绘制前发送CDDS_ITEMPREPAINT消息。在CDDS_ITEMPREPAINT阶段,我们可以设置每个项的颜色。###注意事项-表头自定义绘制的结构体实际上是`NMCUSTOMDRAW`,它用于多个控件的自定义绘制。对于表头,它没有额外的字段,所以我们可以直接使用`NMCUSTOMDRAW`。-在设置文本颜色和背景色后,我们返回`CDRF_NEWFONT`,表示我们已经修改了字体(颜色)属性,系统将使用我们设置的颜色进行绘制。-如果想要更复杂的绘制(比如自己绘制整个项),可以返回`CDRF_SKIPDEFAULT`,然后自己调用DrawText等函数进行绘制,但这样就需要处理所有的绘制。###总结通过以上步骤,我们在MFC中实现了HDN_CUSTOMDRAW消息的处理,可以自定义表头的绘制。§§相关问题§§1.如何为MFC列表控件的表头设置不同的背景色?2.在MFC中,如何处理其他自定义绘制消息(如列表控件的NM_CUSTOMDRAW)?3.如何自己绘制整个表头项?</think>### 在MFC中实现HDN_CUSTOMDRAW消息处理 在MFC中处理`HDN_CUSTOMDRAW`消息需要以下步骤: #### 1. **添加消息映射** 在父窗口(对话框/视图)的消息映射表中添加`ON_NOTIFY`宏: ```cpp // 头文件声明 class CMyDialog : public CDialogEx { protected: afx_msg void OnHdnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult); DECLARE_MESSAGE_MAP() }; // 实现文件 BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx) ON_NOTIFY(HDN_CUSTOMDRAW, 0, &CMyDialog::OnHdnCustomDraw) END_MESSAGE_MAP() ``` > 注意:第二个参数 `0` 表示表头控件ID。若表头是列表控件的子控件(如`CListCtrl`),需使用列表控件的ID[^1]。 #### 2. **实现处理函数** ```cpp void CMyDialog::OnHdnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) { // 转换为NMCUSTOMDRAW结构体 LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR); switch (pNMCD->dwDrawStage) { case CDDS_PREPAINT: // 请求逐项绘制通知 *pResult = CDRF_NOTIFYITEMDRAW; break; case CDDS_ITEMPREPAINT: { // 获取当前表头项索引 int iItem = static_cast<int>(pNMCD->dwItemSpec); // 示例:设置第一项为红底白字 if (iItem == 0) { ::SetTextColor(pNMCD->hdc, RGB(255,255,255)); // 白色文字 ::SetBkColor(pNMCD->hdc, RGB(255,0,0)); // 红色背景 *pResult = CDRF_NEWFONT; // 应用新颜色 } else { *pResult = CDRF_DODEFAULT; // 默认绘制 } break; } default: *pResult = CDRF_DODEFAULT; } } ``` #### 3. **关键说明** 1. **控件ID问题**: - 表头控件通常没有独立ID,需使用父列表控件的ID - 若列表控件ID为`IDC_LIST1`,应修改为: ```cpp ON_NOTIFY(HDN_CUSTOMDRAW, IDC_LIST1, &CMyDialog::OnHdnCustomDraw) ``` 2. **绘制阶段控制**: - `CDDS_PREPAINT`:初始化绘制阶段 - `CDDS_ITEMPREPAINT`:逐项绘制阶段 - 返回值说明: - `CDRF_NOTIFYITEMDRAW`:请求项级绘制 - `CDRF_NEWFONT`:应用新字体/颜色 - `CDRF_DODEFAULT`:使用默认绘制[^2] 3. **结构体转换**: - `NMCUSTOMDRAW`是通用结构,表头控件无专用结构 - 通过`dwItemSpec`获取当前项索引 - 使用GDI函数直接操作设备上下文(HDC)[^3] #### 4. **高级应用** ```cpp case CDDS_ITEMPREPAINT: { // 动态设置颜色 if (IsSpecialItem(iItem)) { CDC* pDC = CDC::FromHandle(pNMCD->hdc); pDC->SetTextColor(m_crTextColor); pDC->SetBkColor(m_crBkgndColor); *pResult = CDRF_NEWFONT; } // 自定义绘制背景 else if (iItem == 2) { CRect rcItem(pNMCD->rc); CBrush br(RGB(0,100,200)); FillRect(pNMCD->hdc, &rcItem, br); *pResult = CDRF_SKIPDEFAULT; // 跳过默认绘制 } break; } ``` > **注意事项**: > - 需要在列表控件初始化后处理消息(`OnInitDialog`中创建控件) > - 复杂绘制可结合`CDRF_NOTIFYPOSTPAINT`进行后期处理 > - 使用`CDRF_SKIPDEFAULT`完全接管绘制过程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值