Visual C++2005中开发自定义绘图控件

本文源代码下载:CustomDraw.exe。

  在您决定开发 Windows 提供的常规免费自定义控件范围之外的控件之后,您必需确定自己的控件将有多少独到之处 — 在功能和外观两方面。例如,我们假定您正在创建一个类似于计速表的控件。由于公共控件库 (ComCtrl32.dll) 中没有类似的控件,您完全需要自己进行以下操作:编写所有控件功能需要的代码,进行绘制,默认终端用户的交互,以及控件与其父窗口之间需要的任意消息处理。

  另一方面,还包括一些您只想调整公共控件功能的情况。例如,我们假定您想创建一个屏蔽编辑控件,它只允许接受指定的字符。如果使用 MFC,通常涉及从 MFC 提供的类派生一个类,该类封装了一个公共控件(在屏蔽编辑控件中,通常为 CEdit),重写必需的虚函数(或处理指定的消息),然后加入自定义的代码。

  本文讨论的重点介于两者之间 — 公共控件赋予您想要的大部分功能,但控件的外观并不是您想要的。例如,列表视图控件提供在许多视图风格中显示数据列表的方式 — 小图标、大图标、列表和详细列表(报告)。然而,如果您想要一个网格控件,那结果怎样呢?尽管公共控件库里没有特别包含网格,但是列表视图控件与它较为接近,它以行和列显示数据,并有一个相关的标头控件。因此,许多人以一个标准的列表视图控件为起点创建自己的网格控件,然后重写该控件及其子项的呈现方式或绘制方式。

  主宰绘图操作

  即使“只”进行绘制,您仍然有至少四种选项可用,它们都具有鲜明的优缺点:

  ·处理 WM_PAINT

  ·所有者绘制

  ·自定义绘制

  ·处理 WM_CTLCOLOR

  处理 WM_PAINT

  最极端的选择是执行一个 WM_PAINT 处理程序,并且自己完成所有的绘制。这意味着,您的代码将需要进行一些与呈现控件相关的琐事 — 创建适当的设备上下文(一个或多个),决定控件的大小和位置,绘制控件等。在绘制过程中,很少需要这种级别的控件。

  所有者绘制

  控制控件绘制的另一种方法是利用所有者绘制。事实上,您也许听开发人员提到过所有者绘制控件,因为它是用于开发自定义控件最普通的技术。该技术普遍使用的主要原因在于,Windows 可为您提供很多帮助。在呈现控件的那一刻,Windows 就已经创建并填写了设备上下文,决定了控件的大小和位置,并且向您传递信息以使您了解此刻绘制的需求。对于列表控件(例如,列表框和列表视图),Windows 将为列表中的每一项调用绘制代码,这意味着您只需绘制这些项,而无需考虑控件的其他方面。注意,所有者绘制可用于大多数控件。然而,它不能用于编辑控件;并且考虑到列表控件,它只能用于报表视图样式。

  自定义绘制

  对于绘制自己的控件而言,这可能是最少为人所知的技术。事实上,许多技术能力较高的开发人员也混淆了术语所有者绘制 (owner-draw) 和自定义绘制 (custom-draw)。关于自定义控件,首先需要了解,它仅针对于指定的公共控件:标头、列表视图、rebar、工具栏、工具提示、跟踪条和树视图。此外,尽管所有者绘制只允许绘制报告视图风格的列表视图控件,而自定义绘制则使您能够处理列表视图控件所有视图风格的绘制。使用自定义绘制的另一个明显优势是,您可以对希望绘制的内容进行严格挑选。实现方式是,在控件绘制的每个阶段由 Windows 向代码发送一个消息。这样,您可以决定在每个阶段是自己进行所有的绘制工作,增加默认的绘制,还是允许 Windows 为该阶段执行所有的绘制。(鉴于自定义绘制是本文的一个主题,因此您很快会看到它的工作方式。)

  处理 WM_CTLCOLOR

  这可能是帮助决定如何呈现控件最简单的方式。正如消息名所指,当要绘制一个控件,并且它能让您的代码决定要使用的画笔时,发送 WM_CTLCOLOR 消息。通常情况下,如果您只想更改控件的颜色,并且不提供除控件本身之外的更多功能,则使用该技术。此外,对于由 Internet Explorer 引入的公共控件(列表视图、树视图、rebar 等),不发送该消息,并且它只与标准控件(编辑、列表框等)协同使用。

  实现自定义绘制的三步曲

  既然您已经了解了绘制控件可用的各种选项(包括使用自定义绘制的好处),那么,让我们来看看实现一个自定义绘制控件需要的三个主要步骤。

  ·执行一个 NM_CUSTOMDRAW 消息处理程序。

  ·指定处理所需的绘制阶段。

  ·筛选特定的绘制阶段(在这些阶段中,您需要加入自己的特定于控件的绘制代码)。

  执行一个NM_CUSTOMDRAW 消息处理程序

  当需要绘制一个公共控件时,MFC 会将控件的自定义绘制通知消息(最初发送到控件的父窗口)以 NM_CUSTOMDRAW 消息的形式反馈给控件。以下是一个 NM_CUSTOMDRAW 处理程序的示例。

