前言

  前些天应好友之拖,帮忙设计一个简单的图像处理的小软件。朋友把核心算法封装好了,但是是用openCV类似于console的编程环境,要我在此基础上改成MFC桌面程序。下图是做成之后的效果:

  我是两年前稍微学了点MFC的知识,这两年中基本没有涉及,因为诸多相同的需求都可以用C#来搞定。这个本来也是想用C#来弄,可是我朋友用了openCV的相关函数封装了核心的“美颜算法”,我就只好重温经典了!

本文只涉及开发该小软件中与MFC控件相关的操作技巧,不提供朋友的“美颜算法”,还请各位见谅!

工程中技术点小结

1、打开与保存文件:

 void CDonutDlg::OnBnClickedButtonRead()
{
BOOL isOpen = TRUE; //是否打开(否则为保存)
CString defaultDir = "E:\\FileTest"; //默认打开的文件路径
CString fileName = ""; //默认打开的文件名
CString filter = "文件 (*.png; *.jpg; *.bmp)|*.png;*.jpg;*.bmp||"; //文件过虑的类型
CFileDialog openFileDlg(isOpen, defaultDir, fileName, OFN_HIDEREADONLY | OFN_READONLY, filter, NULL);
openFileDlg.GetOFN().lpstrInitialDir = "E:\\FileTest\\donut.jpg";
INT_PTR result = openFileDlg.DoModal();
CString filePath = defaultDir + "\\donut.jpg";
if (result == IDOK) {
filePath = openFileDlg.GetPathName();
LoadPicture(filePath);//加载图片保存在全局变量m_image中
UpdatePicture();//显示图片
}
//CWnd::SetDlgItemTextW(IDC_EDIT_SRC, filePath);
// TODO: 在此添加控件通知处理程序代码
}
 void CDonutDlg::OnBnClickedButtonSave()
{
BOOL isOpen = FALSE; //是否打开(否则为保存)
CString defaultDir = "E:\\FileTest"; //默认打开的文件路径
CString fileName = "donut.jpg"; //默认打开的文件名
CString filter = "文件 (*.png; *.jpg; *.bmp)|*.png;*.jpg;*.bmp||"; //文件过虑的类型
CFileDialog openFileDlg(isOpen, defaultDir, fileName, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, filter, NULL);
openFileDlg.GetOFN().lpstrInitialDir = "E:\\FileTest\\donut.jpg";
INT_PTR result = openFileDlg.DoModal();
CString filePath = defaultDir + "\\" + fileName;
if (result == IDOK) {
filePath = openFileDlg.GetPathName();
SavePicture(filePath);
}
//CWnd::SetDlgItemTextW(IDC_EDIT_DEST, filePath);
// TODO: 在此添加控件通知处理程序代码
}

2、滚动条和文本显示:

  • 一共有6个slider监听,每次slider滑动就会触发该函数,在该函数内获取slider当前位置,然后通过映射公式得到文本框内该显示的数据
 void CDonutDlg::OnNMCustomdrawSliderSmooth(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
int nPos = m_SliderSmooth.GetPos(); //获得滑块的当前位置
//另外做一个编辑框 显示所调节的数据;
CString str = ""; m_SliderSmoothValue = ;//1-31整数
m_SliderSmoothValue = (int)floor(nPos / 6.25) * + ;
if (m_SliderSmoothValue == )m_SliderSmoothValue = ;
str.Format("%2d", m_SliderSmoothValue);
SetDlgItemText(IDC_EDIT_SMOOTH, str);
*pResult = ;
}
  • 但是如果想在鼠标抬起后更新图片就要用下面的监听事件了:
 void CDonutDlg::OnNMReleasedcaptureSliderSmooth(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: 在此添加控件通知处理程序代码
UpdatePicture();
*pResult = ;
}

3、更新状态——刷新图片(将openCV格式转换为MFC能显示格式)+ ListBox显示处理信息 + CHECK_BUTTON基本用法

 #include "CvvImage.h"
