用ATL和MFC来创建ActiveX控件
2010-07-25 20:46:35 来源:WEB开发网控件翻译
MFC和ATL在翻译处理上是相似的。在每一个框架里,实现控件的类具有一个名为OnDraw的虚函数。你只需将你的翻译代码添加到OnDraw函数里。然而,在各框架里,OnDraw函数得工作有所不同。
MFC的OnDraw在两种上下文下调用。第一个上下文发生在控件响应一个WM_PAINT消息时。此时,传递给OnDraw函数的设备上下文代表了真实的设备上下文。如果控件正被要求render它自己作为对客户调用IViewObjectEx::Draw的响应,设备上下文或者是一个元设备上下文,或者是一个常规设备上下文。下面的代码说明了基于MFC的控件是怎样被render的:
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的签名包括一个代表控件大小的矩形和一个代表控件非法区域的矩形。MFC调用控件的OnDraw函数来响应一个WM_PAINT消息。此时,OnDraw函数接受一个真实的设备上下文来绘图。MFC还调用控件的OnDraw函数来响应IViewObject::Draw中的一个调用。MFC的实现调用COleControl::OnDrawMetafile,它的缺省OnDrawMetafile调用COleControl::OnDraw。当然,这暗示了控件的实时翻译是与控件的元文件表示相同的,该元文件在设计时与包容器一块存储。你可以使得控件的实时的翻译与设计时的翻译不同,这通过重载COleControl::OnDrawMetafile来实现。通过调用你的控件的InvalidateControl方法,你可以强制进行一个重绘。ATL的翻译机制非常类似于MFC。CComControlBase::OnPaint建立一个ATL_DRAWINFO结构,包括创建一个绘图设备上下文。然后ATL调用控件的OnDrawAdvanced函数。OnDrawAdvanced生成元文件,接着调用你的控件的OnDraw方法,它使用ATL_DRAWINFO结构中的信息来知道怎样在屏幕上绘图。下面是ATL_DRAWINFO结构:
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的消息流控件是怎样处理绘图的:
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函数来强制控件的一次重画。
更多精彩
赞助商链接