void CMyCustomDrawControl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
 LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR);
 ...
}

  正如您所见,NM_CUSTOMDRAW 处理程序将一个指针传递给 NMHDR 类型的结构。然而,该值不足以用于象 NMHDR 这样只包含三个成员(hwndFrom、idFrom 和 code)的结构。

  因此,您通常需要将该结构指针转换为信息量更大的结构 — LPNMCUSTOMDRAW。LPNMCUSTOMDRAW 指向 NMCUSTOMDRAW,它包含诸如 dwDrawStage、dwItemSpec 和 uItemState 这样的成员 — 它们是决定当前绘制阶段及确切绘制(例如,控件本身、或控件的一个项目或子项)所必需的。

  这里值得注意的是,还可以将 NMHDR 指针指向特定于正在绘制控件的类型的结构。表 1 显示控件的一个列表及其相关的自定义绘制结构类型名。

  表 1:控件及其相关的自定义绘制结构

控件 结构(在 commctrl.h 中定义)
Rebar、Trackbar、AuthTicket、My.Resources、My.Settings、My.User 和 My.WebServices。 NMCUSTOMDRAW
List-view NMLVCUSTOMDRAW
Toolbar NMTBCUSTOMDRAW
Tooltip NMTTCUSTOMDRAW
Tree-view NMTVCUSTOMDRAW
时间: 2024-10-28 21:10:51

Visual C++2005中开发自定义绘图控件的相关文章

在Android开发中使用自定义组合控件的例子_Android

一.定义一个XML布局文件setting_item_view.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height=

在Android开发中使用自定义组合控件的例子

一.定义一个XML布局文件 setting_item_view.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height

android开发-自定义日历控件实现事务操作

问题描述 自定义日历控件实现事务操作 android开发中,自定义控件的实现步骤,项目中实现日历控件如何标识事务 解决方案 我的博客中有这么一个实例,http://blog.csdn.net/mr_dsw/article/details/48755993就是通过自定义控件进行日历控件的实现,应该能满足你的要求.自定义控件实现的步骤无非就是onMeasure.onLayout.onDraw

ASP.NET中使用自定义验证控件

asp.net|控件 asp.net 1.1中,有不少验证控件,大大方便了我们,但有的时候,当需要做特殊的验证时,还会觉得不够用的,于是我们可以用自定义验证控件CustomValidator,要使用这个控件,必须在服务端写相应的事件,格式如下: Sub FunctionName(sender as Object, args as ServerValidateEventArgs) ...End Sub其中注意两个参数 value:指示当前的CustomValidator验证的是哪一个控件 IsVa

Android中View自定义组合控件的基本编写方法_Android

有很多情况下,我们只要运用好Android给我提供好的控件,经过布局巧妙的结合在一起,就是一个新的控件,我称之为"自定义组合控件". 那么,这种自定义组合控件在什么情况下用呢?或者大家在做项目时候会发现,某些布局会被重复的利用,同一个布局的XML代码块会被重复的复制黏贴多次,这样会造成代码结构混乱不说,代码量也会增大,各种控件都需要在Java代码中被申明和处理相应的逻辑,工作量着实不小,所以,必须要找到一个合理的"偷懒"的方式,开动脑经去怎么简化以上说的不必要的麻烦

IOS开发自定义CheckBox控件

IOS本身没有系统的CheckBox组件,但是实际开发中会经常用到,所以专门写了一个CheckBox控件,直接上代码 效果图: UICheckBoxButton.h文件如下: #import #import "Common.h" @interface UICheckBoxButton : UIControl { UILabel *label; UIImageView *icon; BOOL checked; id delegate; } @property (retain, nonat

VB.NET中开发多媒体的控件,都有那些啊?

问题描述 标准的是那个控件啊 解决方案 解决方案二:WindowMedialPlayer解决方案三:怎么在工具栏里找不到啊!名称是什么啊?

在 Visual C++ 中开发自定义的绘图控件

本文讨论的重点介于两者 之间 - 公共控件赋予您想要的大部分功能,但控件的外观并不是您想要的.例如,列表视图控件提供在许多视图风格中显示数据列表的方式 - 小图标.大图标.列表和详细列表(报告).然而,如果您想要一个网格控件,那结果怎样呢?尽管公共控件库里没有特别包含网格,但是列表视图控件与它较为接 近,它以行和列显示数据,并有一个相关的标头控件.因此,许多人以一个标准的列表视图控件为起点创建自己的网格控件,然后重写该控件及其子项的呈现方式或 绘制方式.  主宰绘图操作即使"只"进行绘

Android开发中自定义ProgressBar控件的方法示例

本文实例讲述了Android开发中自定义ProgressBar控件的方法.分享给大家供大家参考,具体如下: 很简单,首先加载Drawable,在onMeasure设置好其区域大小, 然后使用canvas.clipRect绘图 public class ProgressView extends ImageView { private Drawable maskDraw; /** * 加载的进度 0-100 */ private int mProcess = 20; public ProgressV