void CDonutDlg::UpdatePicture()
{
double t = ;
CString str; if (fb.setImage(m_SourceImage) == false)//这个一定要
{
return;
} //6个参数在全局定义DonutDlg.h中
//在DonutDlg的构造函数中初始化
//int m_SliderSmoothValue;//1-31整数
//double m_SliderEyeSizeValue;//0.8-1
//double m_SliderSharpenValue;//0-2
//double m_SliderRValue;//0.5-1.5
//double m_SliderGValue;//0.5-1.5
//double m_SliderBValue;//0.5-1.5
t = (double)cvGetTickCount();//用来计算算法执行时间 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
m_image = fb.getResult(); t = (double)cvGetTickCount() - t;//相减为算法执行的时间
str.Format("%lf", t/((double)cvGetTickFrequency()*));
m_ListBox.InsertString(m_ListBox.GetCount(), "美颜时间...");
m_ListBox.InsertString(m_ListBox.GetCount(), str); CDC* pDC = GetDlgItem(IDC_STATIC_PIC)->GetDC();
HDC hDC = pDC->GetSafeHdc();
IplImage img = m_image;
CvvImage cimg;
cimg.CopyOf(&img);//上面几步是将Mat转换为CvvImage,但是opencv2无CvvImage需要从网上下载CvvImage源码加入工程
CRect rect; CStatic* pStatic = (CStatic*)GetDlgItem(IDC_STATIC_PIC);
pStatic->GetClientRect(&rect);
pStatic->GetDC()->FillSolidRect(rect.left, rect.top, rect.Width(), rect.Height(), RGB(, , ));//刷一张背景(否则每次会出现重叠现象) if (BST_UNCHECKED == ((CButton*)GetDlgItem(IDC_CHECK_FILL))->GetCheck())
{
if ((rect.Height()*1.0 / rect.Width() - m_image.rows*1.0 / m_image.cols)>)
{
double new_width = rect.Width();
double new_height = rect.Height()*1.0*m_image.rows / m_image.cols;
double extern_height = (rect.Height() - new_height) / ;//为了居中,整个左上角的贴图向下平移的距离
rect.SetRect(, extern_height, new_width, extern_height + new_height);//cols列--高,cows行--宽
}
else
{
double new_width = rect.Width()*1.0*m_image.cols / m_image.rows;
double new_height = rect.Height();
double extern_width = (rect.Width() - new_width) / ;
rect.SetRect(extern_width, , new_width + extern_width, new_height);
}
}
cimg.DrawToHDC(hDC, &rect);
ReleaseDC(pDC); #ifdef SHOW_IMAGE
if (BST_CHECKED == ((CButton*)GetDlgItem(IDC_CHECK_SHOW_CONSOLE))->GetCheck())
{
do{
namedWindow("show the source imag!");
imshow("show the source imag!", m_image);
} while ();
}
#endif
}

小结

  现在总结一遍才发现这个东西这么简单,我当时竟然花了2夜+1天!看样子还是要多多总结,特别像MFC这种小知识点特别多,不要因为其简单就不总结,也许多年以后你要用到,还得再重新趟一遍坑就浪费时间了!http://pan.baidu.com/s/1pJ5W6CV(私有)

@beautifulzzzz

  2015-10-31 持续更新中~

 

