MFC中的DC,CDC和HDC
設備描述表(DC)是Windows中的一種數據結構,它包含GDI需要的所有關于顯示界面情況的描述字段,包括相連的物理設備和各種各樣的狀態信息。
??????? 圖形顯示功能是由顯卡來完成的,你想要利用顯卡的圖形顯示功能來完成你的圖形輸出,怎么辦,給你一塊硬件能用嗎?好,現在廠商給你提供一個驅動程序,給你一些調用的接口,你就可以訪問了吧。但這種訪問是在驅動層,很麻煩,更麻煩的是,每個廠商給自己顯卡提供的驅動程序還不一樣,那我們寫的圖形輸出程序豈不是換臺機器(不一樣的顯卡)就得修改,一個字:累,兩個字:麻煩?,F在一個救世主出現了,Bill兄,他讓他的兄弟們在驅動之上實現一個抽象層,當然也可以認為是一個中間層的軟件代碼(我們管他叫設備上下文如何,也叫設備描述表DC),由這些代碼和驅動打交道(當然,這些驅動得支持Windows平臺)。然后,他將這種實現封裝到動態鏈接庫中提供給我們使用,我們能通過動態鏈接庫暴露的API函數(相關概念見VC下半部分),得到一個這種實現(可以說是一種資源)的句柄,設備上下文的句柄(HDC),利用的這個句柄,就好像有了訪問這中實現的鑰匙了,以后就可以.......,剩下的參照VC上半部分的內容。
?????? 設備描述表DC是一個定義一組圖形對象及其屬性、影響輸出的數據結構。windows提供設備描述表,用于應用程序和物理設備之間進行交互,從而提供了應用程序設計的平臺無關性。設備描述表又稱為設備上下文,或者設備環境。?
設備描述表是一種數據結構,它包括了一個設備(如顯示器和打印機)的繪制屬性相關的信息。所有的繪制操作通過設備描述表進行。設備描述表與大多WIN32結構不同,應用程序不能直接訪問設備描述表,只能由各種相關API函數通過設備描述表的句柄(HDC)間接訪問該結構。?
設備描述表總是與某種系統硬件設備相關。比如屏幕設備描述表與顯示設備相關,打印機設備描述表與打印設備相關等等。?
屏幕設備描述表,一般我們簡單地稱其為設備描述表。它與顯示設備具有一定的對應關系,在windows GDI界面下,它總是相關于某個窗口或這窗口上的某個顯示區域。通常意義上窗口的設備描述表,一般指的是窗口的客戶區,不包括標題欄、菜單欄所占有的區域,而對于整個窗口來說,其設備描述表嚴格意義上來講應該稱為窗口設備描述表,它包含窗口的全部顯示區域。二者的操作方法完全一致,所不同的僅僅是可操作的范圍不同而已。?
windows?窗口一旦創建,它就自動地產生了與之相對應的設備描述表數據結構,用戶可運用該結構,實現對窗口顯示區域的GDI操作,如劃線、寫文本、繪制位圖、填充等,并且所有這些操作均要通過設備描述表句柄了進行。?
要說設備描述表就必須先說GDI(圖形設備接口)。我們要在程序窗口上顯示圖形或文本等,就可以使用這些GDI函數在程序上“畫畫”、“寫字”。設備描述表(DC)實際上是GDI內部保存的數據結構。設備描述表中的有些值是圖形化的“屬性”,這些屬性定義了一些GDI函數工作的情況,如:文本顏色、圖形填充的情況等。HDC是設備描述表句柄類型,句柄可以簡單的理解為指針,被定義為32位的無符號整數。??
?????????????以上內容轉自:http://longzxr.blog.sohu.com/187934817.html
???????? DC(設備描述表):Windows應用程序通過為指定設備(屏幕,打印機等)創建一個設備描述表(Device Context, DC)在DC表示的邏輯意義的“畫布”上進行圖形的繪制。DC是一種包含設備信息的數據結構,它包含了物理設備所需的各種狀態信息。Win32程序在繪制圖形之前需要獲取DC的句柄HDC,并在不繼續使用時釋放掉。
????????在c++?編程中常會見到HDC,CDC,CClientDC,CPaintDC,CWindowDC這樣的類。
????????HDC是DC的句柄,API中的一個類似指針的數據類型。
??????? CDC是MFC的DC的一個類。
??????? CDC等設備上下分類,都含有一個類的成員變量:m_nHdc;即HDC類型的句柄。
????? CDC及其派生類的繼承視圖:
??????CObject
????? public |------CDC
????? public |------|------CClientDC
??????public |------|------CPaintDC
????? public |------|------CWindowDC
????? public |------|------CMetaFileDC
????? (注意:?除CMetaFileDC以外的三個派生類用于圖形繪制.)
??????? CDC類定義了一個設備描述表相關的類,其對象提供成員函數操作設備描述表進行工作,如顯示器,打印機,以及顯示器描述
表相關的窗口客戶區域。
??????? 通過CDC的成員函數可進行一切繪圖操作。CDC提供成員函數進行設備描述表的基本操作,使用繪圖工具,選擇類型安全的圖形設備結構(GDI),以及色彩,調色板。除此之外還提供成員函數獲取和設置繪圖屬性,映射,控制視口,窗體范圍,轉換坐標,區域操作,裁減,劃線以及繪制簡單圖形(橢圓,多邊形等)。成員函數也提供繪制文本,設置字體,打印機換碼,滾動,處理元文件。
其派生類:
???????? 1.CPaintDC:封裝BeginPaint和EndPaint兩個API的調用。
(1)用于響應窗口重繪消息(WM_PAINT)的繪圖輸出。
(2)CPaintDC在構造函數中調用BeginPaint()取得設備上下文,在析構函數中調用EndPaint()釋放設備上下文。 EndPaint()除了釋放設備上下文外,還負責從消息隊列中清除WM_PAINT消息。因此,在處理窗口重畫時,必須使用CPaintDC,否則 WM_PAINT消息無法從消息隊列中清除,將引起不斷的窗口重畫。
(3)CPaintDC也只能用在WM_PAINT消息處理之中。
???????? 2.CClientDC(客戶區設備上下文): 處理顯示器描述表的相關的窗體客戶區域。
?????構造時自動調用GetDC函數,析構時自動調用ReleaseDC函數.一般應用于客戶區窗口的繪制。
?????當需要處理一個鼠標的單擊,然后馬上畫出一個圓,你不能等到下一個WM_PAINT的消息到來才畫圖,而是馬上,這是就需要CclientDC了。它可以在OnPaint的外面創建一個客戶區域DC
????void?CMainWindow::OnLButtonDown?(UINT?nFlags,?CPoint?point)
????{
????????CRect?rect;
????????GetClientRect?(&rect);
????????CClientDC?dc?(this);
????????dc.MoveTo?(rect.left,?rect.top);
????????dc.LineTo?(rect.right,?rect.bottom);
????????dc.MoveTo?(rect.right,?rect.top);
????????dc.LineTo?(rect.left,?rect.bottom);
????}
???????? 3.CWindowDC: 處理顯示器描述表相關的整個窗體區域,包括了框架和控 件(子窗體)。
(1)可在非客戶區繪制圖形,而CClientDC,CPaintDC只能在客戶區繪制圖形。
(2)坐標原點是在屏幕的左上角,CClientDC,CPaintDC下坐標原點是在客戶區的左上角。
(3)關聯一特定窗口,允許開發者在目標窗口的任何一部分進行繪圖,包含邊界與標題,這種DC同WM_NCPAINT消息一起發送。
????? 4.CMetaFileDC:與元文件相關的設備描述表關聯。
?
下面說下一些細點的知識點
1、CClientDC,CWindowDC?區別不大, 可以說 CWindowDC包含了CClientDC。 就拿記事本來說,CClientDC 就只是我們可以編輯文字的那個區域,是客戶區,CWindowDC 除了上面說的區域, 還包括菜單欄和工具欄等。
2、CClientDC和CWindowDC與 CPaintDC 的區別大點,在DC的獲取方面 CClientDC和CWindowDC 使用的是并只能是GetDC 和 ReleaseDC。CPaintDC 使用的是并只能是 BeginPaint 和 EndPaint。
3、CPaintDC只能用在響應 WM_PAINT?事件CClientDC,CWindowDC 只能用在響應非WM_PAINT 事件
4、關于 WM_PAINT事件
???????? 系統會在多個不同的時機發送WM_PAINT消息:當第一次創建一個窗口時,當改變窗口的大小時,當把窗口從另一個窗口背后移出時,當最大化或最小化窗口時,等等,這些動作都是由系統管理的,應用只是被動地接收該消息,在消息處理函數中進行繪制操作;大多數的時候應用也需要能夠主動引發窗口中的繪制操作,比如當窗口顯示的數據改變的時候,這一般是通過InvalidateRect和InvalidateRgn函數來完成的。InvalidateRect和 InvalidateRgn把指定的區域加到窗口的Update Region中,當應用的消息隊列沒有其他消息時,如果窗口的Update Region不為空時,系統就會自動產生WM_PAINT消息。
??????? 系統為什么不在調用Invalidate時發送WM_PAINT消息呢?又為什么非要等應用消息隊列為空時才發送WM_PAINT消息呢?這是因為系統把在窗口中的繪制操作當作一種低優先級的操作,于是盡可能地推后做。不過這樣也有利于提高繪制的效率:兩個WM_PAINT消息之間通過 InvalidateRect和InvaliateRgn使之失效的區域就會被累加起來,然后在一個WM_PAINT消息中一次得到更新,不僅能避免多次重復地更新同一區域,也優化了應用的更新操作。像這種通過InvalidateRect和InvalidateRgn來使窗口區域無效,依賴于系統在合適的時機發送WM_PAINT消息的機制實際上是一種異步工作方式,也就是說,在無效化窗口區域和發送WM_PAINT消息之間是有延遲的;有時候這種延遲并不是我們希望的,這時我們當然可以在無效化窗口區域后利用SendMessage 發送一條WM_PAINT消息來強制立即重畫,但不如使用Windows GDI為我們提供的更方便和強大的函數:UpdateWindow和RedrawWindow。UpdateWindow會檢查窗口的Update Region,當其不為空時才發送WM_PAINT消息;RedrawWindow則給我們更多的控制:是否重畫非客戶區和背景,是否總是發送 WM_PAINT消息而不管Update Region是否為空等。
5、HDC和CDC相互轉換:
(1)、HDC到CDC的轉換:
方法一: 此方法在設備結束時不會銷毀原來的資源(即:hDC,hBitmap)
CDC *pDC = CDC::FromHandle(hDC);
方法二:此方法在設備結束時會銷毀原來的資源(即:hDC,hBitmap)
CDC dc;
dc.Attach(hDC);
(2)、CDC到HDC的轉換:
?? CDC??dc;
???HDC??hDC;
???hDC?=?dc.GetSafeHdc();
6、首先:CDC 不可以釋放。 FromHandle 是通過 HDC 來創建了一個CDC 對象,以方便操作,釋放 DC 的操作應該針對于HDC 而非此CDC , 如果釋放了它?? pDC->ReleaseDC,就會造成隱患。?
????? HDC?? hDC?? =?? GetDC(hWnd);??
????? CDC?? *pDC?? =?? CDC::FromHandle(hDC);???
????? 這兩者是指向的一個DC對象,只能釋放一次,而這個釋放應該針對 hDC 而非 pDC。
??????然后:GetDC和ReleaseDC的調用匹配,CreateDC和DeleteDC的調用匹配。GetDC是從窗口獲取現有的DC,而CreateDC是創建DC,所以ReleaseDC和DeleteDC的作用一個是釋放,一個是銷毀。
總結
以上是生活随笔為你收集整理的MFC中的DC,CDC和HDC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用TimeQuest时序分析器
- 下一篇: VS2010代码提示功能配置:Visua