MFC OpenCV:鼠标滚轮缩放图片

MFC OpenCV:鼠标滚轮缩放图片

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


一、背景

  前置文章:MFC显示OpenCV图片的三种详细方法
  在利用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的鼠标滚轮函数。
MFC OpenCV:鼠标滚轮缩放图片_第1张图片
MFC OpenCV:鼠标滚轮缩放图片_第2张图片

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、缩放图片结果
MFC OpenCV:鼠标滚轮缩放图片_第3张图片
MFC OpenCV:鼠标滚轮缩放图片_第4张图片

三、全部代码

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(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(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自身的鼠标滚轮函数。
MFC OpenCV:鼠标滚轮缩放图片_第5张图片
  如上图所示,当鼠标左键按下时输出栏显示如下内容:
  atlTraceGeneral - EVENT_LBUTTONDOWN
  atlTraceGeneral - EVENT_LBUTTONDOWN
  atlTraceGeneral - EVENT_LBUTTONDOWN
  而当鼠标滚轮前后滚动时并未出现:
  atlTraceGeneral - EVENT_MOUSEWHEEL
  如此说明opencv的鼠标滚轮函数无效。

你可能感兴趣的:(#,MFC,OpenCV,MFC,OpenCV,鼠标滚轮事件)