[MFC] 梳理一个简单的图片处理桌面软件中用到的MFC控件技巧的更多相关文章

  1. Expression Blend4经验分享:制作一个简单的图片按钮样式

    这次分享如何做一个简单的图片按钮经验 在我的个人Silverlight网页上,有个Iphone手机的效果,其中用到大量的图片按钮 http://raimon.6.gwidc.com/Iphone/de ...

  2. 通过MFC设计一个简单的计价程序

    1.实验目的 掌握使用MFC应用程序向导创建应用程序的方法. 掌握新建对话框资源的方法. 掌握生成对话框的方法. 2.实验内容 用应用程序创建一个默认的对话框应用程序,在对话框中能进入下一个对话框,在 ...

  3. Android一个炫酷的树状图组织架构图开源控件实现过程

    Android一个炫酷的树状图组织架构图开源控件 文章目录 [1 简介] [2 效果展示] [3 使用步骤] [4 实现基本布局流程] [5 实现自由放缩及拖动] [6 实现添加删除及节点动画] [7 ...

  4. Objective-C ,ios,iphone开发基础:快速实现一个简单的图片查看器

    新建一个single view 工程: 关闭ARC , 在.xib视图文件上拖放一个UIImageView  两个UIButton ,一个UISlider ,布局如图. 并为他们连线, UIImage ...

  5. 用MFC完成一个简单的猜数字游戏: 输入的四位数中,位置和数字都正确为A,数字相同而位置不同的为B。

    最近学习了MFC一些比较基础的知识,所以打算通过做一个简单的数字游戏来理解MFC的流程并进一步熟悉其操作. 在这里,我做了一个猜数字的小游戏.第一步当然是设计主界面,先给大家展示一下游戏界面: 主界面 ...

  6. 基于MFC的一个简单计算器

    写一个简单的计算器并不是什么很难的事,主要目的是要通过这个程序来学习和分析其中的核心算法.这个简易计算器的核心部分就是对输入的表达式的正确性判断与求值,其中包括对表达式的解析.中缀表达式转后缀表达式. ...

  7. 用Vue实现一个简单的图片轮播

    本文已收录至https://github.com/likekk/studyBlog欢迎大家star,共同学习,共同进步.如果文章有错误的地方,欢迎大家指出.后期将在将GitHub上规划前端学习的路线和 ...

  8. 一起撸个简单粗暴的Tv应用主界面的网格布局控件(上)

    这一篇是真的隔了好久了~~,也终于可以喘口气来好好写博客了,这段时间实在是忙不过来了,迭代太紧.好,废话不多说,进入今天的主题. 效果 图一是Tv应用:当贝市场的主页 图二是咱自己撸的简单粗暴的 Tv ...

  9. VS2010/MFC编程入门之五十四(Ribbon界面开发:使用更多控件并为控件添加消息处理函数)

    上一节中鸡啄米讲了为Ribbon Bar添加控件的方法.本节教程鸡啄米将继续完善前面的实例,讲解一些稍复杂的控件的添加方法,及如何为它们添加消息处理函数. 一.为Ribbon Bar添加更多Ribbo ...

随机推荐

  1. .Net WinForm下配置Log4Net(总结不输出原因)

    最近做一个winform项目,配置了Log4net 但是总是不能输出,搜索了很多文章加上自己的探索发现自己在项目中添加的 Log4Net.config 生成时没有被复制到Debug文件夹下, 所以程序 ...

  2. flex中通过代码获取supermap的token

    最近工作中需要使用代码来获取supermap服务启动安全访问限制以后的token值,经过一番尝试,最终成功获取到,记录下里,以供翻阅 //get token public function getTo ...

  3. 高流量站点NGINX与PHP-fpm配置优化(译)

    使用Nginx搭配PHP已有7年的这份经历让我们学会如何为高流量站点优化NGINX和PHP-fpm配置. 以下正是这方面的一些提示和建议: 1. 将TCP切换为UNIX域套接字 UNIX域套接字相比T ...

  4. curl+openssl编译

    curl不支持openssl的静态库,所以编译openssl的时候,应该加上shared 参数,记录一下我亲手编译的参数: ./configure --prefix=/usr/local/openss ...

  5. 【日常小问题】windows系统操作技巧

    如何将文件夹视图设置为“详细信息” @2015.3.30 这段时间刚换了电脑,资源管理器视图模式为“大图标”,很不符合俺的操作习惯.修改之—— 1.打开一个文件夹,设置为详细信息显示. 2.点击工具- ...

  6. 如何在SCENEKIT使用SWIFT RUNTIME动态加载COLLADA文件

    问题:今天接到一个项目,负责弄需求的美眉跟我讲能不能做一个原型能够加载Collada文件,流程如下: 用户用app下载Collada 压缩包(如内购项目) 压缩包解压 展示Collada文件里的内容 ...

  7. 《转》python线程池

    线程池的概念是什么? 在IBM文档库中这样的一段描写:“在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是 如此,虚拟机将试图跟踪每一个对象 ...

  8. <Data Structure and Algorithm>排序算法

    排序稳定:如果两个数相同,对他们进行的排序结果为他们的相对顺序不变.例如A={1,2,1,2,1}这里排序之后是A = {1,1,1,2,2} 稳定就是排序后第一个1就是排序前的第一个1,第二个1就是 ...

  9. webform 中使用ajax

    常用的方式有 js –> WebService  , js->*.ashx, js->WebAPI, js->MVC Controller->Action. 前两种就不说 ...

  10. 将图片压缩后转Base64函数

    function CutImgToBase(fn: string): string; // 压缩图片只能压缩bmp:将jpg转换成bmp再压缩 var m1: TMemoryStream; m2: T ...