vs2017開發ActiveX(主講OCX)(四)、繪制ActiveX控件



參考 MFC ActiveX Controls: Painting an ActiveX Control
本文介紹ActiveX控件繪制過程以及如何更改繪制代碼以優化過程。(有關如何通過不使控件單獨恢復以前選擇的GDI對象來優化繪圖的技術,請參閱優化控制圖。在繪制完所有控件后,容器可以自動恢復原始對象。)
本文中的示例來自MFC ActiveX控件向導使用默認設置創建的控件。

繪制控件的整個過程以及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。如果繪制超出矩形區域,則可能會出現意外結果。

控件實現文件(.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功能。

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容器中。

在“ 控制”菜單上,單擊“ 繪制圖元文件”。

將出現一個單獨的窗口,其中顯示元文件。您可以更改此窗口的大小以查看縮放如何影響控件的圖元文件。您可以隨時關閉此窗口。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM