在基于 MFC(Microsoft Foundation Classes)开发的桌面应用中,经常需要实现图像加载、处理与界面显示的功能。结合 OpenCV 库强大的图像处理能力,我们可以快速实现 "将图像显示在 MFC 对话框的 Picture 控件上" 这一需求。
本文将基于完整可运行的工程代码,详细讲解实现原理、关键步骤与代码解析,帮助开发者快速掌握 MFC+OpenCV 联合显示图像的方法。
一、功能概述
本案例实现目标:
- 创建 MFC 对话框应用程序;
- 添加按钮与 Picture 控件;
- 点击按钮打开文件选择对话框,选择本地图像;
- 使用 OpenCV 加载图像,并嵌入显示到 MFC 的 Picture 控件中;
- 自动缩放图像以适配控件大小,保持界面整洁。
开发环境:MFC、OpenCV、C++
二、界面设计准备
在开始编码前,先完成对话框界面布局:
- 向工程中添加一个按钮(Button) ,ID 设为
IDC_BUTTON_LOADIMAGE,标题为 "加载图像"; - 添加一个Picture 控件 ,ID 设为
IDC_SHOW_PICTRUE,用于显示 OpenCV 处理后的图像; - 保留 MFC 默认的对话框框架,无需额外修改样式。

三、头文件与命名空间配置
要在 MFC 中使用 OpenCV,必须引入对应的头文件并声明命名空间:
cpp
#include "stdafx.h"
#include "OpencvImage.h"
#include "OpencvImageDlg.h"
#include "afxdialogex.h"
// OpenCV 核心头文件
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv; // 使用OpenCV命名空间
说明:
core.hpp:OpenCV 核心数据结构(如 Mat);highgui.hpp:图像读取、窗口显示;imgproc.hpp:图像缩放、变换等处理函数。
四、关键变量定义
在对话框类中,定义 Picture 控件的绑定变量:
cpp
CStatic m_ctrlPic; // 绑定 IDC_SHOW_PICTRUE 图片控件
通过DoDataExchange完成控件与变量的关联:
cpp
void COpencvImageDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SHOW_PICTRUE, m_ctrlPic);
}
五、核心功能实现:图像加载与显示
图像显示的核心逻辑在按钮点击响应函数中实现,完整代码如下:
cpp
void COpencvImageDlg::OnBnClickedButtonLoadimage()
{
CString pathName;
// 1. 创建文件打开对话框
CFileDialog openFileDlg(TRUE, NULL, _T(""),
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
_T("所有类型(*.*)|*.*"), NULL);
if(openFileDlg.DoModal() == IDOK)
{
// 获取选中的图像完整路径
pathName = openFileDlg.GetPathName();
// 2. 获取Picture控件的显示区域大小
CRect rc;
m_ctrlPic.GetClientRect(&rc);
cv::Size resizeSize(rc.Width(), rc.Height());
// 3. OpenCV读取图像
cv::Mat src = cv::imread((LPCTSTR)pathName);
cv::Mat resizedDst;
// 4. 缩放图像适配控件大小
cv::resize(src, resizedDst, resizeSize);
// 5. 窗口句柄操作:将OpenCV窗口嵌入MFC控件
cv::destroyAllWindows(); // 清空旧窗口
cv::namedWindow("OpecvImage", CV_WINDOW_AUTOSIZE);
// 获取OpenCV窗口句柄
HWND ImgWnd = (HWND)cvGetWindowHandle("OpecvImage");
// 设置父窗口为MFC Picture控件
::SetParent(ImgWnd, m_ctrlPic.m_hWnd);
// 隐藏OpenCV原生窗口
::ShowWindow(::GetParent(ImgWnd), HIDE_WINDOW);
// 6. 在控件中显示图像
cv::imshow("OpecvImage", resizedDst);
}
UpdateData(FALSE);
}
六、代码核心原理讲解
1. 文件选择对话框
使用 MFC 的CFileDialog实现图像文件选择,支持所有格式的图片文件筛选,用户可自由选择本地图像。
2. 自适应控件缩放
通过GetClientRect获取 Picture 控件的宽高,调用cv::resize将图像缩放到与控件完全匹配的尺寸,避免图像溢出或变形。
3. OpenCV 窗口嵌入 MFC(核心技术)
这是本案例最关键的步骤:
- OpenCV 默认创建独立窗口显示图像;
- 通过
cvGetWindowHandle获取 OpenCV 窗口句柄; - 使用
::SetParent将 OpenCV 窗口的父窗口设置为 MFC Picture 控件; - 隐藏 OpenCV 原生窗口,只保留嵌入后的显示区域。
最终实现效果:图像完全显示在 MFC 对话框的指定控件内,而非独立弹出窗口。
//包含目录
g:\opencv\build\include
g:\opencv\build\include\opencv2
g:\opencv\build\include\opencv

//库目录
g:\opencv\build\x86\vc10\lib

//链接输入
//debug库文件列表
opencv_ml2410d.lib
opencv_calib3d2410d.lib
opencv_contrib2410d.lib
opencv_core2410d.lib
opencv_features2d2410d.lib
opencv_flann2410d.lib
opencv_gpu2410d.lib
opencv_highgui2410d.lib
opencv_imgproc2410d.lib
opencv_legacy2410d.lib
opencv_objdetect2410d.lib
opencv_ts2410d.lib
opencv_video2410d.lib
opencv_nonfree2410d.lib
opencv_ocl2410d.lib
opencv_photo2410d.lib
opencv_stitching2410d.lib
opencv_superres2410d.lib
opencv_videostab2410d.lib

测试图片运行效果:
