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

位图是描述图像的最简单直观的一种方式,把图像横向分为等间距的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,几乎所有绘图过程都应该遵循这个原理。不止是为了防止抖动,也为了提升效率。当然,如果有特殊的需求的话,那就另当别论了。

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值