Visual C++2005中开发自定义绘图控件2.3
来源:互联网 发布:环宇蓝博软件 编辑:程序博客网 时间:2024/05/21 22:46
Visual C++2005中开发自定义绘图控件 href="http://www.itspzo.com/Article/Microsoft/kfyy/VisualC/kj/200605/www.itspzo.com">www.itspzo.com 作者:佚名 文章来源:msdn 点击数: 75 更新时间:2006-5-23
指定处理所需的绘制阶段
正如我在前面提到的,绘制一个控件存在一些“阶段”。特别是,您可以将绘制过程理解为一系列阶段,其中控件通知其父窗口需要绘制的内容。事实上,控件甚至会在绘制控件及其各项前后发送一个通知,从而让编程人员更好地控制该过程。
在所有情况下,单一的 NM_CUSTOMDRAW 处理程序在每个绘制阶段都进行调用。然而,谨记:自定义绘制允许您在自己的绘制中合并默认的控件绘制,您需要指定您将处理哪个绘制阶段。这通过设置 NM_CUSTOMDRAW 处理程序的第二个参数 (pResult) 完成。事实上,如果您从未设置该值,则用初始阶段的 CDDS_PREPAINT 调用函数后,您的函数将不再被调用!
从技术上讲,只有两个阶段指定需要的绘制阶段(CDDS_PREPAINT 和 CDDS_ITEMPREPAINT),它们影响发送通知消息的内容。然而,通常只在处理程序的最后指定代码将处理的绘制阶段。表 2 列出用于指定所需绘制阶段(代码关注的)的值。
表 2:自定义绘制返回标志
自定义绘制返回标志 含义 CDRF_DEFAULT 指示控件自行绘制。该值为默认值,不应该将它与其他值组合在一起。 CDRF_SKIPDEFAULT 用于指定控件根本不进行任何绘制。 CDRF_NEWFONT 当代码更改绘制项/子项的字体时使用。 CDRF_NOTIFYPOSTPAINT 使通知信息在控件或每个项/子项绘制后发送。 CDRF_NOTIFYITEMDRAW 指出项(或子项)将进行绘制。注意,它下面的值与 CDRF_NOTIFYSUBITEMDRAW 相同。 CDRF_NOTIFYSUBITEMDRAW 指出子项(或项)将进行绘制。注意,它下面的值与 CDRF_NOTIFYITEMDRAW 相同。 CDRF_NOTIFYPOSTERASE 当删除控件后需要通知代码时使用。
以下为一个示例,其中的代码指定,当绘制控件的项 (CDRF_NOTIFYITEMDRAW) 及子项 (CDRF_NOTIFYPOSTPAINT),以及绘制完成时,应该调用 NM_CUSTOMDRAW 处理程序。
void CListCtrlWithCustomDraw::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR);
...
*pResult = 0; // Initialize value
*pResult |= CDRF_NOTIFYITEMDRAW;
*pResult |= CDRF_NOTIFYSUBITEMDRAW;
*pResult |= CDRF_NOTIFYPOSTPAINT;
}
筛选指定的绘制阶段
一旦指定要关注的阶段后,您需要处理这些阶段。因为绘制过程的每个阶段只有一个消息要发送,惯例是执行一个 switch 语句以决定准确的绘制阶段。不同的绘制阶段由以下标志定义:
CDDS_PREPAINT
CDDS_ITEM
CDDS_ITEMPREPAINT
CDDS_ITEMPOSTPAINT
CDDS_ITEMPREERASE
CDDS_ITEMPOSTERASE
CDDS_SUBITEM
CDDS_POSTPAINT
CDDS_PREERASE
CDDS_POSTERASE
对于一个 CListCtrl 派生的类,有一个 NM_CUSTOMDRAW 处理程序的示例,其中您可以发现,代码决定当前绘制阶段的方式:
void CMyCustomDrawControl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR);
switch(pNMCD->dwDrawStage)
{
case CDDS_PREPAINT:
...
break;
case CDDS_ITEMPREPAINT:
...
break;
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
...
break;
...
}
*pResult = 0;
}
注意,为了决定子项(例如,列表视图控件)绘制的阶段,您必需使用按位 or 操作符,它有两个值:其中一个为 CDDS_ITEMPREPAINT 或者 CDDS_ITEMPOSTPAINT,另一个为 CDDS_SUBITEM。
要说明它,我们假定您想在绘制列表视图项之前进行一些处理。将编写 switch 语句来处理 CDDS_ITEMPREPAINT。
case CDDS_ITEMPREPAINT:
...
break;
然而,如果是您所关注子项的预绘制阶段,则将如下操作:
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
...
break;
示例:创建一个列表视图控件自定义绘制控件
如前面提到的,您可以完全控制控件及其项的绘制,或者仅执行一小部分特定于应用程序的绘制,并让控件继续进行。本文的焦点更多地偏重于控件绘制技术而非高级的绘制技术,我们将演练一个简单的示例,其中列表视图控件是一个自定义的绘制,因此项的文本将在创建拼接外观的交替单元中显示为不同的颜色。
·创建一个基于 Visual C++ 2005 对话框的项目,名为 ListCtrlColor。
·从 Class View 中选择 Project 菜单选项,并单击 Add Class 调用 Add Class 对话框。
·从分类列表中选择 MFC,然后从模板列表中选择 MFC Class。
·单击 Add 按钮,调用 MFC Class Wizard 对话框。
·对于 Class name胫?CListCtrlWithCustomDraw 并选择 CListCtrl 的 Base class。
·单击 Finish 按钮,生成类的标头和执行文件。
·对于 Class View,右键单击 CListCtrlWithCustomDraw 类,并选择 Properties 上下文菜单选项。
·显示 Properties 窗口时,单击顶部的 Messages 按钮,显示一个两列的消息列表,您可以为其实现处理程序。
·在消息列表中单击 NM_CUSTOMDRAW 项,然后下拉第二列的组合框箭头,并选择值 OnNMCustomdraw。
·现在,处理绘制代码。这里,我们只简单处理项和子项预绘制阶段,指定基于当前行(项)和列(子项)的文本和背景色。要进行此操作,按如下所示修改 OnNMCustomdraw 函数:
void CListCtrlWithCustomDraw::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLVCUSTOMDRAW lpLVCustomDraw = reinterpret_cast(pNMHDR);
switch(lpLVCustomDraw->nmcd.dwDrawStage)
{
case CDDS_ITEMPREPAINT:
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
if (0 == ((lpLVCustomDraw->nmcd.dwItemSpec + lpLVCustomDraw->iSubItem) % 2))
{
lpLVCustomDraw->clrText = RGB(255,255,255); // white text
lpLVCustomDraw->clrTextBk = RGB(0,0,0); // black background
}
else
{
lpLVCustomDraw->clrText = CLR_DEFAULT;
lpLVCustomDraw->clrTextBk = CLR_DEFAULT;
}
break;
default: break;
}
*pResult = 0;
*pResult |= CDRF_NOTIFYPOSTPAINT;
*pResult |= CDRF_NOTIFYITEMDRAW;
*pResult |= CDRF_NOTIFYSUBITEMDRAW;
}
现在,我们来测试新控件。要进行此操作,您只需使用 CListCtrlWithCustomDraw 类将列表视图控件放在对话框中,并对其进行子类派生。下面是完成该操作的步骤。
·在 Resource 视图中,打开应用程序的主对话框 (IDD_LISTCTRLCOLOR_DIALOG)。
·从 Toolbox 中,将一个 List Control 拖放到该对话框。
·右键单击列表控件,并选择 Properties 上下文菜单选项。
·将 View 属性设置为 Report。
·右键单击控件,并选择 Add Variable 上下文菜单选项。
·出现 Add Member Variable Wizard 对话框时,指定 m_lstBooks 的 Variable name,并单击 Finish 按钮。
·这时,您就有了一个 CListCtrl 派生类 (m_lstBooks),它将对话框上的列表视图控件进行子类派生。然而,m_lstBooks 需要从最新创建的 CListCtrlWithCustomDraw 派生,以便于调用您的绘制代码。因此,打开对话框的标题文件 (ListCtrlColorDlg.h),将 m_lstBooks 更改为 CListCtrlWithCustomDraw 类型。
·在 CListCtrlColorDlg 类开始之前,添加以下指令。
#include "ListCtrlWithCustomDraw.h"
·将下面的代码添加到对话框的 OnInitDialog 成员函数,这样我们就能够看到一些列表视图行。
// Insert the columns
m_lstBooks.InsertColumn(0, _T("Author"));
m_lstBooks.InsertColumn(1, _T("Book"));
// Define the data
static struct
{
TCHAR m_szAuthor[50];
TCHAR m_szTitle[100];
} BOOK_INFO[] = {
_T("Tom Archer"), _T("Visual C++.NET Bible"),
_T("Tom Archer"), _T("Extending MFC with the .NET Framework"),
_T("Brian Johnson"), _T("XBox 360 For Dummies")
};
// Insert the data
int idx;
for (int i = 0; i < sizeof BOOK_INFO / sizeof BOOK_INFO[0]; i++)
{
idx = m_lstBooks.InsertItem(i, BOOK_INFO[i].m_szAuthor);
m_lstBooks.SetItemText(i, 1, BOOK_INFO[i].m_szTitle);
}
·现在,建立并运行应用程序。图 1 为应用程序外观的一个示例。
小结
当 Windows 首次作为“下一代”操作系统引入到应用程序开发之中时,它作为新图形用户界面的一个主要论据就是其一致性。该论据的要点所在是其具有一个通用的外观:统一的菜单项、通用控件等。这一通用性的感觉可能会一直延续,直到有第二家公司想设计其自己的应用程序。简单说,提供外观与其他应用程序雷同的应用程序,任何公司都不会逃离这一怪圈。
要建立一个唯一的且让人过目难忘的用户界面,其中一种方式是为应用程序设计并开发自定义的控件。希望本文能对您有所帮助,现在,您了解到一种非常强大的技术,它使您的应用程序能从众多竞争对手的应用程序中脱颖而出。
指定处理所需的绘制阶段
正如我在前面提到的,绘制一个控件存在一些“阶段”。特别是,您可以将绘制过程理解为一系列阶段,其中控件通知其父窗口需要绘制的内容。事实上,控件甚至会在绘制控件及其各项前后发送一个通知,从而让编程人员更好地控制该过程。
在所有情况下,单一的 NM_CUSTOMDRAW 处理程序在每个绘制阶段都进行调用。然而,谨记:自定义绘制允许您在自己的绘制中合并默认的控件绘制,您需要指定您将处理哪个绘制阶段。这通过设置 NM_CUSTOMDRAW 处理程序的第二个参数 (pResult) 完成。事实上,如果您从未设置该值,则用初始阶段的 CDDS_PREPAINT 调用函数后,您的函数将不再被调用!
从技术上讲,只有两个阶段指定需要的绘制阶段(CDDS_PREPAINT 和 CDDS_ITEMPREPAINT),它们影响发送通知消息的内容。然而,通常只在处理程序的最后指定代码将处理的绘制阶段。表 2 列出用于指定所需绘制阶段(代码关注的)的值。
表 2:自定义绘制返回标志
自定义绘制返回标志 含义 CDRF_DEFAULT 指示控件自行绘制。该值为默认值,不应该将它与其他值组合在一起。 CDRF_SKIPDEFAULT 用于指定控件根本不进行任何绘制。 CDRF_NEWFONT 当代码更改绘制项/子项的字体时使用。 CDRF_NOTIFYPOSTPAINT 使通知信息在控件或每个项/子项绘制后发送。 CDRF_NOTIFYITEMDRAW 指出项(或子项)将进行绘制。注意,它下面的值与 CDRF_NOTIFYSUBITEMDRAW 相同。 CDRF_NOTIFYSUBITEMDRAW 指出子项(或项)将进行绘制。注意,它下面的值与 CDRF_NOTIFYITEMDRAW 相同。 CDRF_NOTIFYPOSTERASE 当删除控件后需要通知代码时使用。
以下为一个示例,其中的代码指定,当绘制控件的项 (CDRF_NOTIFYITEMDRAW) 及子项 (CDRF_NOTIFYPOSTPAINT),以及绘制完成时,应该调用 NM_CUSTOMDRAW 处理程序。
void CListCtrlWithCustomDraw::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR);
...
*pResult = 0; // Initialize value
*pResult |= CDRF_NOTIFYITEMDRAW;
*pResult |= CDRF_NOTIFYSUBITEMDRAW;
*pResult |= CDRF_NOTIFYPOSTPAINT;
}
筛选指定的绘制阶段
一旦指定要关注的阶段后,您需要处理这些阶段。因为绘制过程的每个阶段只有一个消息要发送,惯例是执行一个 switch 语句以决定准确的绘制阶段。不同的绘制阶段由以下标志定义:
CDDS_PREPAINT
CDDS_ITEM
CDDS_ITEMPREPAINT
CDDS_ITEMPOSTPAINT
CDDS_ITEMPREERASE
CDDS_ITEMPOSTERASE
CDDS_SUBITEM
CDDS_POSTPAINT
CDDS_PREERASE
CDDS_POSTERASE
对于一个 CListCtrl 派生的类,有一个 NM_CUSTOMDRAW 处理程序的示例,其中您可以发现,代码决定当前绘制阶段的方式:
void CMyCustomDrawControl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR);
switch(pNMCD->dwDrawStage)
{
case CDDS_PREPAINT:
...
break;
case CDDS_ITEMPREPAINT:
...
break;
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
...
break;
...
}
*pResult = 0;
}
注意,为了决定子项(例如,列表视图控件)绘制的阶段,您必需使用按位 or 操作符,它有两个值:其中一个为 CDDS_ITEMPREPAINT 或者 CDDS_ITEMPOSTPAINT,另一个为 CDDS_SUBITEM。
要说明它,我们假定您想在绘制列表视图项之前进行一些处理。将编写 switch 语句来处理 CDDS_ITEMPREPAINT。
case CDDS_ITEMPREPAINT:
...
break;
然而,如果是您所关注子项的预绘制阶段,则将如下操作:
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
...
break;
上一页 [1] [2] [3] 下一页
Visual C++2005中开发自定义绘图控件 www.itspzo.com 作者:佚名 文章来源:msdn 点击数: 80 更新时间:2006-5-23
示例:创建一个列表视图控件自定义绘制控件
如前面提到的,您可以完全控制控件及其项的绘制,或者仅执行一小部分特定于应用程序的绘制,并让控件继续进行。本文的焦点更多地偏重于控件绘制技术而非高级的绘制技术,我们将演练一个简单的示例,其中列表视图控件是一个自定义的绘制,因此项的文本将在创建拼接外观的交替单元中显示为不同的颜色。
·创建一个基于 Visual C++ 2005 对话框的项目,名为 ListCtrlColor。
·从 Class View 中选择 Project 菜单选项,并单击 Add Class 调用 Add Class 对话框。
·从分类列表中选择 MFC,然后从模板列表中选择 MFC Class。
·单击 Add 按钮,调用 MFC Class Wizard 对话框。
·对于 Class name胫?CListCtrlWithCustomDraw 并选择 CListCtrl 的 Base class。
·单击 Finish 按钮,生成类的标头和执行文件。
·对于 Class View,右键单击 CListCtrlWithCustomDraw 类,并选择 Properties 上下文菜单选项。
·显示 Properties 窗口时,单击顶部的 Messages 按钮,显示一个两列的消息列表,您可以为其实现处理程序。
·在消息列表中单击 NM_CUSTOMDRAW 项,然后下拉第二列的组合框箭头,并选择值 OnNMCustomdraw。
·现在,处理绘制代码。这里,我们只简单处理项和子项预绘制阶段,指定基于当前行(项)和列(子项)的文本和背景色。要进行此操作,按如下所示修改 OnNMCustomdraw 函数:
void CListCtrlWithCustomDraw::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLVCUSTOMDRAW lpLVCustomDraw = reinterpret_cast(pNMHDR);
switch(lpLVCustomDraw->nmcd.dwDrawStage)
{
case CDDS_ITEMPREPAINT:
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
if (0 == ((lpLVCustomDraw->nmcd.dwItemSpec + lpLVCustomDraw->iSubItem) % 2))
{
lpLVCustomDraw->clrText = RGB(255,255,255); // white text
lpLVCustomDraw->clrTextBk = RGB(0,0,0); // black background
}
else
{
lpLVCustomDraw->clrText = CLR_DEFAULT;
lpLVCustomDraw->clrTextBk = CLR_DEFAULT;
}
break;
default: break;
}
*pResult = 0;
*pResult |= CDRF_NOTIFYPOSTPAINT;
*pResult |= CDRF_NOTIFYITEMDRAW;
*pResult |= CDRF_NOTIFYSUBITEMDRAW;
}
现在,我们来测试新控件。要进行此操作,您只需使用 CListCtrlWithCustomDraw 类将列表视图控件放在对话框中,并对其进行子类派生。下面是完成该操作的步骤。
·在 Resource 视图中,打开应用程序的主对话框 (IDD_LISTCTRLCOLOR_DIALOG)。
·从 Toolbox 中,将一个 List Control 拖放到该对话框。
·右键单击列表控件,并选择 Properties 上下文菜单选项。
·将 View 属性设置为 Report。
·右键单击控件,并选择 Add Variable 上下文菜单选项。
·出现 Add Member Variable Wizard 对话框时,指定 m_lstBooks 的 Variable name,并单击 Finish 按钮。
·这时,您就有了一个 CListCtrl 派生类 (m_lstBooks),它将对话框上的列表视图控件进行子类派生。然而,m_lstBooks 需要从最新创建的 CListCtrlWithCustomDraw 派生,以便于调用您的绘制代码。因此,打开对话框的标题文件 (ListCtrlColorDlg.h),将 m_lstBooks 更改为 CListCtrlWithCustomDraw 类型。
·在 CListCtrlColorDlg 类开始之前,添加以下指令。
#include "ListCtrlWithCustomDraw.h"
·将下面的代码添加到对话框的 OnInitDialog 成员函数,这样我们就能够看到一些列表视图行。
// Insert the columns
m_lstBooks.InsertColumn(0, _T("Author"));
m_lstBooks.InsertColumn(1, _T("Book"));
// Define the data
static struct
{
TCHAR m_szAuthor[50];
TCHAR m_szTitle[100];
} BOOK_INFO[] = {
_T("Tom Archer"), _T("Visual C++.NET Bible"),
_T("Tom Archer"), _T("Extending MFC with the .NET Framework"),
_T("Brian Johnson"), _T("XBox 360 For Dummies")
};
// Insert the data
int idx;
for (int i = 0; i < sizeof BOOK_INFO / sizeof BOOK_INFO[0]; i++)
{
idx = m_lstBooks.InsertItem(i, BOOK_INFO[i].m_szAuthor);
m_lstBooks.SetItemText(i, 1, BOOK_INFO[i].m_szTitle);
}
·现在,建立并运行应用程序。图 1 为应用程序外观的一个示例。
图 1. 自定义绘制示例应用程序
小结
当 Windows 首次作为“下一代”操作系统引入到应用程序开发之中时,它作为新图形用户界面的一个主要论据就是其一致性。该论据的要点所在是其具有一个通用的外观:统一的菜单项、通用控件等。这一通用性的感觉可能会一直延续,直到有第二家公司想设计其自己的应用程序。简单说,提供外观与其他应用程序雷同的应用程序,任何公司都不会逃离这一怪圈。
要建立一个唯一的且让人过目难忘的用户界面,其中一种方式是为应用程序设计并开发自定义的控件。希望本文能对您有所帮助,现在,您了解到一种非常强大的技术,它使您的应用程序能从众多竞争对手的应用程序中脱颖而出。
- Visual C++2005中开发自定义绘图控件2.3
- Visual C++2005中开发自定义绘图控件
- Visual C++2005中开发自定义绘图控件之一
- Visual C++2005中开发自定义绘图控件之二
- Visual C++2005中开发自定义绘图控件之三
- Visual C++2005中开发自定义绘图控件
- Visual C++2005中开发自定义绘图控件
- Visual Studio 2005:在 Visual C++ 中开发自定义的绘图控件
- Visual Studio 2005:在 Visual C++ 中开发自定义的绘图控件
- Visual Studio 2005:在 Visual C++ 中开发自定义的绘图控件
- 转自MSDN: Visual Studio 2005:在 Visual C++ 中开发自定义的绘图控件
- 在Visual C++ 中开发自定义的绘图控件
- 在 Visual C++ 中开发自定义的绘图控件
- 在 Visual C++ 中开发自定义的绘图控件 NM_CUSTOMDRAW
- 在 Visual C++ 中开发自定义的绘图控件(一)
- VC++2005中开发自定义绘图控件
- VC++2005中开发自定义绘图控件
- VC++2005中开发自定义绘图控件
- 一些小幽默
- Visual C++2005中开发自定义绘图控件
- 谁动了我的浏览器
- 拥抱自然
- 思维吊床
- Visual C++2005中开发自定义绘图控件2.3
- AIO SN + Crack Searching Options
- 开发!
- VC之美化界面篇
- 免费网络硬盘汇总
- 喘口气,记录一下
- 我喜欢的个人签名。
- 和她来到学校
- Writing your first Django app, part 2---IE的问题吗?费解