学了MFC一段时间后,试着要用对话框打开一幅bmp图像并保存,结果发现网上这些资料太少了,而且有的也讲不清,讲不全,所以自己磕磕碰碰捣鼓了好久,期间也谢谢各位大神的指导,现在我终于完成,特意写出来与大家分享,各位菜鸟共勉。
一、首先要先了解bmp位图结构
http://wenku.baidu.com/view/d06c23543c1ec5da50e2706d.html
可以去看看,内容不多但是够看,也容易懂
二、了解位图的显示函数
SetStretchBltMode()
StretchDIBits()具体函数介绍自己百度一下,我就不多说了
三、开始做啦
1、新建一个MFC对话框文档
默认其他设置,点击完成后会出现这个界面
在按钮上单击鼠标右键,在弹出的列表中选择属性 把标题改为读取图片
再添加一个按钮,把ID改为IDC_SAVE,标题改为保存图片
在控件中选择图像,然后在对话框画一个大小适宜的矩形框,在选中对话框点击右键,选择属性,把ID改为IDC_PICTURE
回到对话框界面,双击读取图片按钮,这时会弹出一个对话框,点确定然后就会跳到关联函数这边了
先把CDialog::OnOK();注释起来,这个是点击按钮后对话框就会关闭的函数
然后在// CDialog::OnOK();下面添加以下代码
代码都有注释,不懂的地方可以自己再百度
//CFileDialog为VC中打开文件对话框类
BITMAPFILEHEADER bmpHeader;//文件头
BITMAPINFOHEADER bmpInfo;//信息头
CFileDialog dlg(TRUE, "*.BMP", NULL,NULL,"位图文件(*.BMP)|*.bmp;*.BMP|",this);
CFile bmpFile;//记录打开文件
CString strFileName;//记录选择文件路径
if (!dlg.DoModal() == IDOK) return;
strFileName = dlg.GetPathName();
//以只读的方式打开文件
if(!bmpFile.Open(strFileName, CFile::modeRead|CFile::typeBinary))return;
if (bmpFile.Read(&bmpHeader,sizeof(BITMAPFILEHEADER))!= sizeof(BITMAPFILEHEADER))
{
AfxMessageBox("readbmp header failed!");
return;
}
if (bmpHeader.bfType != 0x4d42)
{
AfxMessageBox("invalidfile type!");
return;
}
if (bmpFile.Read(&bmpInfo,sizeof(BITMAPINFOHEADER))!= sizeof(BITMAPINFOHEADER))
{
AfxMessageBox("readbmp infor header failed!");
return;
}
if (bmpInfo.biBitCount != 24)
{
AfxMessageBox("File is not 24 bit.Applicationdoesn't support this kind of file!");
return;
}
pBmpInfo = (BITMAPINFO*)new char[sizeof(BITMAPINFOHEADER)];
if (!pBmpInfo)
{
AfxMessageBox("memoryerror!");
return;
}
//为图像数据申请空间
memcpy(pBmpInfo,&bmpInfo,sizeof(BITMAPINFOHEADER));
DWORD dataBytes = bmpHeader.bfSize - bmpHeader.bfOffBits;
pBmpData = (BYTE*)new char[dataBytes];
if (!pBmpData)
{
AfxMessageBox("memoryerror!");
delete pBmpData;
return;
}
if (bmpFile.Read(pBmpData,dataBytes) != dataBytes)
{
AfxMessageBox("Readbmp data failed!");
delete pBmpInfo;
delete pBmpData;
return;
}
bmpFile.Close();
CWnd *pWnd=GetDlgItem(IDC_PICTURE);//获得pictrue控件窗口的句柄
CRect rect;
pWnd->GetClientRect(&rect);//获得pictrue控件所在的矩形区域
CDC *pDC=pWnd->GetDC();//获得pictrue控件的DC
//显示图片
pDC->SetStretchBltMode(COLORONCOLOR);
StretchDIBits(pDC->GetSafeHdc(),0,0,rect.Width(),rect.Height(),0,0,bmpInfo.biWidth,bmpInfo.biHeight,pBmpData,pBmpInfo,DIB_RGB_COLORS,SRCCOPY);
iBmpWidth=bmpInfo.biWidth;
iBmpHeight=bmpInfo.biHeight;
然后在这个.cpp文件头处添加
BITMAPINFO* pBmpInfo; //记录图像细节
BYTE* pBmpData; //图像数据
int iBmpWidth; // 输入的宽度,以像素为单位
int iBmpHeight; // 输入的高度,以像素为单位
这些是全局变量,主要是为了后面图像保存可以用的
再回到对话框界面,双击保存图片按钮,这时会弹出一个对话框,点确定然后就会跳到关联函数这边了
在// TODO: Add your control notificationhandler code here下添加下面这些代码
BITMAPFILEHEADER bmpf;//文件头
BITMAPINFOHEADER bmpi;//信息头
int Widthbytes;
CFile bmpFile;
CString strFileName;
CFileDialog dlg(FALSE, "*.BMP", NULL,NULL,"位图文件(*.BMP)|*.bmp;*.BMP|");
if (!dlg.DoModal() == IDC_SAVE)return;
strFileName = dlg.GetPathName();
if (bmpFile.Open(strFileName, CFile::modeCreate |CFile::modeReadWrite)== 0) return ;
Widthbytes = (iBmpWidth*3+3)/4*4;//位图对齐,确保为4的倍数
/* BITMAPFILEHEADER结构填写 */
bmpf.bfType =0x4d42;
bmpf.bfOffBits =sizeof(BITMAPFILEHEADER)+ sizeof(BITMAPINFOHEADER);
bmpf.bfSize = bmpf.bfOffBits + Widthbytes *iBmpHeight;
bmpf.bfReserved1 =0;
bmpf.bfReserved2 =0;
/* BITMAPINFOHEADER结构填写 */
bmpi.biSize = sizeof(BITMAPINFOHEADER);
bmpi.biWidth = iBmpWidth;
bmpi.biHeight =iBmpHeight;
bmpi.biPlanes = 1;
bmpi.biBitCount =24;//24位
bmpi.biCompression= BI_RGB;
bmpi.biSizeImage=0;
bmpi.biXPelsPerMeter= 0;
bmpi.biYPelsPerMeter= 0;
bmpi.biClrUsed = 0;
bmpi.biClrImportant= 0;
bmpFile.Write(&bmpf,sizeof(bmpf));//写文件头;
bmpFile.Write(&bmpi,sizeof(bmpi));//写信息头;
bmpFile.Write(pBmpData,Widthbytes*iBmpHeight);//写图像数据信息;
bmpFile.Close();
OK全部完成了,编译运行一下,点击打开图片按钮就能显示图片了
呵呵,写得不够专业,还望大家不吝赐教