久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

今天在學習用內(nèi)存DC畫圖,,終于有了初步了解。現(xiàn)將收集的關于內(nèi)存DC介紹及其相關操作的資料貼出來共享一下,。

 行走在理想邊緣 2014-08-13

DC 即Device Context,,是GDI內(nèi)部的一個資料結(jié)構(gòu),一個DC會和某個特定的顯示設備(如打印機,、屏幕等)產(chǎn)生關聯(lián),。我們?nèi)绻苋〉迷揇C的handle 那我們便可以在這顯示設備上寫字、畫圖,。
在Form 或Picturebox中都有一個hdc的屬性,,指的便是這東西,但是,,怎么又會有一個Memory DC呢?這是一個存在記憶體內(nèi)的 dc ,,它除了不像form picturebox能將圖形,、文字顯示出來之外,,其他的幾乎都相同,它也可以用在所有的 GDI API 呼叫之上,,其實我們在VB中早就有使用上這 Memory DC 了,,只是沒有自覺。當我們設 form picturebox的AutoRedraw = True時,, hdc所指的便是Momoory DC,,這時我們在其上作繪圖動作,都沒有顯示在form上,,這便是先前說的,,它只是在記憶體中,不會真的畫出圖,。而我們下 refresh指令時,,便是將這MemoryDC上的圖,,copy到 form/PictureBox上。
  另外我們也可以使用CreateCompatibleDC() API 它傳入一個 hDc ,,代表產(chǎn)生的 Memory DC和 hdc相容,,若傳0則是與屏幕相容的 Memory DC hMemDC = CreateCompatibleDC(0)
  這時候,該hMemDC所指的繪圖區(qū)有多大呢?其實只有一個單色Pixel,,直到我們使用SelectObject( hMemDC, hBitmap)
  那hMemDC顯示區(qū)就會有和hBitmap一樣的寬度,、高度、顏色選擇等,。 而且我們在hMemDC上的任何繪圖,,也都會反映在 hBitMap上,也就是說,,原本hBitMap所指的圖,,在SelectObject(hMemDC, hBitMap)后,我們使用gdi函式在hMemDC上畫一條線,,那么該hBitmap所指的圖也會有一條線了,。
那么Memory DC又有什么作用呢?
我們知道, 在使用VC開發(fā)圖形相關的應用程序時,,常常需要使用MFC的CDC類直接把圖形畫在窗口上,。這通常是通過響應Windows的WM_PAINT消息實現(xiàn)的。如果要畫的圖形比較復雜,,或者比較大,,那么畫圖過程可能會造成窗口的閃爍。當窗口調(diào)整大小時,,這種閃爍由為明顯,。
解決窗口閃爍問題的有效辦法就是使用內(nèi)存DC,也稱為緩沖DC,。在內(nèi)存中準備一個和窗口DC相同屬性的DC,,在這個內(nèi)存DC上執(zhí)行畫圖操作。完成畫圖以后,,把畫圖輸出的內(nèi)容整體復制到目標窗口DC上,。因為畫圖操作不在窗口DC上進行,所以在畫圖的過程中窗口可以保持原來的內(nèi)容,。當畫好的內(nèi)容被復制到窗口DC時,,因為復制操作執(zhí)行的非常快,,所以用戶感覺窗口仿佛被立刻被畫好,,從而消除了從舊畫面到白板再到新畫面的閃爍現(xiàn)象。
生成內(nèi)存DC主要用到以下四個函數(shù):
CreateCompatibleDC(CDC* pDC ),。CDC類的成員函數(shù),,用于創(chuàng)建一個和pDC指向的DC兼容的內(nèi)存DC,。
CreateDiscardableBitmap( CDC* pDC, int nWidth, int nHeight)。CBitmap類的成員函數(shù),,用于按指定尺寸創(chuàng)建一個和pDC指向的DC兼容的位圖,。    
SelectObject(CBitmap * pBitmap)。CDC類的成員函數(shù),,執(zhí)行以后,,所有在該DC上的圖像輸出都將被畫到pBitmap指向的位圖上。
BOOL BitBlt (int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop ),。CDC類的成員函數(shù),,用于從源DC(pSrcDC)復制一個矩形的圖象到當前DC中。
 好了,,目前我所能理解到的原理就是上面的樣子,,下面來看看具體應該怎樣操作吧。
