MFC OpenCV:鼠标滚轮缩放图片

电玩女神 2022-02-01 12:47 806阅读 0赞

MFC OpenCV:鼠标滚轮缩放图片

    • 一、背景
    • 二、实现步骤
    • 三、全部代码
    • 四、注意

一、背景

  前置文章:MFC显示OpenCV图片的三种详细方法
  在利用OpenCV嵌套MFC窗口显示图片后,希望通过鼠标滚轮函数缩放图片。

二、实现步骤

1、新建MFC应用程序。
在这里插入图片描述
2、配置OpenCV运行环境。
在这里插入图片描述
3、添加MFC的Pictrue Control控件
在这里插入图片描述
4、编写代码。只需修改MFCApplication1Dlg.cpp文件。
在这里插入图片描述
添加的代码:

  1. //在MFCApplication1Dlg.cpp添加库文件
  2. #include "opencv2/opencv.hpp"
  3. using namespace cv;
  4. //在MFCApplication1Dlg.cpp添加全局变量
  5. double g_iZoom = 1;//初始缩放值
  6. double g_iRadio = 0.1;//缩放步距
  7. Mat g_matOriginal;//原始图片
  8. //在MFCApplication1Dlg.cpp的CMFCApplication1Dlg::OnInitDialog()函数中添加如下代码:
  9. namedWindow("ImageShow");//创建OpenCV窗口
  10. HWND hWnd = (HWND)cvGetWindowHandle("ImageShow");//嵌套opencv窗口
  11. HWND hParent = ::GetParent(hWnd);
  12. ::SetParent(hWnd, GetDlgItem(IDC_STATIC)->m_hWnd);
  13. ::ShowWindow(hParent, SW_HIDE);
  14. g_iZoom = 1;//初始缩放值为1,表示原图
  15. g_matOriginal = imread("E:\\vs\\image\\11.png");//opencv读取图片
  16. imshow("ImageShow", g_matOriginal);//opencv显示图片
  17. waitKey(1);

5、初步运行结果。到此可以简单显示图片。
在这里插入图片描述
6、右键MFC的Pictrue Control控件,添加MFC的鼠标滚轮函数。
在这里插入图片描述
在这里插入图片描述

  1. BOOL CMFCApplication1Dlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
  2. {
  3. // TODO: 在此添加消息处理程序代码和/或调用默认值
  4. CRect rect;
  5. GetDlgItem(IDC_STATIC)->GetWindowRect(&rect);//获取MFC图像显示区域
  6. Point p(pt.x, pt.y);//opencv鼠标坐标
  7. Rect r(rect.left, rect.top, rect.right, rect.bottom);//opencv窗口显示区域
  8. if (r.contains(p)) //鼠标放在图片窗口上
  9. {
  10. int w = g_matOriginal.cols, h =g_matOriginal.rows;//原图宽高
  11. Mat mat;
  12. if (zDelta > 0)//放大图片
  13. {
  14. double zoom = g_iZoom + g_iRadio;
  15. if (w * zoom * h * zoom < 3000 * 3000)//图片宽高<3000*3000时缩放值才会变大
  16. {
  17. g_iZoom = zoom;
  18. }
  19. resize(g_matOriginal, mat, Size(), g_iZoom, g_iZoom, INTER_LINEAR); //按比例放大图片
  20. }
  21. else if (zDelta < 0)//缩小图片
  22. {
  23. double zoom = g_iZoom - g_iRadio;
  24. if (w * zoom * h * zoom > 100 * 100)//图片宽高>100*100时缩放值才会变小
  25. {
  26. g_iZoom = zoom;
  27. }
  28. resize(g_matOriginal, mat, Size(), g_iZoom, g_iZoom, INTER_AREA); //按比例缩小图片
  29. }
  30. imshow("ImageShow", mat);//显示缩放后图片
  31. waitKey(1);
  32. }
  33. return CDialogEx::OnMouseWheel(nFlags, zDelta, pt);
  34. }

