CPaintDC類與 CClientDC類的區別

CPaintDC 與 CClientDC

  CPaintDC 與 CClientDC都是從CDC類繼承而來。所以,這兩個類的外在行爲高度的抽象一致。以致於初者會誤以爲兩者的使用可以替換(或者說MFC初學者很容易將兩者的使用混淆)。事實上,MFC將兩者都從CDC繼承,是爲了讓用戶在不同的場景下更加方便,高效的使用DC。如果不理解兩者內部運作原理,混淆使用,就會出現屏幕繪製不能達到客戶調用結果要求,屏幕刷新效率下降等一系列問題。

  兩者有以下區別:
1.構造函數和析構函數內部調用的區別。

CPaintDC類:
CPaintDC::CPaintDC(CWnd* pWnd)
{
ASSERT_VALID(pWnd);
ASSERT(::IsWindow(pWnd->m_hWnd));
if (!Attach(::BeginPaint(m_hWnd = pWnd->m_hWnd, &m_ps)))
AfxThrowResourceException();
}


CPaintDC::~CPaintDC()
{
ASSERT(m_hDC != NULL);
ASSERT(::IsWindow(m_hWnd));
::EndPaint(m_hWnd, &m_ps);
Detach();
}
        CPaintDC類的構造函數和析構函數分別調用CWnd::BeginPaint()和CWnd::EndPaint()函數,則這兩個函數是爲了響應WM_PAINT消息的,它們是成對使用的。這就決定了CPaintDC類應該只能在CWnd派生窗口類中的WM_PAINT消息處理函數OnPaint()函數中使用。
  由於CWnd::EndPaint()函數除了釋放DC外,還額外的負責從消息隊列中刪除當前WM_PAINT消息,所以,如果在OnPaint()函數中錯誤的使用CClientDC類重繪,將會引起不斷的窗口重繪。


CClientDC類:
CClientDC::CClientDC(CWnd* pWnd)
{
ASSERT(pWnd == NULL || ::IsWindow(pWnd->m_hWnd));
if (!Attach(::GetDC(m_hWnd = pWnd->GetSafeHwnd())))
AfxThrowResourceException();
}


CClientDC::~CClientDC()
{
ASSERT(m_hDC != NULL);
::ReleaseDC(m_hWnd, Detach());
}
  CClientDC類的構造函數和析構函數分別調用CWnd::GetDC()和CWnd::ReleaseDC()函數,它只能在窗口的客戶區中使用(客戶區:窗口中除了邊框、標題欄、菜單欄以及狀態欄外的中間部分)。它是響應窗口中除WM_PAINT消息之外的重繪消息(如鍵盤輸入時繪製文本、鼠標移動時繪圖)時使用。
  
  查看過CPaintDC 類和 CClientDC類的構造函數和析構函數以後,你就會知道,在使用上述兩個DC類的時候,應該是在函數中將其申明爲函數的局部變量使用,以便在使用完畢後,由系統自動調用析構函數完成相關函數(EndPaint()和ReleaseDC()函數)的調用。
  初學MFC,上面的理解有不當的地方,歡迎大家指教。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章