资源描述
打开一幅图片
1. 新建一个多文档MFC应用程序.
2. 在_Doc.h文件C_Doc类中增加以下组员变量;
public:
int numquad; //调色板数
int flagOpen; //标志是否打开bmp
BITMAPINFO* pbi; //统计图像细节
BYTE* lpbuf; //图像数据
RGBQUAD* quad; //调色板
BITMAPFILEHEADER bf;//文件头
BITMAPINFOHEADER bi; //信息头
3. 修改”打开”菜单项响应函数;
a. 找到菜单资源
b. 在”打开”菜单项建立类向导,页面设置以下:
选择“Add function”,然后单击“Edit Code”
编辑代码以下:
void CZhbDoc::OnFileOpen()
{
// TODO: Add your command handler code here
LPCTSTR lpszFilter="BMP Files(*.bmp)|*.bmp|任何文件|*.*||";
CFileDialog dlg(TRUE,lpszFilter,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,lpszFilter,NULL);
CString filepath;
CFile file;
//打开文件对话框
if(dlg.DoModal()==IDOK)
{
filepath=dlg.GetPathName();
if(file.Open(filepath,CFile::modeRead|CFile::shareDenyNone,NULL)==0)
{
//读取文件失败
AfxMessageBox("无法打开文件!",MB_OK,0);
return;
}
//读取文件头
file.Read(&bf,sizeof(bf));
//判定是否是BMP文件
if(bf.bfType!=0x4d42)//'BM'
{
AfxMessageBox("非BMP文件!",MB_OK,0);
return;
}
//判定文件是否损坏
if(file.GetLength()!=bf.bfSize)
{
AfxMessageBox("文件已损坏,请检验!",MB_OK,0);
return;
}
//读文件信息头
file.Read(&bi,sizeof(bi));
//计算调色板数目
numquad=0;
if(bi.biBitCount<24)
{
numquad=1<<bi.biBitCount;
}
//为图像信息pbi申请空间
pbi=(BITMAPINFO*)HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+numquad*sizeof(RGBQUAD));
memcpy(pbi,&bi,sizeof(bi));
quad=(RGBQUAD*)((BYTE*)pbi+sizeof(BITMAPINFOHEADER));
//读取调色板
if(numquad!=0)
{
file.Read(quad,sizeof(RGBQUAD)*numquad);
}
//为图像数据申请空间
bi.biSizeImage=bf.bfSize-bf.bfOffBits;
lpbuf=(BYTE*)HeapAlloc(GetProcessHeap(),0,bi.biSizeImage);
//读取图像数据
file.Read(lpbuf,bi.biSizeImage);
//图像读取完成,关闭文件,设置标志
file.Close();
flagOpen=1;
}
}
4. 在C_Veiw类中增加paint消息处理函数;
a. 以下图:
点击“add handler”,然后再点“edit existing”
c. 在处理函数里编写以下代码:
void CZhbView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
CZhbDoc* pDoc = GetDocument(); //得到文档指针,注意,文档命名是和工程名相关!!不一样程序不一样.
ASSERT_VALID(pDoc);
//是否已打开某个BMP文件
if(pDoc->flagOpen==1)
{
//这个函数显示DIB
SetDIBitsToDevice(dc.m_hDC, //DIB将输出设备描述表
0, //设备描述表中位图输出起始逻辑x地址
0, //设备描述表中位图输出起始逻辑x地址
pDoc->bi.biWidth, //DIB宽度
pDoc->bi.biHeight, //DIB高度
0, //DIB开始读取输出像素数据x位置
0, //DIB开始读取输出像素数据y位置
0, //DIB中像素水平行号,它对应lpBits内存缓冲区第一行数据
pDoc->bi.biHeight, //DIB行数,对应包含在由lpBits所指内存缓冲区中数据
pDoc->lpbuf, //包含像素数据内存缓冲区指针
pDoc->pbi, //指向初始化了BITMAPINFO数据结构指针,描述了位图大小和色彩数据
DIB_RGB_COLORS); //指定是显示颜色
}
Invalidate(FALSE);
// Do not call CView::OnPaint() for painting messages
}
保留一幅图片
1.修改”另存为”菜单项响应函数;
a找到菜单资源
b在”另存为”菜单项建立类向导,页面设置以下:
选择“Add function”,然后单击“Edit Code”
代码以下:
void CZhbDoc::OnFileSaveAs()
{
LPCTSTR lpszFilter="BMP Files(*.bmp)|*.bmp|任何文件|*.*||";
CFileDialog dlg(FALSE,lpszFilter,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,lpszFilter,NULL);
if (dlg.DoModal()!=IDOK)
return;
CFile file;
CFileException fe;
if (!file.Open(dlg.GetPathName(), CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive, &fe))
{
// 失败
ReportSaveLoadException(dlg.GetPathName(), &fe, TRUE, AFX_IDP_INVALID_FILENAME);
return;
}
file.SeekToBegin();
file.Write(&bf,sizeof(bf));
file.Write(&bi,sizeof(bi));
if(numquad!=0)
{
file.Write(quad,sizeof(RGBQUAD)*numquad);
}
file.WriteHuge(lpbuf,bi.biSizeImage);
file.Close();
}
展开阅读全文