[MFC] 梳理一个简单的图片处理桌面软件中用到的MFC控件技巧

简介:


 

 前言 

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

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

 

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

 

工程中技术点小结

1、打开与保存文件:

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

 

2、滚动条和文本显示: 

  • 一共有6个slider监听,每次slider滑动就会触发该函数,在该函数内获取slider当前位置,然后通过映射公式得到文本框内该显示的数据
复制代码
 1 void CDonutDlg::OnNMCustomdrawSliderSmooth(NMHDR *pNMHDR, LRESULT *pResult)
 2 {
 3     LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
 4     // TODO:  在此添加控件通知处理程序代码
 5     int nPos = m_SliderSmooth.GetPos(); //获得滑块的当前位置
 6     //另外做一个编辑框 显示所调节的数据;
 7     CString str = ""; m_SliderSmoothValue = 1;//1-31整数
 8     m_SliderSmoothValue = (int)floor(nPos / 6.25) * 2 + 1;
 9     if (m_SliderSmoothValue == 33)m_SliderSmoothValue = 31;
10     str.Format("%2d", m_SliderSmoothValue);
11     SetDlgItemText(IDC_EDIT_SMOOTH, str);
12     *pResult = 0;
13 }
复制代码

 

  • 但是如果想在鼠标抬起后更新图片就要用下面的监听事件了:
1 void CDonutDlg::OnNMReleasedcaptureSliderSmooth(NMHDR *pNMHDR, LRESULT *pResult)
2 {
3     // TODO:  在此添加控件通知处理程序代码
4     UpdatePicture();
5     *pResult = 0;
6 }

 

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

复制代码
 1 #include "CvvImage.h"
 2 void CDonutDlg::UpdatePicture()
 3 {
 4     double t = 0;
 5     CString str;
 6 
 7     if (fb.setImage(m_SourceImage) == false)//这个一定要
 8     {
 9         return;
10     }
11 
12     //6个参数在全局定义DonutDlg.h中
13     //在DonutDlg的构造函数中初始化
14     //int m_SliderSmoothValue;//1-31整数
15     //double m_SliderEyeSizeValue;//0.8-1
16     //double m_SliderSharpenValue;//0-2
17     //double m_SliderRValue;//0.5-1.5
18     //double m_SliderGValue;//0.5-1.5
19     //double m_SliderBValue;//0.5-1.5
20     t = (double)cvGetTickCount();//用来计算算法执行时间
21 
22     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;  
23     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;  
24     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
25     m_image = fb.getResult();
26 
27     t = (double)cvGetTickCount() - t;//相减为算法执行的时间
28     str.Format("%lf", t/((double)cvGetTickFrequency()*1000));
29     m_ListBox.InsertString(m_ListBox.GetCount(), "美颜时间...");
30     m_ListBox.InsertString(m_ListBox.GetCount(), str);
31 
32 
33     CDC* pDC = GetDlgItem(IDC_STATIC_PIC)->GetDC();
34     HDC hDC = pDC->GetSafeHdc();
35     IplImage img = m_image;
36     CvvImage cimg;
37     cimg.CopyOf(&img);//上面几步是将Mat转换为CvvImage,但是opencv2无CvvImage需要从网上下载CvvImage源码加入工程
38     CRect rect;
39 
40     CStatic* pStatic = (CStatic*)GetDlgItem(IDC_STATIC_PIC);
41     pStatic->GetClientRect(&rect);
42     pStatic->GetDC()->FillSolidRect(rect.left, rect.top, rect.Width(), rect.Height(), RGB(192, 192, 192));//刷一张背景(否则每次会出现重叠现象)
43 
44 
45     if (BST_UNCHECKED == ((CButton*)GetDlgItem(IDC_CHECK_FILL))->GetCheck())
46     {
47         if ((rect.Height()*1.0 / rect.Width() - m_image.rows*1.0 / m_image.cols)>0)
48         {
49             double new_width = rect.Width();
50             double new_height = rect.Height()*1.0*m_image.rows / m_image.cols;
51             double extern_height = (rect.Height() - new_height) / 2;//为了居中,整个左上角的贴图向下平移的距离
52             rect.SetRect(0, extern_height, new_width, extern_height + new_height);//cols列--高,cows行--宽
53         }
54         else
55         {
56             double new_width = rect.Width()*1.0*m_image.cols / m_image.rows;
57             double new_height = rect.Height();
58             double extern_width = (rect.Width() - new_width) / 2;
59             rect.SetRect(extern_width, 0, new_width + extern_width, new_height);
60         }
61     }
62     cimg.DrawToHDC(hDC, &rect);
63     ReleaseDC(pDC);
64 
65 #ifdef SHOW_IMAGE
66     if (BST_CHECKED == ((CButton*)GetDlgItem(IDC_CHECK_SHOW_CONSOLE))->GetCheck())
67     {
68         do{
69             namedWindow("show the source imag!");
70             imshow("show the source imag!", m_image);
71         } while (0);
72     }
73 #endif
74 }
复制代码

 

小结

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

 

@beautifulzzzz

  2015-10-31 持续更新中~



本文转自beautifulzzzz博客园博客,原文链接:http://www.cnblogs.com/zjutlitao/p/4926399.html,如需转载请自行联系原作者

相关文章
|
6月前
|
C++
基于Qt的简易音乐播放器设计与实现
基于Qt的简易音乐播放器设计与实现
244 0
|
6月前
MFC对话框构架程序
MFC对话框构架程序
33 0
|
Windows
QT桌面项目(第一个应用程序 桌面壁纸软件)
QT桌面项目(第一个应用程序 桌面壁纸软件)
102 0
|
程序员
MFC应用程序开发教程2——基于对话框编程
MFC应用程序开发教程2——基于对话框编程
161 1
MFC应用程序开发教程2——基于对话框编程
Revit 二次开发添加WPF窗口的办法
Revit 二次开发添加WPF窗口的办法
Revit 二次开发添加WPF窗口的办法
|
程序员 API 开发工具
MFC应用程序开发教程1
MFC应用程序开发教程1
227 0
MFC应用程序开发教程1
Qt开发Activex笔记(三):C#调用Qt开发的Activex控件
Qt开发Activex笔记(三):C#调用Qt开发的Activex控件
Qt开发Activex笔记(三):C#调用Qt开发的Activex控件
|
编解码 Windows
Qt疑难杂症:无法QVideoWidget播放器上浮控件
Qt疑难杂症:无法QVideoWidget播放器上浮控件
Qt疑难杂症:无法QVideoWidget播放器上浮控件
|
编译器 C语言 异构计算
QT软件开发:基于QtAV设计的视频播放器
QT软件开发:基于QtAV设计的视频播放器
654 0
QT软件开发:基于QtAV设计的视频播放器
|
测试技术
艾伟:WinForm控件开发总结(二)------使用和调试自定义控件
在上一篇文章里我们创建了一个简单的控件FirstControl,现在我来介绍一下怎么使用和调试自己的控件。我希望将过程写的尽可能的详细,让想学习控件开发的朋友容易上手,高手们见谅。       在同一个solution里添加一个Windows Application工程(在Solution Explorer里右键点击CustomControlSample solution选择Add->New Project…),命名为TestControl。
892 0