testDlg.hUINTshowvideo(LPVOIDlpParameter);classCtestDlg:publicCDialogEx{构造public:
testDlg.h
UINT showvideo( LPVOID lpParameter );
class CtestDlg : public CDialogEx
{
// 构造
public:
CtestDlg(CWnd* pParent = NULL); // 标准构造函数
// 对话框数据
enum { IDD = IDD_TEST_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
/*HANDLE hThread1;
HANDLE hThread2;*/
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedOk();
//IplImage* TheImage;
//CString m_vdpath;
//CString mPath;
void ShowImage( IplImage* img, UINT ID );
void ResizeImage(IplImage* img);
void OnTimer(UINT nIDEvent) ;
afx_msg void OnBnClickedvideo();
afx_msg void OnBnClickedabout();
afx_msg void OnBnClickedtool();
afx_msg void OnBnClickedopenimage();
afx_msg void OnBnClickedrun();
};
test.cpp
#include "stdafx.h"
#include "test.h"
#include "testDlg.h"
#include "afxdialogex.h"
#include "CvvImage.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CString m_vdpath;
CString mPath;
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
afx_msg void OnBnClickedhelp();
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
ON_WM_CTLCOLOR()
ON_BN_CLICKED(IDC_help, &CAboutDlg::OnBnClickedhelp)
END_MESSAGE_MAP()
// CtestDlg 对话框
CtestDlg::CtestDlg(CWnd* pParent /*=NULL*/): CDialogEx(CtestDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CtestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CtestDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDOK, &CtestDlg::OnBnClickedOk)
ON_BN_CLICKED(IDC_video, &CtestDlg::OnBnClickedvideo)
ON_BN_CLICKED(IDC_about, &CtestDlg::OnBnClickedabout)
ON_BN_CLICKED(IDC_tool, &CtestDlg::OnBnClickedtool)
ON_BN_CLICKED(IDC_openimage, &CtestDlg::OnBnClickedopenimage)
ON_BN_CLICKED(IDC_run, &CtestDlg::OnBnClickedrun)
END_MESSAGE_MAP()
// CtestDlg 消息处理程序
BOOL CtestDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
CvSize ImgSize;
ImgSize.height = IMAGE_HEIGHT;
ImgSize.width = IMAGE_WIDTH;
TheImage = cvCreateImage( ImgSize, IPL_DEPTH_8U, IMAGE_CHANNELS );
//UpdateData(FALSE); 将成员变量的值赋值给控件,将数据从窗口显示。
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CtestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CtestDlg::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();
//CDialog::OnPaint(); // 重绘对话框
CDialog::UpdateWindow(); // 更新windows窗口,如果无这步调用,图片显示还会出现问题
ShowImage( TheImage, IDC_STATIC ); // 重绘图片函数
//add background picture
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
CDC dcMem;
dcMem.CreateCompatibleDC(&dc);
CBitmap bmpBackground;
bmpBackground.LoadBitmap(IDB_BITMAP1);
BITMAP bitmap;
bmpBackground.GetBitmap(&bitmap);
CBitmap *pbmpOld=dcMem.SelectObject(&bmpBackground);
dc.StretchBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,
bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CtestDlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
}
//以下为showimage函数
void CtestDlg::ShowImage(IplImage* img, UINT ID)// ID 是Picture Control控件的ID号
{
CDC* pDC=GetDlgItem(ID)->GetDC();// 获得显示控件的 DC
HDC hDC=pDC->GetSafeHdc();// 获取 HDC(设备句柄) 来进行绘图操作
CRect rect;
GetDlgItem(ID)->GetClientRect(&rect);
int rw=rect.right-rect.left; // 求出picture control的宽和高
int rh=rect.bottom-rect.top;
int iw=img->width; // 读取图片的宽和高
int ih=img->height;
int tx = (int)(rw - iw)/2; // 使图片的显示位置正好在控件的正中
int ty = (int)(rh - ih)/2;
SetRect( rect, tx, ty, tx+iw, ty+ih );
CvvImage cimg;
cimg.CopyOf(img); // 复制图片
cimg.DrawToHDC(hDC,&rect);
ReleaseDC(pDC);
}
//以下为改变图片大小以适应控件
void CtestDlg::ResizeImage(IplImage* img)
{
// 读取图片的宽和高
int w = img->width;
int h = img->height;
// 找出宽和高中的较大值者
int max = (w > h)? w: h;
// 计算将图片缩放到TheImage区域所需的比例因子
float scale = (float) ( (float) max / 512.0f );
// 缩放后图片的宽和高
int nw = (int)( w/scale );
int nh = (int)( h/scale );
// 为了将缩放后的图片存入 TheImage 的正中部位,需计算图片在 TheImage 左上角的期望坐标值
int tlx = (nw > nh)? 0: (int)(256-nw)/2;
int tly = (nw > nh)? (int)(256-nh)/2: 0;
// 设置 TheImage 的 ROI 区域,用来存入图片 img
cvSetImageROI( TheImage, cvRect( tlx, tly, nw, nh) );
// 对图片 img 进行缩放,并存入到 TheImage 中
cvResize( img, TheImage );
// 重置 TheImage 的 ROI 准备读入下一幅图片
cvResetImageROI( TheImage );
}
//以下为打开视频函数
void CtestDlg::OnBnClickedvideo()
{
CFileDialog dlg(TRUE, NULL, NULL,OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
_T("video files (*.avi) |*.avi| All Files (*.*) |*.*||"), NULL
); // 选项图片的约定
dlg.m_ofn.lpstrTitle = _T("Open video"); // 打开文件对话框的标题名
// CString mPath = dlg.GetPathName();
//capture=cvCaptureFromAVI(mPath);
//SetTimer(1,25,NULL);
if(dlg.DoModal()==IDOK)
{
m_vdpath=dlg.GetPathName();
}
CWinThread *hThread2=AfxBeginThread(showvideo,NULL,0,0,0,NULL);
}
UINT showvideo( LPVOID lpParameters )
{
CtestDlg *pDlg = (CtestDlg*)lpParameters;
CvCapture* pCapture=NULL;
pCapture = cvCaptureFromAVI(m_vdpath);
if(pCapture == NULL)
AfxMessageBox("AVI视频打开失败或格式不对");
IplImage* frame=NULL;
while(true)
{
if(frame = cvQueryFrame(pCapture) )
{
// cvQueryFrame( pCapture ) 用来提取指定视频中的每一帧
//视频的尾部 则退出
/* cvWaitKey(50000);*/
//Sleep(1);
pDlg->ResizeImage( frame ); // 对读入的图片进行缩放,使其宽或高最大值者刚好等于 再复制到 TheImage 中
pDlg->ShowImage( TheImage, IDC_STATIC ); // 调用显示图片函数
}
else
{
break;
}
}
cvReleaseImage( &frame );
cvReleaseCapture( &pCapture );// 释放 ipl 占用的内存
return 0;
}
以前不另外加线程视频可以再空控件里运行,就是其它对话框其它按键都禁用了,所以想单独给视频加个线程,我自己试了下,不能播放了,对线程不是很了解,还请大家帮帮忙看看什么原因...
8 个解决方案
那个函数ResizeImage就不需要了,opencv显示图像cimg.DrawToHDC(hDC,&rect);这个就可以自动改变图片大小以适应你给的控件的rect了。
线程我也在学习
看了一下,你用的是工作线程,想要与界面交互就使用界面线程。现学现用的,你可以参考下。
慢慢研究rect方法,,用rect实现控件的控制与你需要的视频图像显示
多线程可以参考下《秒杀多线程面试题系列》
http://blog.csdn.net/column/details/killthreadseries.html
这里有十五篇文章,绝对让你在有收获。
-------------------
MoreWindows
计科小硕 迅雷/微软/豌豆荚实习生 CSDN资深博客专家 2012年度CSDN博客之星
我的微博:
http://weibo.com/MoreWindows
我的博客:
http://blog.csdn.net/MoreWindows