该软件之所以叫完美图片批处理器,是因为C++技术网在推出一系列零基础入门教程的同时还会进行一系列项目的开发,目前已完成的有《小熊文件名批处理器》、《完美图片批处理器1.1版》,已启动的有完美记事项目,开发这些软件不仅能够用于日常的生活工作中,而且能够让初学者边学习边开发,提高实际动手能力,熟悉项目开发流程,在实际操作中增加成就感,进一步促进学习效果。软件界面如下:
下面对完美图片批处理器1.1版开发中的一些知识点进行总结,供大家参考,若有不当之处,请在文章留言处批评指正。整个思路是:将选择的图片的路径、文件名保存到CString容器中,然后依次进行处理、保存。
一、成员变量如下:
CString m_PicturePathName;// - 图片路径
CString m_PictureFolder;// - 图片文件夹路径
CString m_PictureTitle;// - 文件名,不包含扩展名
CString m_DestPicturePathName;// - 输出文件完整路径名
CFont m_fontTitle;// - 标题字体
CFont m_fontTips;// - 提示字体
int m_iWidthMax;// - 最大宽度输入数值
int m_iWidth;// - 宽度输入数值
int m_iHigh;// - 高度输入数值
BOOL m_mode;// - 处理模式类型
BOOL m_flag;// - 是否完成转换标志
std::vector<CString> m_filePathName;// - 文件完整路径容器
std::vector<CString> m_fileTitle;// - 文件名不包括扩展名容器
std::vector<CString> m_fileExt;// - 文件扩展名容器
二、文件选择对话框处理
首先,在小熊文件名批处理器中,采用的是文件夹对话框,单击浏览后选择某个文件夹,然后对整个文件夹下面的所有文件进行遍历、处理。而在该项目中我想到有时候我们还是会处理某一张或者是选定的几张图片,因此用文件夹对话框的话就显得不是很灵活,而文件对话框能够多选的属性刚好能满足要求,能多能少。文件选择对话框,大家应该都很熟悉,单击浏览按钮弹出一个选择文件的对话框,即: CFileDialog fpd(TRUE);
fpd.DoModal();
简单两句代码就可以弹出对话框了,但是此时的对话框不具有多选属性,还需要对其参数做一些设置。MSDN中说明如下:To enable the user to select multiple files, set the OFN_ALLOWMULTISELECT flag before you call DoModal. You must supply your own file name buffer to store the returned list of multiple file names. Do this by replacing m_ofn.lpstrFile with a pointer to a buffer you have allocated, after you construct the CFileDialog, but before you call DoModal. Additionally, you must set m_ofn.nMaxFile with the number of characters in the buffer pointed to by m_ofn.lpstrFile. If you set the maximum number of files to be selected to n, the necessary buffer size is n*(_MAX_PATH + 1) + 1.
想必大家都能看懂,我也就不逐字逐句翻译了,其实就是:设置OFN_ALLOWMULTISELECT标志;然后重新定义一个缓冲区,并用一个指向该缓冲区的指针替换m_ofn.lpstrFile,假设你支持选择的文件数目最大为n,那么缓冲区大小为n*(_MAX_PATH + 1) + 1,最后设置m_ofn.nMaxFile为n*(_MAX_PATH + 1) + 1。
#define MIN_FILE_NUMBER 50 //至少允许选择50个文件
#define FILE_BUFFER_SIZE ((_MAX_PATH+1)*MIN_FILE_NUMBER+1)//缓冲区大小
fpd.m_ofn.Flags |= OFN_ALLOWMULTISELECT;//支持多个文件选择标志
fpd.m_ofn.lpstrTitle = L"请选择图片";
fpd.m_ofn.lpstrFilter = L"JPEG(*.jpg;*.jpeg)\0*.jpg;*.jpeg\0ALL Files(*.*)\0*.*\0\0";//文件选择格式过滤
fpd.m_ofn.lpstrFile = new TCHAR[FILE_BUFFER_SIZE];//重新定义缓冲区大小
memset(fpd.m_ofn.lpstrFile, 0, FILE_BUFFER_SIZE);//初始化定义的缓冲区
fpd.m_ofn.nMaxFile = FILE_BUFFER_SIZE;
然后就是将选择的文件路径进行存储,在后面依次处理:
POSITION pos = fpd.GetStartPosition();//获取第一个文件的位置
while (NULL != pos)
{
PicturePathName = fpd.GetNextPathName(pos);//图片完整路径名
......
}
三、图片处理
int curWidth, curHigh, oriWidth, oriHigh;//当前宽高,原始宽高
int fileNum = m_filePathName.size();//用户选择的文件数目
for (int i = 0; i < fileNum; i++)
{
CImage imSrc, imDest;//原始图片对象和目标图片对象
imSrc.Load(m_filePathName[i]);//加载图片到图片对象中
oriWidth = imSrc.GetWidth();//获取原始图像宽度
oriHigh = imSrc.GetHeight();//获取原始图像高度
if (m_mode == TRUE)//最大宽度模式下宽高计算设置
{
UpdateData(TRUE);
curWidth = m_iWidthMax;
curHigh = (int)(curWidth*oriHigh / oriWidth + 0.5);//按比例缩小或放大并四舍五入
}
imDest.Create(curWidth, curHigh, 32);//创建新图片
HDC imDestDC;
imDestDC = imDest.GetDC();
SetStretchBltMode(imDestDC, HALFTONE);//设置位图拉伸模式
SetBrushOrgEx(imDestDC, 0, 0, NULL);//设置刷子起始点,此2句能够消除失真,获得高质量图像
imSrc.StretchBlt(imDestDC, 0, 0, curWidth, curHigh);//进行拉伸
imDest.ReleaseDC();
m_PictureTitle.Format(L"%s_%d×%d.", m_fileTitle[i], curWidth, curHigh);
m_DestPicturePathName = m_PictureFolder + m_PictureTitle + m_fileExt[i];
imDest.Save(m_DestPicturePathName);//保存图片
imSrc.Destroy();//销毁图片对象
imDest.Destroy();
}
这就是图片处理的核心代码,并不难理解。
四、开发中应该注意的细节问题
1.软件属性中详细信息设置,效果如下:
2.“关于系统菜单”的设置
这个设置在“资源视图”-->“String Table”选项中,如下:
3. “关于对话框”的设置
需要将标题和内容进行适当的修改。
4.禁用窗口最大化按钮以及窗口不可变大小设置
该项目涉及的主要知识点如上所述,后面会将项目源代码共享出来,有兴趣的可以再进行验证一下,如有问题,欢迎指出。