MFC中显示 .bmp格式的位图
最近在看VisualC++ 图像处理的书籍,表示一直在从基础做起,今天就记录一个简单功能的实现,显示.bmp格式的位图。
首先需要理解的是窗口创建的过程包括两个步骤:首先擦除窗口的背景,然后在对窗口进行重新绘制。
一般而言,对于单文档或多文档的MFC程序,显示图像的代码要放在OnDraw函数之中。刚刚说过,窗口重绘时,要先将窗口的背景擦除,也就是发送WM_ERASEBKGND消息,然后用OnEraseBkgnd()函数处理这个消息,所以我们的显示图像的代码也可以放在这个函数之中。当然,这里只是为了实现显示位图这一个功能,在实际工程中,要根据实际情况,选择代码放置的地方。
下面先给出代码,然后一行一行地详细解释:
BOOL CLoadBitmapView::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//return FALSE;
HBITMAP hBit;
hBit=(HBITMAP) LoadImage(NULL,_T("D:\\Axing.bmp"),IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION); //载入图像
CBitmap cBit;
cBit.Attach(hBit);
CDC MemDC;
MemDC.CreateCompatibleDC(pDC); //创建与当前设备描述表相适应的内存DC
BITMAP bitmap;
cBit.GetBitmap(&bitmap);
CBitmap *oldBit;
oldBit=MemDC.SelectObject(&cBit);
CRect rect;
GetClientRect(&rect);
pDC->BitBlt(100,100,rect.Width()/2.5,rect.Height(),&MemDC,0,0,SRCCOPY);
return TRUE;
//return CView::OnEraseBkgnd(pDC);
}
首先来解释一下HBITMAP、CBitmap、BITMAP三者之间的关系。
HBITMAP是图片的句柄,CBitmap是MFC定义的一个类,在这个类中对HBITMAP进行了封装,BITMAP则是一个结构体,这个结构体中保存着位图的各种信息(如宽度和高度等)。有三个函数是和这三个类型息息相关的。
第一个:Attach(),这个函数是CBitmap类的成员函数,作用就是将HBITMAP类型转换成CBitmap类型。我们在代码中会用到它。
第二个:GetBitmap(),这个函数也是CBitmap类的成员函数,作用就是获取位图的信息,并将位图的信息保存在BITMAP 结构指针中。
第三个:GetObject(),这个函数的作用就是,从HBITMAP句柄中获取BITMAP结构。
这三个函数的具体用法,详细说明在这里就不赘述了,用的时候可以百度一下很方便的。
我们先建立了一个HBITMAP类型的句柄,然后用LoadImage()函数来载入一个位图,并保存位图的句柄。之后,创建一个CBitmap类的对象,然后将HBITMAP转换成CBitmap对象(用Attach()函数)。之后用CReateCompatibleDC()函数,创建一个与当前设备上下文相兼容的内存DC。
问题来了,为什么要创建这个内存DC呢?
其实,这个内存DC的作用就是缓冲。如果需要对屏幕进行比较多的GUI操作,如果直接对屏幕DC进行操作,会导致同显示内存之间的过于频繁的数据交换,于是程序运行效率将受到严重影响。任何绘图的过程都是这样,要完成一幅图像的显示,总是在显示终端上依次绘制每个像素点,以形成完整的图像。我们在内存中虚拟一块画布(就是内存DC),绘图时仅仅对内存进行操作。待政府图像绘制完成时在整体复制到屏幕上,这样避免了外设和内存之间频繁的数据交换,程序的运行效率会提高很多。这就是使用CreateCompatibleDC()函数创建内存DC 的作用。
接着,我们将位图选入到内存DC中(MemDC.SelectObject(&cBit)),这一步也是相当重要的。因为当兼容的内存DC创建的时候,他的显示表面是标准的一个单色像素宽和单色像素高。在应用程可以使用内存DC进行绘图操作之前,必须将一个具有正确高度和宽度的位图,选入到内存DC中,这时内存设备上下文显示表面的大小就由当前选入的位图决定了。
之后CRect rect;GetClientRect(&rect);用于获取客户区。
最后用BitBlt()函数将内存DC中的内容复制到当前DC中,显示位图完毕。
这里要解释一下BitBlt函数,它的函数原型为:
BOOLBitBlt(int x,int y,int nWidth,int nHeight,CDC*pSrcDC,int xSrc,int ySrc,DWORDdwRop);
参数x、y表示目的DC(当前设备上下文)矩形区域的左上角坐标,nWidth,nHeight,表示矩形区域的宽和高,pSRCDC则是源DC(内存DC)的指针,xSrc和ySrc表示源DC矩形区域的左上角坐标。我们可以看到并没有参数表示源目的矩形区域的宽和高,这样,区域之间的复制只能是1:1的,所以当图像比较大时,只能显示图像的一部分。为了解决这个问题,可以用StretchBlt()函数,这个函数和BitBlt()函数的功能基本一致,只是可以对图像进行伸缩变换,这是因为在StretchBlt()函数中增加了两个参数,表示源DC矩形区域的大小。所以上面的代码可以改成
pDC->StretchBlt(100,100,rect.Width()/2.5,rect.Height(),&MemDC,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
。
这样就可以显示整张位图了。
MFC中显示 .bmp格式的位图的更多相关文章
- MFC对话框中显示BMP,JPG图片
//************************************ // 方法说明: 显示JPG和GIF.BMP图片 // 参数说明: CDC * pDC 设 ...
- MFC对话框显示BMP图片
1.MFC对话框显示BMP图片我们先从简单的开始吧.先分一个类: (一) 非动态显示图片(即图片先通过资源管理器载入,有一个固定ID) (二) 动态载入图片(即只需要在程序中指定图片的路径即可载入) ...
- 火狐低版本中显示时间格式为:yyyy-MM-dd hh:mm:ss,出现NaN
在低版本的火狐(43以下)和IE8中,显示时间格式为:yyyy-MM-dd hh:mm:ss,会出现NaN:原因是只支持yyyy/MM/dd hh:mm:ss; 所以在new Date('2018-0 ...
- MFC中显示一张位图
1.用类CBitmap加载位图 2.创建内存DC, 将位图选进此内存DC 3.调用BitBlt将内存DC的内容拷贝到其它DC(通知是显示DC) 例子(来自MSDN): // This OnDraw() ...
- Linux C语言解析并显示.bmp格式图片
/************************* *bmp.h文件 *************************/ #ifndef __BMP_H__ #define __BMP_H__ # ...
- 在MFC中显示图片(opencv Mat类型)
1,在MFC窗体中添加picture control控件,并添加对应的变量名 2,在窗体的初始化窗口中添加: namedWindow(); HWND hWnd = (HWND)cvGetWindowH ...
- 在RichTextBox控件中显示RTF格式文件
实现效果: 知识运用: RichTextBox控件的LoadFile方法 //将文件内容加载到RichTextBox控件中 public void LoadFile(string path,Ri ...
- asp:gridview 中显示日期格式
boundfield中应该这样设置: <asp:BoundField HeaderText="发表时间" DataField="PostTime" Htm ...
- 在MFC中显示cmd命令行
添加函数 void InitConsoleWindow1() { ; FILE* fp; AllocConsole(); nCrt = _open_osfhandle((long)GetStdHand ...
随机推荐
- 大数据时代的技术hive:hive介绍
我最近研究了hive的相关技术,有点心得,这里和大家分享下. 首先我们要知道hive到底是做什么的.下面这几段文字很好的描述了hive的特性: 1.hive是基于Hadoop的一个数据仓库工具,可以将 ...
- Solr单机部署和集群部署
用到的相关jar包:http://pan.baidu.com/disk/home#list/path=%2Fsolr Solr目录结构 Solr 目录 Contrib :solr 为了增强自身的功能, ...
- Bootstrap学习之路(2)---导航组件
在bootstrap中,导航条的样式都依赖于.nav类,而样式又分为多种,如: 标签页的样式为:.nav-tabs <ul class="nav nav-tabs"> ...
- js 只能输入数字和小数点
<html><head><meta http-equiv="content-Type" content="text/html;charset ...
- Android项目中单实例数据库类,解决database is locked
一.数据库操作 package com.ping.db; import android.content.Context; import android.database.sqlite.SQLiteDa ...
- Java读写大文本文件(2GB以上)
如下的程序,将一个行数为fileLines的文本文件平均分为splitNum个小文本文件,其中换行符'r'是linux上的,windows的java换行符是'\r\n': package kddcup ...
- [Duilib] 交替背景色设置失败的原因
用列表显示一列数据时,相邻数据常用不同背景色来达到区别的作用.但是设置了Duilib相应属性之后交替背景色效果并未出现.逐一排除之后发现是item的enable属性设置为"false&quo ...
- 求相同号码一天内的上网流量——mapreduce
上网数据 1363157985066 13726230503 00-FD-07-A4-72-B8:CMCC 120.196.100.82 i02.c.aliimg.com 24 27 2481 246 ...
- python 安装预编译库注意事项-pip
一般安装依赖库用pip install 库名 就可以,某些情况下依赖的库需要安装预编译好的, 可以参考pip 安装时的错误信息 下面这个链接中可以直接下载 http://www.lfd.uci.edu ...
- spring依赖注入原理剖析
PropertyDefinition.java package junit.test; public class PropertyDefinition { private String name; p ...