MFC OpenCV:鼠标滚轮缩放图片


一、背景

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

二、实现步骤

1、新建MFC应用程序。


2、配置OpenCV运行环境。

3、添加MFC的Pictrue Control控件

4、编写代码。只需修改MFCApplication1Dlg.cpp文件。

添加的代码:

//在MFCApplication1Dlg.cpp添加库文件
#include "opencv2/opencv.hpp"
using namespace cv;

//在MFCApplication1Dlg.cpp添加全局变量
double g_iZoom = 1;//初始缩放值
double g_iRadio = 0.1;//缩放步距
Mat g_matOriginal;//原始图片

//在MFCApplication1Dlg.cpp的CMFCApplication1Dlg::OnInitDialog()函数中添加如下代码:
    namedWindow("ImageShow");//创建OpenCV窗口
    HWND hWnd = (HWND)cvGetWindowHandle("ImageShow");//嵌套opencv窗口
    HWND hParent = ::GetParent(hWnd);
    ::SetParent(hWnd, GetDlgItem(IDC_STATIC)->m_hWnd);
    ::ShowWindow(hParent, SW_HIDE);
    g_iZoom = 1;//初始缩放值为1,表示原图
    g_matOriginal = imread("E:\\vs\\image\\11.png");//opencv读取图片
    imshow("ImageShow", g_matOriginal);//opencv显示图片
    waitKey(1);

5、初步运行结果。到此可以简单显示图片。


6、右键MFC的Pictrue Control控件,添加MFC的鼠标滚轮函数。

BOOL CMFCApplication1Dlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    CRect rect;
    GetDlgItem(IDC_STATIC)->GetWindowRect(&rect);//获取MFC图像显示区域
    Point p(pt.x, pt.y);//opencv鼠标坐标
    Rect r(rect.left, rect.top, rect.right, rect.bottom);//opencv窗口显示区域
    if (r.contains(p)) //鼠标放在图片窗口上
    {
        int w = g_matOriginal.cols, h =g_matOriginal.rows;//原图宽高
        Mat mat;
        if (zDelta > 0)//放大图片
        {
            double zoom = g_iZoom + g_iRadio;
            if (w * zoom * h * zoom < 3000 * 3000)//图片宽高<3000*3000时缩放值才会变大
            {
                g_iZoom = zoom;
            }
            resize(g_matOriginal, mat, Size(), g_iZoom, g_iZoom, INTER_LINEAR); //按比例放大图片
        }
        else if (zDelta < 0)//缩小图片
        {
            double zoom = g_iZoom - g_iRadio;
            if (w * zoom * h * zoom > 100 * 100)//图片宽高>100*100时缩放值才会变小
            {
                g_iZoom = zoom;
            }
            resize(g_matOriginal, mat, Size(), g_iZoom, g_iZoom, INTER_AREA); //按比例缩小图片
        }
        imshow("ImageShow", mat);//显示缩放后图片
        waitKey(1);
    }
    return CDialogEx::OnMouseWheel(nFlags, zDelta, pt);
}

7、缩放图片结果

缩小图片

放大图片

三、全部代码

MFCApplication1Dlg.h


// MFCApplication1Dlg.h: 头文件
//

#pragma once


// CMFCApplication1Dlg 对话框
class CMFCApplication1Dlg : public CDialogEx
{
// 构造
public:
    CMFCApplication1Dlg(CWnd* pParent = nullptr);   // 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_MFCAPPLICATION1_DIALOG };
#endif

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持


// 实现
protected:
    HICON m_hIcon;

    // 生成的消息映射函数
    virtual BOOL OnInitDialog();
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
};

MFCApplication1Dlg.cpp


// MFCApplication1Dlg.cpp: 实现文件
//

#include "stdafx.h"
#include "MFCApplication1.h"
#include "MFCApplication1Dlg.h"
#include "afxdialogex.h"

#include "opencv2/opencv.hpp"
using namespace cv;

