之前,失败了无数次,把我给整疯了,这次终于成功了!
现在将搭建的方法发到博客上。
最终解决的途径
跳出思维局限,不要拘泥于某一个版本,比如vs2019或者vs2017,说不定vs2015就可以呢?
这次vs2015就成功了!
首先安装vs2015社区版
下载的时候记得勾选Visual C++
现在开始搭建框架
新建MFC应用程序
应用程序类型设置
把文件DIb.h和Dib.cpp拷贝到项目文件夹下
把dib.h添加到项目的“解决方案”下的“头文件”
把dib.cpp文件添加到项目的“解决方案”下的“源文件”
修改代码部分
重要提示:
每一个类都有一个头文件(.h)和源文件(.cpp)
一定要看清楚,不要加错了
----------------------------------Doc.h--------------------------------------------
修改一
找到 #pragma once
在下面添加
#include "Dib.h"
修改二
找到特性和操作,直接替换
// 特性 public: CDib m_dib; // 操作 public: HGLOBAL GetHObject() const //获取Dib对象的句柄 { return m_hDIB; } CPalette* GetDocPal() const //获取调色板指针 { return m_palDIB; } CSize GetDocDimension() const//获取调色板大小 { return m_sizeDoc; } void UpdateObject(HGLOBAL hDIB);//更新dib对象
修改三
找到实现
// 实现 public: void SetDib(); //初始化dib对象
protected: HGLOBAL m_hDIB; CPalette* m_palDIB; CSize m_sizeDoc;
-----------------------doc类重写函数(打开、保存文件)的添加----------------------------
类视图,打开属性
在此添加Open、Save函数(不可手动复制添加)
-------------------------------------Doc.cpp-----------------------------------------
找到构造函数
// TODO: 在此添加一次性构造代码 m_hDIB = NULL;// 初始化变量 m_palDIB = NULL; m_sizeDoc = CSize(1,1);
找到析构函数
if (m_hDIB != NULL)// 判断是否有DIB对象 { ::GlobalFree((HGLOBAL) m_hDIB); } if (m_palDIB != NULL)// 判断调色板是否存在 { delete m_palDIB; }
找到OnOpenDocument函数
if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE; // TODO: 在此添加您专用的创建代码 CFile file; if (!file.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite))// 打开文件 { return FALSE;// 返回FALSE } DeleteContents(); m_hDIB=m_dib.LoadFile(file); if(m_hDIB==NULL)// 调用LoadFile()读取图象 { return FALSE; } SetDib();// 初始化DIB if (m_hDIB == NULL) // 判断读取文件是否成功 { AfxMessageBox(L"读取图像时出错");// 提示出错 return FALSE;// 返回FALSE } SetPathName(lpszPathName);// 设置文件名称 SetModifiedFlag(FALSE);// 初始化修改标记为FALSE return TRUE;// 返回TRUE
找到OnSaveDocument函数
// TODO: 在此添加专用代码和/或调用基类 CFile file; if(!file.Open(lpszPathName, CFile::modeCreate |// 打开文件 CFile::modeReadWrite | CFile::shareExclusive)) { return FALSE;// 返回FALSE } BOOL bSuccess = FALSE; bSuccess = m_dib.SaveFile(m_hDIB, file); // 保存图象 file.Close();// 关闭文件 SetModifiedFlag(FALSE);// 重置脏标记为FALSE if (!bSuccess) { AfxMessageBox(L"保存BMP图象时出错");// 提示出错 } return bSuccess; //return CDocument::OnSaveDocument(lpszPathName);
现在检查Doc类是否已经存在SetDib函数和UpdateObject函数
若不存在,则手动添加,随后粘贴代码
若存在,直接复制粘贴如下代码到Doc.cpp文件中,并修改类名部分
类名根据项目名称的不同而不同
void C********Doc::SetDib() //这个函数需要手动添加,前面的类名要与项目一致 { LPSTR lpdib = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB); if (m_dib.GetWidth(lpdib) > INT_MAX ||m_dib.GetHeight(lpdib) > INT_MAX)// 判断图象是否过大 { ::GlobalUnlock((HGLOBAL) m_hDIB); ::GlobalFree((HGLOBAL) m_hDIB); // 释放DIB对象 m_hDIB = NULL;// 设置DIB为空 AfxMessageBox(L"初始化失败"); return; } m_sizeDoc = CSize((int)m_dib.GetWidth(lpdib), (int)m_dib.GetHeight(lpdib));// 设置文档大小 ::GlobalUnlock((HGLOBAL) m_hDIB); m_palDIB = new CPalette;// 创建新调色板 if (m_palDIB == NULL)// 判断是否创建成功 { ::GlobalFree((HGLOBAL) m_hDIB); // 失败 m_hDIB = NULL;// 设置DIB对象为空 return; } // 调用CreateDIBPalette来创建调色板 if (m_dib.ConstructPalette(m_hDIB, m_palDIB) == NULL) { delete m_palDIB;// 删除 m_palDIB = NULL;// 设置为空 return;// 返回空 } }
void C********Doc::UpdateObject(HGLOBAL hDIB) //这个函数需要手动添加,类名要修改 { if (m_hDIB != NULL) // 判断DIB是否为空 { ::GlobalFree((HGLOBAL) m_hDIB);// 非空,则清除 } m_hDIB = hDIB; // 替换成新的DIB对象 }
---------------------------View.cpp----------------------------
找到OnDraw函数
看到这里
删去注释,解除封印
看到这一行,在下面添加代码
// TODO: 在此处为本机数据添加绘制代码 HGLOBAL hDIB = pDoc->GetHObject(); // 判断DIB是否为空 if (hDIB != NULL) { LPSTR lpDibSection = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); // 获取DIB宽度 int cxDIB = (int) pDoc->m_dib.GetWidth(lpDibSection); // 获取DIB高度 int cyDIB = (int) pDoc->m_dib.GetHeight(lpDibSection); ::GlobalUnlock((HGLOBAL) hDIB); CRect rcDIB; rcDIB.top = rcDIB.left = 0; rcDIB.right = cxDIB; rcDIB.bottom = cyDIB; CRect rcDest= rcDIB; // 输出DIB pDoc->m_dib.DrawDib(pDC->m_hDC, &rcDest, pDoc->GetHObject(), &rcDIB, pDoc->GetDocPal()); }
在确保项目文件夹下已有“stdafx.h”“stdafx.cpp存在时,编译执行
效果