圖形裝置介面(GDI)是一個可執行程式,它接受Windows應用程式的繪圖請求(表現為GDI函數調用),並將它們傳給相應的裝置驅動程式,完成特定於硬體的輸出,象印表機輸出和螢幕輸出。GDI負責Windows的所有圖形輸出,包括螢幕上輸出像素、在印表機上輸出硬拷貝以及繪製Windows使用者介面。
應用程式可以使用GDI建立三種類型的圖形輸出:向量輸出、點陣圖形輸出和文本輸出。
向量圖形輸出
向量圖形輸出指的是建立線條和填充圖形,包括點、直線、曲線、多邊形、扇形和矩形的繪製。
光柵輸出
點陣圖形的輸出是指點陣圖形函數對以位元影像形式儲存的資料進行操作,它包括各種位元影像和表徵圖的輸出。在螢幕上表現為對若干行和列的像素的操作,在印表機上則是若干行和列的點陣的輸出。
點陣圖形輸出的優點是速度很快,它是直接從記憶體到顯存的拷貝操作。缺點是需要額外的記憶體空間。Windows在繪製介面時使用了大量的光柵輸出。
文本輸出
與DOS字元方式下的輸出不同,Windows是按圖形方式輸出的。這樣,在輸出文本時,必須以邏輯座標為單位計算文本的輸出位置,而不是象DOS下以文本行為單位輸出文本。這比DOS下的文本輸出要難一些。
MFC中與GDI有關的類
為了支援GDI繪圖,MFC提供了兩種重要的類:裝置上下文類,用於設定繪圖屬性和繪製圖形;繪圖對象類,封裝了各種GDI繪圖對象,包括畫筆、刷子、字型、位元影像、調色盤和地區。
裝置上下文類
裝置上下文類包括CDC和它的衍生類別CClientDC、CPaintDC、CWindowDC、CmeteFileDC。
CDC是裝置上下文類的基類,除了一般的視窗顯示外,還用於基於案頭的全螢幕繪製和非螢幕顯示的印表機輸出。CDC類封裝了所有圖形輸出函數,包括向量、光柵和文本輸出。
CPaintDC用於響應視窗重繪訊息(WM_PAINT)是的繪圖輸出。CPaintDC在建構函式中調用BeginPaint()取得裝置上下文,在解構函式中調用EndPaint()釋放裝置上下文。EndPaint()除了釋放裝置上下文外,還負責從訊息佇列中清除WM_PAINT訊息。因此,在處理視窗重畫時,必須使用CPaintDC,否則WM_PAINT訊息無法從訊息佇列中清除,將引起不斷的視窗重畫。CPaintDC也只能用在WM_PAINT訊息處理之中。
CWindowDC用於視窗客戶區和非客戶區(包括視窗邊框、標題列、控制按鈕等)的繪製。除非要自己繪製視窗邊框和按鈕(如一些CD播放程式等),否則一般不用它。
CmeteFileDC專門用於圖元檔案的繪製。圖元檔案記錄一組GDI命令,可以通過這一組GDI命令重建圖形輸出。使用CmeteFileDC時,所有的圖形輸出命令會自動記錄到一個與CmeteFileDC相關的圖元檔案中。
繪圖物件類
繪圖物件類包括CGdiObject、畫筆、刷子、字型、位元影像、調色盤、地區等。CGdiObject是繪圖物件類的基類,但該類不能直接為應用程式所使用。要使用GDI對象,必須使用它的衍生類別:畫筆、刷子、字型、位元影像、地區等等。
使用繪圖物件要注意兩點:
1.同其他MFC對象一樣,GDI對象的建立也要分為兩步:第一步,是定義一個GDI繪圖對象類的執行個體;第二步調用該對象的建立方法真正建立對象。
2.建立對象:使用該對象,首先要調用CDC::SelectObject()將它選入到裝置上下文中,同時儲存原來的設定到一個GDI對象指標比如說pOldObject中。在使用完後,再用SelectObject(pOldObject)恢複原來的設定。但是,如果該裝置上下文是使用者自己建立的,則不必恢複原來設定,因為架構會在該裝置上下文生存期結束時刪除該裝置上下文,同時也就刪除了原來存放於該裝置上下文中的繪圖對象設定。
訪問當前即時檢視和使用中文件
對於SDI程式,主架構視窗就是文檔框窗,可以採用以下方法取得當前文檔和視圖:
取得使用中文件:
CMyDocument* pDoc;
pDoc=(CMyDocument*)((CFrameWnd*)AfxGetApp()->m_pMainWnd)
->GetActiveDocument();
或
pDoc=(CMyDocument*)((CFrameWnd*)AfxGetMainWnd());
這兩者是等效的。
取得即時檢視:
CMyView* pView;
pView=(CMyView*)((CFrameWnd*)AfxGetApp()->m_pMainWnd)->GetActiveView();
對於MDI程式,由於子視窗才是文檔框窗,因此首先要用GetActiveFrame()取得活動子架構視窗,然後通過該子視窗擷取使用中文件和視圖:
CMDIChildWnd* pChild=(CMDIChildWnd*)((CFrameWnd*)AfxGetApp()->m_pMainWnd)->GetActiveFrame();
取得使用中文件:
CMyDocument* pDoc=pChild->GetActiveDocument();
CMyView* pView=(CMyView*)pChild->GetActiveView();
可以把上述函數片段做成靜態成員函數,比如:
static CMyDocument::GetCurrentDoc()
{
CMDIChildWnd* pChild=(CMDIChildWnd*)((CFrameWnd*)AfxGetApp()- >m_pMainWnd)->GetActiveFrame();
CMyDocument* pDoc=pChild->GetActiveDocument();
}
這樣就可以通過以下方式取得使用中文件(或視圖):
CMyDocument::GetCurrentDoc();
註:靜態成員函數調用時不需要一個具體的對象與之相關聯。