最初顯示或重繪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容器中。
在「 控制」菜單上,單擊「 繪製圖元文件」。
將出現一個單獨的窗口,其中顯示元文件。您能夠更改此窗口的大小以查看縮放如何影響控件的圖元文件。您能夠隨時關閉此窗口。