日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

MFC和Win32之三___CGdiObject类和windows Gdi对象

發布時間:2023/12/4 windows 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MFC和Win32之三___CGdiObject类和windows Gdi对象 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

小結:

前面講到的windows窗口對象,在windows下用句柄來代表之,并且用了一個數據結構WNDCLASS(窗口類)來描述之。同理,windows的Gdi對象也有一些句柄來代表之(比如hPen等),同時也有一個數據結構來描述之,即設備描述表(Device Context),而且其本身也有句柄,因此也可以看作是windows的一個對象。

由于設備描述表這個數據結果不像WNDCLASS那樣單一,因為他要描述多個繪圖設備。所以MFC同時也封裝設備描述表,并用幾個類來代表不同的設備描述表,他們的基類都是CDC。這里特別講到了,當直接使用CDC這個基類的情況,可以看出CDC這個基類的構造函數中并沒有創建任何的設備描述表,所以要使用時創建一個設備描述表(堆上,棧上都可以)。同時這個基類的析構函數不是虛擬的,所以不必擔心該對象釋放時,它的句柄沒有釋放。

windows的Gdi對象,就是通過CGdiObject來封裝。

?


?

?

?

?

  • 設備描述表

    ?

    ?

  • 設備描述表概述

    ?

    ?

    ?

  • ?

    ?

    當一個應用程序使用GDI函數時,必須先裝入特定的設備驅動程序,然后為繪制窗口準備設備描述表,比如指定線的寬度和顏色、刷子的樣式和顏色、字體、剪裁區域等等。不像其他Win32結構,設備描述表不能被直接訪問,只能通過系列Win32函數來間接地操作。

    如同Windows“窗口類”一樣,設備描述表也是一種Windows數據結構,用來描述繪制窗口所需要的信息。它定義了一個坐標映射模式、一組GDI圖形對象及其屬性。這些GDI對象包括用于畫線的筆,繪圖、填圖的刷子,位圖,調色板,剪裁區域,及路徑(Path)。

    表2-2列出了設備描述表的結構和各項缺省值,表2-3列出了設備描述表的類型,表2-4顯示設備描述表的類型。

    表2-2 設備描述表的結構

    屬性

    缺省值

    Background color

    Background color setting from Windows Control Panel (typically, white)

    Background mode

    OPAQUE

    Bitmap

    None

    Brush

    WHITE_BRUSH

    Brush origin

    (0,0)

    Clipping region

    Entire window or client area with the update region clipped, as appropriate. Child and pop-up windows in the client area may also be clipped

    Palette

    DEFAULT_PALETTE

    Current pen position

    (0,0)

    Device origin

    Upper left corner of the window or the client area

    Drawing mode

    R2_COPYPEN

    Font

    SYSTEM_FONT (SYSTEM_FIXED_FONT for applications written to run with Windows versions 3.0 and earlier)

    Intercharacter spacing

    0

    Mapping mode

    MM_TEXT

    Pen

    BLACK_PEN

    Polygon-fill mode

    ALTERNATE

    Stretch mode

    BLACKONWHITE

    Text color

    Text color setting from Control Panel (typically, black)

    Viewport extent

    (1,1)

    Viewport origin

    (0,0)

    Window extent

    (1,1)

    Window origin

    (0,0)

     

    表2-3 設備描述表的分類

    Display

    顯示設備描述表,提供對視頻顯示設備上的繪制操作的支持

    Printer

    打印設備描述表,提供對打印機、繪圖儀設備上的繪制操作的支持

    Memory

    內存設備描述表,提供對位圖操作的支持

    Information

    信息設備描述表,提供對操作設備信息獲取的支持

    表2-3中的顯示設備描述表又分三種類型,如表2-4所示。

    表2-4 顯示設備描述表的分類

    名稱

    特點

    功能

    Class Device

    Contexts

    提供對Win16的向后兼容

     

    Common

    Device

    Contexts

    在Windows系統的高速緩沖區,數量有限

    Applicaion獲取設備描述表時,Windows用缺省值初始化該設備描述表,Application使用它完成繪制操作,然后釋放

    Private

    Device

    Contexts

    沒有數量限制,用完不需釋放一次獲取,多次使用

    多次使用過程中,每次設備描述表屬性的任何修改或變化都會被保存,以支持快速繪制

    ?

    ?

    (1)使用設備描述表的步驟

    要使用設備描述表,一般有如下步驟:

    ?

    • 獲取或者創建設備描述表;

      ?

      ?

    • 必要的話,改變設備描述表的屬性;

      ?

      ?

    • 使用設備描述表完成繪制操作;

      ?

      ?

    • 釋放或刪除設備描述表。

      ?

      ?

      ?

    Common設備描述表通過::GetDC,::GetDCEx,::BeginPaint來獲得一個設備描述表,用畢,用::ReleaseDC或::EndPaint釋放設備描述表;

    Printer設備描述表通過::CreateDC創建設備描述表,用::DeleteDC刪除設備描述表。

    Memory設備描述表通過::CreateCompatibleDC創建設備描述表,用::DeleteDC刪除。

    Information設備描述表通過::CreateIC創建設備描述表,用::DeleteDC刪除。

    (2)改變設備描述表屬性的途徑

    要改變設備描述表的屬性,可通過以下途徑:

    用::SelectObject選入新的除調色板以外的GDI Object到設備描述表中;

    對于調色板,使用::SelectPalette函數選入邏輯調色板,并使用::RealizePalette把邏輯調色板的入口映射到物理調色板中。

    用其他API函數改變其他屬性,如::SetMapMode改變映射模式。

    ?

  • 設備描述表在MFC中的實現

    ?

    ?

    ?

  • MFC提供了CDC類作為設備描述表類的基類,它封裝了Windows的HDC設備描述表對象和相關函數。

    ?

  • CDC類

    ?

    CDC類包含了各種類型的Windows設備描述表的全部功能,封裝了所有的Win32 GDI 函數和設備描述表相關的SDK函數。在MFC下,使用CDC的成員函數來完成所有的窗口繪制工作。

    CDC 類的結構示意圖2-2所示。

    ?

    CDC類有兩個成員變量:m_hDC,m_hAttribDC,它們都是Windows設備描述表句柄。CDC的成員函數作輸出操作時,使用m_Hdc;要獲取設備描述表的屬性時,使用m_hAttribDC。

    在創建一個CDC類實例時,缺省的m_hDC等于m_hAttribDC。如果需要的話,程序員可以分別指定它們。例如,MFC框架實現CMetaFileDC類時,就是如此:CMetaFileDC從物理設備上讀取設備信息,輸出則送到元文件(metafile)上,所以m_hDC和m_hAttribDC是不同的,各司其責。還有一個類似的例子:打印預覽的實現,一個代表打印機模擬輸出,一個代表屏幕顯示。

    CDC封裝::SelectObject(HDC hdc,HGDIOBJECT hgdiobject)函數時,采用了重載技術,即它針對不同的GDI對象,提供了名同而參數不同的成員函數:

    SelectObject(CPen *pen)用于選入筆;

    SelectObject(CBitmap* pBitmap)用于選入位圖;

    SelectObject(CRgn *pRgn)用于選入剪裁區域;

    SelectObject(CBrush *pBrush)用于選入刷子;

    SelectObject(CFont *pFont)用于選入字體;

    至于調色板,使用SelectPalette(CPalette *pPalette,BOOL bForceBackground )選入調色板到設備描述表,使用RealizePalletter()實現邏輯調色板到物理調色板的映射。

    ?

  • 從CDC派生出功能更具體的設備描述表

    ?

    ?

    ?

  • 從CDC 派生出四個功能更具體的設備描述表類。層次如圖2-3所示。

    ?

    ?

    下面,分別討論派生出的四種設備描述表。

    ?

    • CCientDC

      ?

      ?

      ?

    代表窗口客戶區的設備描述表。其構造函數CClientDC(CWnd *pWin)通過::GetDC獲取指定窗口的客戶區的設備描述表HDC,并且使用成員函數Attach把它和CClientDC對象捆綁在一起;其析構函數使用成員函數Detach把設備描述表句柄HDC分離出來,并調用::ReleaseDC釋放設備描述表HDC。

    ?

    • CPaintDC

      ?

      ?

      ?

    僅僅用于響應WM_PAINT消息時繪制窗口,因為它的構造函數調用了::BeginPaint獲取設備描述表HDC,并且使用成員函數Attach把它和CPaintDC對象捆綁在一起;析構函數使用成員函數Detach把設備描述表句柄HDC分離出來,并調用::EndPaint釋放設備描述表HDC,而::BeginPaint和::EndPaint僅僅在響應WM_PAINT時使用。

    ?

    • CMetaFileDC

      ?

      ?

      ?

    用于生成元文件。

    ?

    • CWindowDC

      ?

      ?

      ?

    代表整個窗口區(包括非客戶區)的設備描述表。其構造函數CWindowDC(CWnd *pWin)通過::GetWindowDC獲取指定窗口的客戶區的設備描述表HDC,并使用Attach把它和CWindowDC對象捆綁在一起;其析構函數使用Detach把設備描述表HDC分離出來,調用::ReleaseDC釋放設備描述表HDC。

    ?

  • MFC設備描述表類的使用

    ?

    ?

    ?

  • ?

  • 使用CPaintDC、CClientDC、CWindowDC的方法

    ?

    首先,定義一個這些類的實例變量,通常在棧中定義。然后,使用它。

    例如,MFC中CView對WM_PAINT消息的實現方法如下:

    void CView::OnPaint()

    {

    // standard paint routine

    CPaintDC dc(this);

    OnPrepareDC(&dc);

    OnDraw(&dc);

    }

    在棧中定義了CPaintDC類型的變量dc,隨著構造函數的調用獲取了設備描述表;設備描述表使用完畢,超出其有效范圍就被自動地清除,隨著析構函數的調用,其獲取的設備描述表被釋放。

    如果希望在堆中創建,例如

    CPaintDC *pDC;

    pDC = new CPaintDC(this)

    則在使用完畢時,用delete刪除pDC:

    delete pDC;

    ?

    ?

  • 直接使用CDC

    ?

    ?

    ?

  • 需要注意的是:在生成CDC對象的時候,并不像它的派生類那樣,在構造函數里獲取相應的Windows設備描述表。最好不要使用::GetDC等函數來獲取一個設備描述表,而是創建一個設備描述表。其構造函數如下:

    CDC::CDC()

    {

    m_hDC = NULL;

    m_hAttribDC = NULL;

    m_bPrinting = FALSE;

    }

    其析構函數如下:

    CDC::~CDC()

    {

    if (m_hDC != NULL)

    ::DeleteDC(Detach());

    }

    在CDC析構函數中,如果設備描述表句柄不空,則調用DeleteDC刪除它。這是直接使用CDC時最好創建Windows設備描述表的理由。如果設備描述表不是創建的,則應該在析構函數被調用前分離出設備描述表句柄并用::RealeaseDC釋放它,釋放后m_hDC為空,則在析構函數調用時不會執行::DeleteDC。當然,不用擔心CDC的派生類的析構函數調用CDC的析構函數,因為CDC::~CDC()不是虛擬析構函數。

    直接使用CDC的例子是內存設備上下文,例如:

    CDC dcMem; //聲明一個CDC對象

    dcMem.CreateCompatibleDC(&dc); //創建設備描述表

    pbmOld = dcMem.SelectObject(&m_bmBall);//更改設備描述表屬性

    …//作一些繪制操作

    ?

    dcMem.SelectObject(pbmOld);//恢復設備描述表的屬性

    dcMem.DeleteDC(); //可以不調用,而讓析構函數去刪除設備描述表

    ?

  • GDI對象

    ?

    ?

    ?

  • 在討論設備描述表時,已經多次涉及到GDI對象。這里,需強調一下:GDI對象要選入Windows 設備描述表后才能使用;用畢,要恢復設備描述表的原GDI對象,并刪除該GDI對象。

    一般按如下步驟使用GDI對象:

    Create or get a GDI OBJECT hNewGdi;

    ?

    hOldGdi = ::SelectObject(hdc, hNewGdi)

    ……

    ::SelectObject(hdc, hOldGdi)

    ::DeleteObject(hNewGdi)

    先創建或得到一個GDI對象,然后把它選入設備描述表并保存它原來的GDI對象;用畢恢復設備描述表原來的GDI對象并刪除新創建的GDI對象。

    需要指出的是,如果hNewGdi是一個Stock GDI對象,可以不刪除(刪除也可以)。通過

    HGDIOBJ GetStockObject(

    int fnObject // type of stock object

    );

    來獲取Stock GDI對象。

    ?

    ?

  • MFC GDI對象

    ?

    MFC用一些類封裝了Windows GDI對象和相關函數,層次結構如圖2-4所示:

    ?

    ?

    CGdiObject封裝了Windows GDI Object共有的特性。其派生類在繼承的基礎上,主要封裝了各類GDI的創建函數以及和具體GDI對象相關的操作。

    ?

    CGdiObject的構造函數僅僅讓m_hObject為空。如果m_hObject不空,其析構函數將刪除對應的Windows GDI對象。MFC GDI對象和Windows GDI對象的關系如圖2-5所示。

    ?

  • 使用MFC GDI類的使用

    ?

    ?

    ?

  • 首先創建GDI對象,可分一步或兩步創建。一步創建就是構造MFC對象和Windows GDI對象一步完成;兩步創建則先構造MFC對象,接著創建Windows GDI對象。然后,把新創建的GDI對象選進設備描述表,取代原GDI對象并保存。最后,恢復原GDI對象。例如:

    void CMyView::OnDraw(CDC *pDC)

    {

    CPen penBlack; //構造MFC CPen對象

    if (penBlack.CreatePen(PS_SOLID, RGB(0, 0, 0)))

    {

    CPen *pOldPen = pDC->SelectObject(&penBlack)); //選進設備表,保存原筆

    pDC->SelectObject(pOldPen); //恢復原筆

    }else

    {

    }

    }

    和在SDK下有一點不同的是:這里沒有DeleteObject。因為執行完OnDraw后,棧中的penBlack被銷毀,它的析構函數被調用,導致DeleteObject的調用。

    還有一點要說明:

    pDC->SelectObject(&penBlack)返回了一個CPen *指針,也就是說,它根據原來PEN的句柄創建了一個MFC CPen對象。這個對象是否需要刪除呢?不必要,因為它是一個臨時對象,MFC框架會自動地刪除它。當然,在本函數執行完畢把控制權返回給主消息循環之前,該對象是有效的。

    轉載于:https://www.cnblogs.com/ghw0501/archive/2012/02/24/4733925.html

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的MFC和Win32之三___CGdiObject类和windows Gdi对象的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。