MFC ActiveX 控件:绘制 ActiveX 控件

本文介绍 ActiveX 控件绘制过程,以及如何更改绘制代码以优化该过程。 (请参阅 优化控件绘图 ,了解如何通过不单独还原以前选择的 GDI 对象来优化绘图。绘制完所有控件后,容器可以自动还原原始对象。

重要

ActiveX 是一项不推荐用于新开发的旧技术。 有关取代 ActiveX 的新式技术的详细信息,请参阅 ActiveX 控件

本文中的示例来自具有默认设置的 MFC ActiveX 控件向导创建的控件。 有关使用 MFC ActiveX 控件向导创建主干控件应用程序的详细信息,请参阅 MFC ActiveX 控件向导一文。

下面介绍了以下主题:

ActiveX 控件的绘制过程

当 ActiveX 控件最初显示或重新绘制时,它们遵循类似于使用 MFC 开发的其他应用程序的绘制过程,这有一个重要区别:ActiveX 控件可以处于活动状态或非活动状态。

活动控件由子窗口在 ActiveX 控件容器中表示。 与其他窗口一样,它负责在收到WM_PAINT消息时自行绘制。 控件的基类 COleControl 在其函数中 OnPaint 处理此消息。 此默认实现调用 OnDraw 控件的函数。

非活动控件的绘制方式不同。 当控件处于非活动状态时,其窗口不可见或不存在,因此它无法接收画图消息。 相反,控件容器直接调用 OnDraw 控件的函数。 这不同于活动控件的绘制过程,即 OnPaint 从不调用成员函数。

如前一段所述,如何更新 ActiveX 控件取决于控件的状态。 但是,由于框架在这两种情况下都调用 OnDraw 成员函数,因此在此成员函数中添加大部分绘制代码。

OnDraw成员函数处理控件绘制。 当控件处于非活动状态时,控件容器将调用 OnDraw、传递控件容器的设备上下文以及控件占用的矩形区域的坐标。

框架 OnDraw 传递给成员函数的矩形包含控件占用的区域。 如果控件处于活动状态,左上角为 (0, 0),传递的设备上下文是包含该控件的子窗口。 如果控件处于非活动状态,则左上角坐标不一定为 (0, 0),传递的设备上下文适用于包含该控件的控件容器。

注释

请务必 OnDraw 修改不依赖于矩形的左上角点等于 (0, 0),并且仅在传递给 OnDraw的矩形内绘制。 如果绘制超出矩形区域,则可能会出现意外结果。

控件实现文件中 MFC ActiveX 控件向导提供的默认实现(。如下所示的 CPP 用白色画笔绘制矩形,并使用当前背景色填充椭圆。

void CMyAxUICtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& /*rcInvalid*/)
{
   if (!pdc)
      return;

   // TODO: Replace the following code with your own drawing code.
   pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
   pdc->Ellipse(rcBounds);
}

注释

绘制控件时,不应假设作为 pdc 参数 OnDraw 传递给函数的设备上下文的状态。 有时,设备上下文由容器应用程序提供,不一定初始化为默认状态。 具体而言,显式选择绘图代码所依赖的笔、画笔、颜色、字体和其他资源。

优化画图代码

成功绘制控件后,下一步是优化 OnDraw 函数。

ActiveX 控件绘制的默认实现绘制整个控制区域。 这足以用于简单控件,但在许多情况下,如果仅重新绘制了需要更新的部分,而不是整个控件,则重新绘制控件的速度会更快。

OnDraw 函数通过传递需要重绘的控件的 矩形区域 rcInvalid 来提供一种简单的优化方法。 使用此区域,通常小于整个控制区域,以加快绘制过程。

使用图元文件绘制控件

在大多数情况下,函数的 OnDrawpdc 参数指向屏幕设备上下文(DC)。 但是,当打印控件的图像或在打印预览会话期间,接收用于呈现的 DC 是一种称为“图元文件 DC”的特殊类型。 与立即处理发送到它的请求的屏幕 DC 不同,图元文件 DC 存储稍后要播放的请求。 某些容器应用程序还可以选择在设计模式下使用图元文件 DC 呈现控件图像。

容器可以通过两个接口函数发出图元文件绘图请求: IViewObject::Draw (此函数也可以为非图元文件绘图调用)和 IDataObject::GetData。 将图元文件 DC 作为参数之一传递时,MFC 框架调用 COleControl::OnDrawMetafile。 由于这是虚拟成员函数,因此在控件类中重写此函数以执行任何特殊处理。 默认行为调用 COleControl::OnDraw

为了确保可以在屏幕和图元文件设备上下文中绘制控件,你必须仅使用屏幕和图元文件 DC 中支持的成员函数。 请注意,坐标系可能不会以像素为单位测量。

由于调用控件函数的默认实现OnDrawMetafile,因此仅使用适用于图元文件和屏幕设备上下文的成员函数,除非重写OnDrawMetafileOnDraw 下面列出了可在图元文件和屏幕设备上下文中使用的成员函数的 CDC 子集。 有关这些函数的详细信息,请参阅 MFC 参考中的类 CDC

BibBlt 和弦
Ellipse Escape ExcludeClipRect
ExtTextOut FloodFill IntersectClipRect
LineTo MoveTo OffsetClipRgn
OffsetViewportOrg OffsetWindowOrg PatBlt
Pie Polygon Polyline
PolyPolygon RealizePalette RestoreDC
RoundRect SaveDC ScaleViewportExt
ScaleWindowExt SelectClipRgn SelectObject
SelectPalette SetBkColor SetBkMode
SetMapMode SetMapperFlags SetPixel
SetPolyFillMode SetROP2 SetStretchBltMode
SetTextColor SetTextJustification SetViewportExt
SetViewportOrg SetWindowExt SetWindowORg
StretchBlt TextOut

除了 CDC 成员函数,还有其他几个函数在图元文件 DC 中兼容。 其中包括 CPalette::AnimatePaletteCFont::CreateFontIndirect 和三个 CBrush成员函数: CreateBrushIndirectCreateDIBPatternBrushCreatePatternBrush

图元文件中未记录的函数包括:DrawFocusRectDrawIconDrawTextExcludeUpdateRgnFillRect、FrameRectGrayStringInvertRectScrollDCTabbedTextOut 由于图元文件 DC 实际上未与设备关联,因此不能将 SetDIBits、GetDIBits 和 CreateDIBitmap 与图元文件 DC 配合使用。 可以将 SetDIBitsToDevice 和 StretchDIBits 与图元文件 DC 用作目标。 CreateCompatibleDCCreateCompatibleBitmapCreateDiscardableBitmap 对图元文件 DC 没有意义。

使用图元文件 DC 时要考虑的另一点是,坐标系可能不以像素为单位测量。 出于此原因,应调整所有绘图代码以适应传递给 OnDrawrcBounds 参数的矩形。 这可以防止意外绘制控件外部,因为 rcBounds 表示控件窗口的大小。

为控件实现图元文件呈现后,请使用测试容器测试图元文件。 请参阅 使用测试容器测试属性和事件 了解有关如何访问测试容器的信息。

使用测试容器测试控件的图元文件

  1. 在“测试容器的 编辑 ”菜单上,单击“ 插入新控件”。

  2. “插入新控件 ”框中,选择该控件,然后单击“ 确定”。

    控件将显示在测试容器中。

  3. “控件 ”菜单上,单击“ 绘制图元文件”。

    此时会显示一个单独的窗口,其中显示图元文件。 可以更改此窗口的大小,以查看缩放如何影响控件的图元文件。 可以随时关闭此窗口。

另请参阅

MFC ActiveX 控件