對于一個窗口,,我們可以用下面的代碼來創(chuàng)建內(nèi)存DC,,在內(nèi)存DC上輸出,并最終復制到窗口DC上,。
C/C++ code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void PaintWnd(CWnd * pWnd)
{
     CDC * pWndDC = pWnd->GetWindowDC();
     CRect WndRect = pWnd->GetWindowRect();
     CDC MemDC;
     CBitMap MemBitmap; 
     MemDC.CreateCompatibleDC(pWndDC);  // 創(chuàng)建內(nèi)存DC
     MemBitmap.CreateCompatibleBitmap(  // 創(chuàng)建兼容的位圖
         pWndDC,
         WndRect.Width(),
         WndRect.Height());
  MemDC.SelectObject(MemBitmap);  // 讓內(nèi)存DC輸出到位圖(我的理解就是選擇畫布)
     // 使用MemDC畫圖
     ……
    pWndDC->BitBlt(// 從內(nèi)存DC復制到窗口DC
         0,0,
         WndRect.Width(),
         WndRect.Height(),
         &MemDC, 
         0,0,
         SRCCOPY);
}

當然,,實際的情況下,我們需要考慮的更多,,因為內(nèi)存DC,、位圖的創(chuàng)建都可能會失敗。為了簡化代碼,,此處定義了一個類CMemoryDC,,包裝了內(nèi)存DC創(chuàng)建過程中的出錯處理,內(nèi)存DC的事后清理等操作,,并自動復制內(nèi)存DC的內(nèi)容到目標DC上,。
聲明CMemoryDC類的頭文件MemoryDC.h如下:
C/C++ code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#pragma once
 #include "Afxwin.h"
   
 class CMemoryDC
 {
 public:
      CMemoryDC(CDC *dc, RECT * rect,bool autoRender = false);
      ~CMemoryDC(void);
   
      bool IsOK();
      void Render(CDC * p_objectDC = NULL);
      CDC* GetMemoryDC();
      operator CDC * ();
 private:
     bool m_bAutoRender;
  CRect m_DCRect;
   CDC* m_pOriginalDC;
     CDC m_MemoryDC;
     CBitmap m_MemoryBmp;
};

類的實現(xiàn)文件CMemoryDC.cpp如下:
C/C++ code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 #include ".MemoryDC.h"
   
 CMemoryDC::CMemoryDC(CDC *dc, RECT * rect, bool autoRender)
  {    
      m_bAutoRender = autoRender;
      m_pOriginalDC = dc;
      if (dc==NULL || rect==NULL)
          return;
      if (!m_MemoryDC.CreateCompatibleDC(dc))
          return;
      m_DCRect.SetRect(rect->left, rect->top, rect->right, rect->bottom);   
      if (!m_MemoryBmp.CreateCompatibleBitmap(dc, m_DCRect.Width(), m_DCRect.Height()))
          return;
      m_MemoryDC.SelectObject(m_MemoryBmp);
 }
   
 CMemoryDC::~CMemoryDC(void)
  {
      if (m_bAutoRender)
          Render();
      if (m_MemoryDC.m_hDC!=NULL)
          m_MemoryDC.DeleteDC();
      if (m_MemoryBmp.m_hObject!=NULL)
          m_MemoryBmp.DeleteObject();
 }
   
 bool CMemoryDC::IsOK()
  {
      return m_MemoryDC.m_hDC!=NULL && m_MemoryBmp.m_hObject != NULL;
   
 }
 void CMemoryDC::Render(CDC * p_objectDC)
  {
      if (!IsOK())
          return;
   
      CDC * pDC = (p_objectDC==NULL ? m_pOriginalDC : p_objectDC);
      CSize Size = m_MemoryDC.GetViewportExt() ;
      pDC->BitBlt(
          m_DCRect.left, 
          m_DCRect.top,
          m_DCRect.Width(),
          m_DCRect.Height(),
          &m_MemoryDC, 
          0,0,
          SRCCOPY);
 }
 CDC* CMemoryDC::GetMemoryDC()
  {
      return & m_MemoryDC;
 }
 CMemoryDC::operator CDC * ()
  {
      return & m_MemoryDC;
}

使用這個類可以大大簡化內(nèi)存DC的創(chuàng)建操作。如果我們在窗口消息WM_PAINT的響應函數(shù)中使用內(nèi)存DC,,只要用如下這樣簡便的代碼便可實現(xiàn):
 
C/C++ code?
1
2
3
4
5
6
7
8
9
CRect Rect;
 GetClientRect(Rect);
 CPaintDC dc(this); // device context for painting
      CMemoryDC MemDC(&dc, Rect, true);
      if (MemDC.IsOK())
       {
          // 使用MemDC畫窗口
       }    
 // MemDC析構(gòu)時會自動把圖像復制到dc,,無需其它操作
使用CMemoryDC創(chuàng)建內(nèi)存DC防止窗口閃爍,編程的代碼和不使用內(nèi)存DC時相比,,數(shù)量和復雜性幾乎沒有增加。


另外,,關于此文章的word文檔我也上傳了,,需要的朋友可去下載。http://download.csdn.net/source/1381542

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,謹防詐騙,。如發(fā)現(xiàn)有害或侵權內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多