用ATL和MFC来创建ActiveX控件应该使用哪个框架

 我来答
Mexico卡卡
2017-09-11 · TA获得超过1万个赞
知道大有可为答主
回答量:1.3万
采纳率:98%
帮助的人:1884万
展开全部

为控件添加功能代码

MFC和ATL在功能代码的处理上是相似的。在每一个框架里,实现控件的类具有一个名为OnDraw的虚函数。你只需将你的功能代码添加到OnDraw函数里。然而,在各框架里,OnDraw函数得工作有所不同。

MFC的OnDraw在两种上下文中调用。第一个上下文发生在控件响应一个WM_PAINT消息时。此时,传递给OnDraw函数的设备上下文是实际的设备上下文。如果控件正被要求绘制它自己作为对客户调用IViewObjectEx::Draw的响应,则设备上下文或者是一个元文件设备上下文,或者是一个常规设备上下文。下面的代码说明了基于MFC的控件是怎样被绘制的:

void CMFCMsgTrafficCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, 

const CRect& rcInvalid)

{

// TODO: 在下面加入自己的绘图代码

pdc->FillRect(rcBounds, 

CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));

ShowGraph(*pdc, const_cast<CRect&>(rcBounds), nMessagesToShow);

}

COleControl::OnDraw的签名包括一个代表控件大小的矩形和一个代表控件无效区域的矩形。当响应WM_PAINT消息时,MFC调用控件的OnDraw函数。此时,OnDraw函数接受一个实际的设备上下文来绘图。当通过IViewObject::Draw来响应一个调用时,MFC也要调用控件的OnDraw函数。MFC的实现调用COleControl::OnDrawMetafile,并且它的缺省OnDrawMetafile调用COleControl::OnDraw。当然,这暗示了控件的实时绘制是和设计时与容器一起存储的控件图元文件表示法相同。你可以让控件的实时绘制模样与设计时的绘制模样不同,这通过重载COleControl::OnDrawMetafile来实现。通过调用你的控件的InvalidateControl方法,你可以强制进行一次重绘。

ATL的绘制机制非常类似于MFC。CComControlBase::OnPaint建立一个ATL_DRAWINFO结构,包括创建一个绘图设备上下文。然后ATL调用控件的OnDrawAdvanced函数。OnDrawAdvanced生成元文件,接着调用自己控件的OnDraw方法,它使用ATL_DRAWINFO结构中的信息来了解如何在屏幕上绘图。下面是ATL_DRAWINFO结构:

[cpp] view plain copy 
struct ATL_DRAWINFO  
{  
    UINT cbSize;  
    DWORD dwDrawAspect;  
    LONG lindex;  
    DVTARGETDEVICE* ptd;  
    HDC hicTargetDev;  
    HDC hdcDraw;  
    LPCRECTL prcBounds;  //在这个矩形中绘图  
    LPCRECTL prcWBounds; //WindowOrg and Ext if metafile  
    BOOL bOptimize;  
    BOOL bZoomed;  
    BOOL bRectInHimetric;  
    SIZEL ZoomNum;       //ZoomX = ZoomNum.cx/ZoomNum.cy  
    SIZEL ZoomDen;  
};

ATL为你填写此结构。当你正在屏幕上绘图时,你所感兴趣的最重要的域是hdcDraw 和 prcBounds。如果你对在一个元文件里绘图感兴趣,或者你需要注意缩放因子等等,那么其它域也是重要的。下面的代码显示了基于ATL的消息流控件是怎样处理绘图的:

[cpp] view plain copy 
HRESULT CATLMsgTrafficCtl::OnDraw(ATL_DRAWINFO& di)  
{  
   RECT& rc = *(RECT*)di.prcBounds;  
   HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));  
   FillRect(di.hdcDraw, &rc, hBrush);  
   DeleteObject(hBrush);  
   Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);  
   ShowGraph(di.hdcDraw, rc, nMessagesToShow);  
   return S_OK;  
}

注意当你使用ATL的时候,设备和GDI句柄你都必须处理。在ATL中,你调用控件的FireViewChange函数来强制控件的一次重画。

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式