double g_iZoom = 1;//初始缩放值
double g_iRadio = 0.1;//缩放步距
Mat g_matOriginal;//原始图片
//void OpenCVMouse(int event, int x, int y, int flags, void* param);

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CMFCApplication1Dlg 对话框



CMFCApplication1Dlg::CMFCApplication1Dlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_MFCAPPLICATION1_DIALOG, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMFCApplication1Dlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialogEx)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_MOUSEWHEEL()
END_MESSAGE_MAP()


// CMFCApplication1Dlg 消息处理程序

BOOL CMFCApplication1Dlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE);         // 设置大图标
    SetIcon(m_hIcon, FALSE);        // 设置小图标

    namedWindow("ImageShow");//创建OpenCV窗口
    HWND hWnd = (HWND)cvGetWindowHandle("ImageShow");//嵌套opencv窗口
    HWND hParent = ::GetParent(hWnd);
    ::SetParent(hWnd, GetDlgItem(IDC_STATIC)->m_hWnd);
    ::ShowWindow(hParent, SW_HIDE);

    g_iZoom = 1;//初始缩放值为1,表示原图
    //setMouseCallback("ImageShow", OpenCVMouse, NULL); // 鼠标事件
    g_matOriginal = imread("E:\\vs\\image\\11.png");//opencv读取图片
    imshow("ImageShow", g_matOriginal);//opencv显示图片
    waitKey(1);
    

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CMFCApplication1Dlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // 用于绘制的设备上下文

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // 使图标在工作区矩形中居中
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // 绘制图标
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFCApplication1Dlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}


BOOL CMFCApplication1Dlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    CRect rect;
    GetDlgItem(IDC_STATIC)->GetWindowRect(&rect);//获取MFC图像显示区域
    Point p(pt.x, pt.y);//opencv鼠标坐标
    Rect r(rect.left, rect.top, rect.right, rect.bottom);//opencv窗口显示区域
    if (r.contains(p)) //鼠标放在图片窗口上
    {
        int w = g_matOriginal.cols, h =g_matOriginal.rows;//原图宽高
        Mat mat;
        if (zDelta > 0)//放大图片
        {
            double zoom = g_iZoom + g_iRadio;
            if (w * zoom * h * zoom < 3000 * 3000)//图片宽高<3000*3000时缩放值才会变大
            {
                g_iZoom = zoom;
            }
            resize(g_matOriginal, mat, Size(), g_iZoom, g_iZoom, INTER_LINEAR); //按比例放大图片
        }
        else if (zDelta < 0)//缩小图片
        {
            double zoom = g_iZoom - g_iRadio;
            if (w * zoom * h * zoom > 100 * 100)//图片宽高>100*100时缩放值才会变小
            {
                g_iZoom = zoom;
            }
            resize(g_matOriginal, mat, Size(), g_iZoom, g_iZoom, INTER_AREA); //按比例缩小图片
        }
        imshow("ImageShow", mat);//显示缩放后图片
        waitKey(1);
    }

    return CDialogEx::OnMouseWheel(nFlags, zDelta, pt);
}


//void OpenCVMouse(int event, int x, int y, int flags, void* param)//opencv滚轮函数
//{
//  if (event == EVENT_MOUSEWHEEL)//鼠标滚轮函数
//  {
//      TRACE("EVENT_MOUSEWHEEL\n");
//  }
//  if (event == EVENT_LBUTTONDOWN)
//  {
//      TRACE("EVENT_LBUTTONDOWN\n");//鼠标左键点击函数
//  }
//}



四、注意

  Opencv窗口嵌套入MFC后,其鼠标按键函数有效,但其鼠标滚轮函数无效,只能使用MFC自身的鼠标滚轮函数。


  如上图所示,当鼠标左键按下时输出栏显示如下内容:
  atlTraceGeneral - EVENT_LBUTTONDOWN
  atlTraceGeneral - EVENT_LBUTTONDOWN
  atlTraceGeneral - EVENT_LBUTTONDOWN
  而当鼠标滚轮前后滚动时并未出现:
  atlTraceGeneral - EVENT_MOUSEWHEEL
  如此说明opencv的鼠标滚轮函数无效。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。