• [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 持续更新中~

     

  • 相关阅读:
    MT【305】丹德林双球
    MT【304】反射路径长度比
    MT【303】估计
    MT【302】利用值域宽度求范围
    MT【301】值域宽度
    MT【300】余弦的三倍角公式
    MT【299】对数型数列不等式
    MT【298】双参数非齐次
    xadmin 自定义actions
    xadmin 添加自定义权限
  • 原文地址:https://www.cnblogs.com/zjutlitao/p/4926399.html
Copyright © 2020-2023  润新知