CDC,CClientDC,CPaintDC,CWindowDC 比較區別

CDC,CClientDC,CPaintDC,CWindowDC 比較區別windows

MFC中的CDC,CClientDC,CPaintDC,CWindowDC的區別異步

CDCWindows繪圖設備的基類。函數

CClientDC
(1)
(客戶區設備上下文)用於客戶區的輸出,與特定窗口關聯,可讓開發者訪問目標窗口中客戶區,其構造函數中包含了GetDC,析構函數中包含了ReleaseDC優化

CPaintDC
(1)
用於響應窗口重繪消息(WM_PAINT)是的繪圖輸出。
(2)CPaintDC
在構造函數中調用BeginPaint()取得設備上下文,在析構函數中調用EndPaint()釋放設備上下文。 EndPaint()除了釋放設備上下文外,還負責從消息隊列中清除WM_PAINT消息。所以,在處理窗口重畫時,必須使用CPaintDC,不然 WM_PAINT消息沒法從消息隊列中清除,將引發不斷的窗口重畫。
(3)CPaintDC
也只能用在WM_PAINT消息處理之中。this

CWindowDC
(1)
可在非客戶區繪製圖形,而CClientDCCPaintDC只能在客戶區繪製圖形。
(2)
座標原點是在屏幕的左上角,CClientDCCPaintDC下座標原點是在客戶區的左上角。
(3)
關聯一特定窗口,容許開發者在目標窗口的任何一部分進行繪圖,包含邊界與標題,這種DCWM_NCPAINT消息一塊兒發送。spa

===========code

CPaintDC用於響應窗口重繪消息(WM_PAINT)是的繪圖輸出。CPaintDC在構造函數中調用BeginPaint()取得設備上下文,在析構函數中調用EndPaint()釋放設備上下文。EndPaint()除了釋放設備上下文外,還負責從消息隊列中清除 WM_PAINT消息。所以,在處理窗口重畫時,必須使用CPaintDC,不然WM_PAINT消息沒法從消息隊列中清除,將引發不斷的窗口重畫。 CPaintDC也只能用在WM_PAINT消息處理之中。對象

系統什麼時候發送WM_PAINT消息?隊列

系統會在多個不一樣的時機發送WM_PAINT消息:當第一次建立一個窗口時,當改變窗口的大小時,當把窗口從另外一個窗口背後移出時,當最大化或最小 化窗口時,等等,這些動做都是由系統管理的,應用只是被動地接收該消息,在消息處理函數中進行繪製操做;大多數的時候應用也須要可以主動引起窗口中的繪製 操做,好比當窗口顯示的數據改變的時候,這通常是經過InvalidateRectInvalidateRgn函數來完成的。 InvalidateRectInvalidateRgn把指定的區域加到窗口的Update Region中,當應用的消息隊列沒有其餘消息時,若是窗口的Update Region不爲空時,系統就會自動產生WM_PAINT消息。ci

系統爲何不在調用Invalidate時發送WM_PAINT消息呢?又爲何非要等應用消息隊列爲空時才發送WM_PAINT消息 呢?這是由於系統把在窗口中的繪製操做看成一種低優先級的操做,因而儘量地推後作。不過這樣也有利於提升繪製的效率:兩個WM_PAINT消息之間經過 InvalidateRectInvaliateRgn使之失效的區域就會被累加起來,而後在一個WM_PAINT消息中一次獲得更新,不只能避免屢次 重複地更新同一區域,也優化了應用的更新操做。像這種經過InvalidateRectInvalidateRgn來使窗口區域無效,依賴於系統在合適 的時機發送WM_PAINT消息的機制其實是一種異步工做方式,也就是說,在無效化窗口區域和發送WM_PAINT消息之間是有延遲的;有時候這種延遲 並非咱們但願的,這時咱們固然能夠在無效化窗口區域後利用SendMessage 發送一條WM_PAINT消息來強制當即重畫,但不如使用Windows GDI爲咱們提供的更方便和強大的函數:UpdateWindowRedrawWindowUpdateWindow會檢查窗口的Update Region,當其不爲空時才發送WM_PAINT消息;RedrawWindow則給咱們更多的控制:是否重畫非客戶區和背景,是否老是發送 WM_PAINT消息而無論Update Region是否爲空等。

說明:在繪圖時推薦使用CClientDC,CPaintDCCWindowDC對象,而不推薦直接使用CDC對象。

創建項目,採用單文檔結構

HDC:

首先在CYourClassView類中add windows message handler, 一個是LButtonDown, 另外一個是LButtonUp.添加成員變量:m_ptOrigin用來記錄初始點位置。

view結構體中初始化m_ptOrigin變量:

CYourClassView:: CYourClassView ()

{

       // TODO: add construction code here

       m_ptOrigin=0;

}

LButtonDown函數裏面添加代碼:

void CYourClassView::OnLButtonDown(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       m_ptOrigin=point;

       CView::OnLButtonDown(nFlags, point);

}

LButtonUp中添加代碼,首先使用HDC:

void CYourClassView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       HDC hdc;

       hdc=::GetWindowDC(m_hWnd);

       MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);

       LineTo(hdc,point.x,point.y);

       ::ReleaseDC(m_hWnd,hdc);


CView::OnLButtonUp(nFlags, point);

}

使用CDC:

void CYourClassView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       CDC *pdc=GetDC();

       pdc->MoveTo(m_ptOrigin);

       pdc->LineTo(point);

       ReleaseDC(pdc);


CView::OnLButtonUp(nFlags, point);

}

使用CClientDC:

void CYourClassView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       CClientDC dc(this);

       dc.MoveTo(m_ptOrigin);

       dc.LineTo(point);


CView::OnLButtonUp(nFlags, point);

}

使用CWindowDC:

void CYourClassView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       CWindowDC dc(this);

       dc.MoveTo(m_ptOrigin);

       dc.LineTo(point);

CView::OnLButtonUp(nFlags, point);

相關文章
相關標籤/搜索