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 ...
随机推荐
- linux内核值shmmax问题
问题:(rac安装过程中grid检测) Please run the following script on each node as "root" user to execut ...
- 2016第20周四java基础概念
简单的说JDK=JRE+Java编译器.调试器.工具类库等:JRE=JVM(类似于jre目录下的bin)+必要运行的类库(类似于jre目录下的lib) JVM:Java Virtual Mechina ...
- Android 高仿UC浏览器监控剪切板弹出悬浮窗功能
UC浏览器应该是android手机里 最流行的浏览器之一了,他们有一个功能 相信大家都体验过,就是如果你复制了什么文字,(在其他app中 复制也有这个效果!,所以能猜到肯定是监控了剪切板),就会弹出一 ...
- XX.frame.origin.x 赋值问题
can't use that myView.frame.origin.x=25.0; 因为.操作 和 = 一起用的话会调用 set方法.所以上式是行不通的. 可以用下面的方式来实现. that I h ...
- pthread_attr_t 线程属性(一)
1. 线程属性: 使用pthread_attr_t类型表示,我们需要对此结构体进行初始化, 初始化后使用,使用后还要进行去除初始化! ...
- invalid initialization of non-const reference of type与discards qualifiers
参数传递 函数参数的传递是初始化语义:用调用者的实参去初始化函数的形参,如果参数是对象,需要调用该类的拷贝构造函数,如果没有显式定义的拷贝构造函数,则执行默认的按成员拷贝 ...
- [转] VS 整合NUnit进行单元测试
Jeff Wong原文 5分钟实现VS2010整合NUnit进行单元测试 1.下载安装NUnit(最新win版本为NUnit-2.6.0.12051.msi) http://www.nunit.org ...
- YII Framework学习教程-YII的安全
web应用的安全问题是很重要的,在“黑客”盛行的年代,你的网站可能明天都遭受着攻击,为了从某种程度上防止被攻击,YII提供了防止攻击的几种解决方案.当然这里讲的安全是片面的,但是值得一看. 官方提供的 ...
- jQuery遮罩插件jQuery.blockUI.js简介
利用Jquery.blockui.js创建可拖动.自定义内容的弹出层 利用Jquery.blockui.js创建可拖动.自定义内容的弹出层 目标 : 1 . 弹出层的内容可以自定义任意的HTML元素 ...
- [转]Linux的chattr与lsattr命令详解
转自:http://www.cnblogs.com/yangxia-test/archive/2013/05/24/3096410.html 这两个命令是用来查看和改变文件.目录属性的,与chmod这 ...