C++ MFC使用GDI對象CBitmap示例

原文鏈接:http://c.biancheng.net/cpp/html/3091.html

位圖是描述圖像的最簡單直觀的一種方式,把圖像橫向分爲等間距的W列,縱向分爲等間距的H列,於是這個圖像大小被定義爲分辨率W*H。位圖分爲單色圖和彩色圖,區分方法是圖片的一個像素點可以用多少種顏色表示。現在這裏介紹的位圖是作爲GDI對象來介紹的,後面會在位圖專題中介紹位圖。

在MFC中CBitmap類封裝了位圖對象及其基本操作,可以使用多種方式來創建位圖對象。

1) 在內存中創建位圖對象

BOOL CreateBitmap(
    int nWidth,         //位圖寬度
    int nHeight,        //位圖高度
    UINT nPlanes,       //指定目標設備的位面數
    UINT nBitcount,     //顏色位圖
    const void* lpBits  //位圖數據
);

當前內存中已存在位圖數據,需要構造CBitmap對象便於管理位圖,此時就可以簡單地調用CreateBitmap即可。

2) 根據BITMAP結構在內存中創建位圖對象

BOOL CreateBitmapIndirect(
    LPBITMAP lpBitmap  //指向BITMAP結構
);

CreateBitmapIndirect與CreateBitmap類似,都是在內存中直接創建位圖對象。而CreateBitmapIndirect通過BITMAP結構指定待創建位圖對象的參數信息。BITMAP結構定義如下:

typedef struct tagBITMAP
{
    LONG    bmType;        //位圖類型。對於邏輯位圖,必須爲0
    LONG    bmWidth;       //位圖寬度,必須大於0
    LONG    bmHeight;      //位圖高度,必須大於0
    LONG    bmWidthBytes;  //位圖數據中一行有幾個字節
    WORD    bmPlanes;      //指定目標設備的位面數
    WORD    bmBitsPixel;   //指定每個像素的位數
    LPVOID  bmBits;        //位圖數據
} BITMAP;


3) 創建與指定設備上下文兼容的位圖對象

BOOL CreateCompatibleBitmap(
    CDC* pDC,    //目標DC
    int nWidth,  //位圖寬度
    int nHeight  //位圖高度
);

 

4) 從應用程序資源中加載位圖對象,有兩種形式,可以根據資源名或資源ID加載。

BOOL LoadBitmap(
    LPCTSTR lpszResourceName  //位圖資源名,絕對路徑
);

BOOL LoadBitmap(
    UINT nIDResource  //位圖資源ID
);

示例:使用GDI對象CBitmap顯示位圖

1) 導入位圖資源。通過加載位圖資源的方式,加載8個位圖資源,資源ID爲默認ID。

2) 定義繪圖結構和變量

struct my_Bitmap{
    CRect rect;  //圖形顯示區域
    CBitmap bmp;  //位圖
};

成員變量:my_Bitmap m_my_Bitmap[8];

3) 初始化繪圖區域

void CSDITestView::InitRectBitmap()
{
    //加載的圖片大小是128*128
    CRect rect(0,0,128,128);
    for (int i=0;i<8;i++)
    {
        if (i<4)
        {
            //第一行圖形
            CRect rect;
            rect.left=20+i*160;
            rect.top=20;
            rect.right=100+i*160;
            rect.bottom=148;

            m_my_Bitmap[i].rect.CopyRect(rect);
        }
        else
        {
            //第二行圖形
            CRect rect;
            rect.left=20+(i-4)*160;
            rect.top=168;
            rect.right=100+(i-4)*160;
            rect.bottom=296;

            m_my_Bitmap[i].rect.CopyRect(rect);
        }
    }
}

4) 初始化繪圖信息

void CSDITestView::InitBitmap()
{
    m_my_Bitmap[0].bmp.LoadBitmapW(IDB_BITMAP1);
    m_my_Bitmap[1].bmp.LoadBitmapW(IDB_BITMAP2);
    m_my_Bitmap[2].bmp.LoadBitmapW(IDB_BITMAP3);
    m_my_Bitmap[3].bmp.LoadBitmapW(IDB_BITMAP4);
    m_my_Bitmap[4].bmp.LoadBitmapW(IDB_BITMAP5);
    m_my_Bitmap[5].bmp.LoadBitmapW(IDB_BITMAP6);
    m_my_Bitmap[6].bmp.LoadBitmapW(IDB_BITMAP7);
    m_my_Bitmap[7].bmp.LoadBitmapW(IDB_BITMAP8);
}

 

5) 具體繪圖過程。在OnDraw函數中添加下面的代碼:

//採用GDI CBitmap繪圖 S
CRect WndRect;
GetWindowRect(&WndRect);
ScreenToClient(&WndRect);

CClientDC cdc(this);
CDC mdc,TempDc;
BITMAP BmpInfo;
CBitmap ClientBmp,*pOldBmp;
//創建與設備DC兼容的內存DC
mdc.CreateCompatibleDC(&cdc);
TempDc.CreateCompatibleDC(&cdc);
//創建與設備DC兼容的位圖對象
ClientBmp.CreateCompatibleBitmap(&cdc,WndRect.right,WndRect.bottom);
mdc.SelectObject(&ClientBmp);

//依次把位圖貼到內存DC
for (int i=0;i<8;i++)
{
    TempDc.SelectObject(&m_my_Bitmap[i].bmp);
    m_my_Bitmap[i].bmp.GetBitmap(&BmpInfo);

    mdc.TransparentBlt(m_my_Bitmap[i].rect.left,m_my_Bitmap[i].rect.top,BmpInfo.bmWidth,BmpInfo.bmHeight,&TempDc,0,0,BmpInfo.bmWidth,BmpInfo.bmHeight,RGB(255,255,255));

}
//把內存DC貼到設備DC上
cdc.BitBlt(0,0,WndRect.right,WndRect.bottom,&mdc,0,0,SRCCOPY);
//環境清理
ClientBmp.DeleteObject();
mdc.DeleteDC();
//採用GDI CBitmap繪圖 E
6) 運行結果如圖4-4-1所示:


圖4-4-1 使用GDI對象CBitmap顯示圖片


其實,不僅僅對於位圖操作需要先寫到內存DC後寫到設備DC,幾乎所有繪圖過程都應該遵循這個原理。不止是爲了防止抖動,也爲了提升效率。當然,如果有特殊的需求的話,那就另當別論了。

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章