7、缩放图片结果
缩小图片
放大图片

三、全部代码

MFCApplication1Dlg.h

  1. // MFCApplication1Dlg.h: 头文件
  2. //
  3. #pragma once
  4. // CMFCApplication1Dlg 对话框
  5. class CMFCApplication1Dlg : public CDialogEx
  6. {
  7. // 构造
  8. public:
  9. CMFCApplication1Dlg(CWnd* pParent = nullptr); // 标准构造函数
  10. // 对话框数据
  11. #ifdef AFX_DESIGN_TIME
  12. enum { IDD = IDD_MFCAPPLICATION1_DIALOG };
  13. #endif
  14. protected:
  15. virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
  16. // 实现
  17. protected:
  18. HICON m_hIcon;
  19. // 生成的消息映射函数
  20. virtual BOOL OnInitDialog();
  21. afx_msg void OnPaint();
  22. afx_msg HCURSOR OnQueryDragIcon();
  23. DECLARE_MESSAGE_MAP()
  24. public:
  25. afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
  26. };

MFCApplication1Dlg.cpp

  1. // MFCApplication1Dlg.cpp: 实现文件
  2. //
  3. #include "stdafx.h"
  4. #include "MFCApplication1.h"
  5. #include "MFCApplication1Dlg.h"
  6. #include "afxdialogex.h"
  7. #include "opencv2/opencv.hpp"
  8. using namespace cv;
  9. double g_iZoom = 1;//初始缩放值
  10. double g_iRadio = 0.1;//缩放步距
  11. Mat g_matOriginal;//原始图片
  12. //void OpenCVMouse(int event, int x, int y, int flags, void* param);
  13. #ifdef _DEBUG
  14. #define new DEBUG_NEW
  15. #endif
  16. // CMFCApplication1Dlg 对话框
  17. CMFCApplication1Dlg::CMFCApplication1Dlg(CWnd* pParent /*=nullptr*/)
  18. : CDialogEx(IDD_MFCAPPLICATION1_DIALOG, pParent)
  19. {
  20. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  21. }
  22. void CMFCApplication1Dlg::DoDataExchange(CDataExchange* pDX)
  23. {
  24. CDialogEx::DoDataExchange(pDX);
  25. }
  26. BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialogEx)
  27. ON_WM_PAINT()
  28. ON_WM_QUERYDRAGICON()
  29. ON_WM_MOUSEWHEEL()
  30. END_MESSAGE_MAP()
  31. // CMFCApplication1Dlg 消息处理程序
  32. BOOL CMFCApplication1Dlg::OnInitDialog()
  33. {
  34. CDialogEx::OnInitDialog();
  35. // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
  36. // 执行此操作
  37. SetIcon(m_hIcon, TRUE); // 设置大图标
  38. SetIcon(m_hIcon, FALSE); // 设置小图标
  39. namedWindow("ImageShow");//创建OpenCV窗口
  40. HWND hWnd = (HWND)cvGetWindowHandle("ImageShow");//嵌套opencv窗口
  41. HWND hParent = ::GetParent(hWnd);
  42. ::SetParent(hWnd, GetDlgItem(IDC_STATIC)->m_hWnd);
  43. ::ShowWindow(hParent, SW_HIDE);
  44. g_iZoom = 1;//初始缩放值为1,表示原图
  45. //setMouseCallback("ImageShow", OpenCVMouse, NULL); // 鼠标事件
  46. g_matOriginal = imread("E:\\vs\\image\\11.png");//opencv读取图片
  47. imshow("ImageShow", g_matOriginal);//opencv显示图片
  48. waitKey(1);
  49. return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
  50. }
  51. // 如果向对话框添加最小化按钮,则需要下面的代码
  52. // 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
  53. // 这将由框架自动完成。
  54. void CMFCApplication1Dlg::OnPaint()
  55. {
  56. if (IsIconic())
  57. {
  58. CPaintDC dc(this); // 用于绘制的设备上下文
  59. SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  60. // 使图标在工作区矩形中居中
  61. int cxIcon = GetSystemMetrics(SM_CXICON);
  62. int cyIcon = GetSystemMetrics(SM_CYICON);
  63. CRect rect;
  64. GetClientRect(&rect);
  65. int x = (rect.Width() - cxIcon + 1) / 2;
  66. int y = (rect.Height() - cyIcon + 1) / 2;
  67. // 绘制图标
  68. dc.DrawIcon(x, y, m_hIcon);
  69. }
  70. else
  71. {
  72. CDialogEx::OnPaint();
  73. }
  74. }
  75. //当用户拖动最小化窗口时系统调用此函数取得光标
  76. //显示。
  77. HCURSOR CMFCApplication1Dlg::OnQueryDragIcon()
  78. {
  79. return static_cast<HCURSOR>(m_hIcon);
  80. }
  81. BOOL CMFCApplication1Dlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
  82. {
  83. // TODO: 在此添加消息处理程序代码和/或调用默认值
  84. CRect rect;
  85. GetDlgItem(IDC_STATIC)->GetWindowRect(&rect);//获取MFC图像显示区域
  86. Point p(pt.x, pt.y);//opencv鼠标坐标
  87. Rect r(rect.left, rect.top, rect.right, rect.bottom);//opencv窗口显示区域
  88. if (r.contains(p)) //鼠标放在图片窗口上
  89. {
  90. int w = g_matOriginal.cols, h =g_matOriginal.rows;//原图宽高
  91. Mat mat;
  92. if (zDelta > 0)//放大图片
  93. {
  94. double zoom = g_iZoom + g_iRadio;
  95. if (w * zoom * h * zoom < 3000 * 3000)//图片宽高<3000*3000时缩放值才会变大
  96. {
  97. g_iZoom = zoom;
  98. }
  99. resize(g_matOriginal, mat, Size(), g_iZoom, g_iZoom, INTER_LINEAR); //按比例放大图片
  100. }
  101. else if (zDelta < 0)//缩小图片
  102. {
  103. double zoom = g_iZoom - g_iRadio;
  104. if (w * zoom * h * zoom > 100 * 100)//图片宽高>100*100时缩放值才会变小
  105. {
  106. g_iZoom = zoom;
  107. }
  108. resize(g_matOriginal, mat, Size(), g_iZoom, g_iZoom, INTER_AREA); //按比例缩小图片
  109. }
  110. imshow("ImageShow", mat);//显示缩放后图片
  111. waitKey(1);
  112. }
  113. return CDialogEx::OnMouseWheel(nFlags, zDelta, pt);
  114. }
  115. //void OpenCVMouse(int event, int x, int y, int flags, void* param)//opencv滚轮函数
  116. //{
  117. // if (event == EVENT_MOUSEWHEEL)//鼠标滚轮函数
  118. // {
  119. // TRACE("EVENT_MOUSEWHEEL\n");
  120. // }
  121. // if (event == EVENT_LBUTTONDOWN)
  122. // {
  123. // TRACE("EVENT_LBUTTONDOWN\n");//鼠标左键点击函数
  124. // }
  125. //}

四、注意

  Opencv窗口嵌套入MFC后,其鼠标按键函数有效,但其鼠标滚轮函数无效,只能使用MFC自身的鼠标滚轮函数。
在这里插入图片描述
  如上图所示,当鼠标左键按下时输出栏显示如下内容:
  atlTraceGeneral - EVENT_LBUTTONDOWN
  atlTraceGeneral - EVENT_LBUTTONDOWN
  atlTraceGeneral - EVENT_LBUTTONDOWN
  而当鼠标滚轮前后滚动时并未出现:
  atlTraceGeneral - EVENT_MOUSEWHEEL
  如此说明opencv的鼠标滚轮函数无效。

发表评论

表情:
评论列表 (有 0 条评论,806人围观)

还没有评论,来说两句吧...

相关阅读