vs2017开发ActiveX(主讲OCX)(四)、绘制ActiveX控件


参考 MFC ActiveX Controls: Painting an ActiveX Control
本文介绍ActiveX控件绘制过程以及如何更改绘制代码以优化过程。(有关如何经过不使控件单独恢复之前选择的GDI对象来优化绘图的技术,请参阅优化控制图。在绘制完全部控件后,容器能够自动恢复原始对象。)
本文中的示例来自MFC ActiveX控件向导使用默认设置建立的控件。

绘制控件的整个过程以及ActiveX控件向导建立的代码以支持绘制

ActiveX控件的绘制过程

最初显示或重绘ActiveX控件时,它们遵循与使用MFC开发的其余应用程序相似的绘制过程,但有一个重要区别:ActiveX控件能够处于活动状态或非活动状态。web

ActiveX控件容器中的子窗口表示活动控件。与其余窗口同样,它在接收WM_PAINT消息时负责绘制自身。控件的基类COleControl在其OnPaint函数中处理此消息。此默认实现调用OnDraw控件的功能。设计模式

非活动控件的绘制方式不一样。当控件处于非活动状态时,其窗口要么不可见,要么不存在,所以没法接收绘制消息。相反,控件容器直接调用控件的OnDraw功能。这与活动控件的绘制过程不一样,由于OnPaint永远不会调用成员函数。app

如前面段落中所讨论的,ActiveX控件的更新方式取决于控件的状态。可是,由于框架OnDraw在两种状况下都调用成员函数,因此在此成员函数中添加大部分绘制代码。框架

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

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

注意 重要的是,您的修改OnDraw不依赖于矩形的左上角等于(0,0),而是仅在传递给矩形的内部绘制OnDraw。若是绘制超出矩形区域,则可能会出现意外结果。测试

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

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功能。spa

ActiveX控件绘制的默认实现绘制整个控件区域。这对于简单的控件来讲已经足够了,可是在许多状况下,若是仅从新绘制须要更新的部分而不是整个控件,则从新绘制控件会更快。

该OnDraw函数经过传递rcInvalid提供了一种简单的优化方法,rcInvalid是须要重绘的控件的矩形区域。使用此区域(一般小于整个控制区域)可加快绘制过程。

如何使用元文件绘制控件

在大多数状况下,函数的pdc参数OnDraw指向屏幕设备上下文(DC)。然而,当打印控件的图像时或在打印预览会话期间,接收用于渲染的DC是称为“元文件DC”的特殊类型。与当即处理发送给它的请求的屏幕DC不一样,元文件DC存储稍后要回放的请求。在设计模式下,某些容器应用程序还能够选择使用图元文件DC来呈现控制图像。

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

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

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

Arc BibBlt Chord
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 :: AnimatePalette,CFont :: CreateFontIndirect,以及三个成员函数CBrush:CreateBrushIndirect,CreateDIBPatternBrush和CreatePatternBrush。

未记录在图元文件中的函数有:DrawFocusRect,DrawIcon,DrawText,ExcludeUpdateRgn,FillRect,FrameRect,GrayString,InvertRect,ScrollDC和TabbedTextOut。因为元文件DC实际上并未与设备关联,所以不能将SetDIBits,GetDIBits和CreateDIBitmap与图元文件DC一块儿使用。您可使用SetDIBitsToDevice和StretchDIBits将元文件DC做为目标。CreateCompatibleDC,CreateCompatibleBitmap和CreateDiscardableBitmap 对于元文件DC没有意义。

使用图元文件DC时要考虑的另外一点是,坐标系可能没法以像素为单位进行测量。出于这个缘由,全部的绘图代码应该进行调整,以适应传递到矩形OnDraw的rcBounds参数。这能够防止在控件外部意外绘制,由于rcBounds表示控件窗口的大小。

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

使用Test Container测试控件的元文件
在“测试容器”的“ 编辑”菜单上,单击“ 插入新控件”。

在“ 插入新控件”框中,选择该控件,而后单击“ 肯定”。

该控件将出如今Test容器中。

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

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

相关文章
相关标签/搜索