// SampleGrab2Dlg.cpp : 实现文件 // #include "stdafx.h" #include "SampleGrab2.h" #include "SampleGrab2Dlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CSampleGrab2Dlg 对话框 CString m_editOpenDir; CSampleGrab2Dlg::CSampleGrab2Dlg(CWnd* pParent /*=NULL*/) : CDialog(CSampleGrab2Dlg::IDD, pParent) , m_editOpenDir(_T("")) , m_editSaveDir(_T("")) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CSampleGrab2Dlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT1, m_editOpenDir); DDX_Control(pDX, IDC_EDIT1, e_Openfile); DDX_Control(pDX, IDC_EDIT3, e_Savedir); } BEGIN_MESSAGE_MAP(CSampleGrab2Dlg, CDialog) ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_FILE_OPEN1, &CSampleGrab2Dlg::OnBnClickedFileOpen1) ON_BN_CLICKED(IDC_FILE_OPEN2, &CSampleGrab2Dlg::OnBnClickedFileOpen2) ON_BN_CLICKED(IDC_Grab, &CSampleGrab2Dlg::OnBnClickedGrab) END_MESSAGE_MAP() // CSampleGrab2Dlg 消息处理程序 BOOL CSampleGrab2Dlg::OnInitDialog() { CDialog::OnInitDialog(); // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CSampleGrab2Dlg::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 { CDialog::OnPaint(); } e_Openfile.SetWindowTextW((LPCTSTR)m_editOpenDir); e_Savedir.SetWindowTextW((LPCTSTR)m_editSaveDir); } //当用户拖动最小化窗口时系统调用此函数取得光标显示。 // HCURSOR CSampleGrab2Dlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } // 抓帧功能 //HRESULT CSampleGrab2Dlg::GrabFrameFromMovie(void) //{ // return E_NOTIMPL; //} HRESULT CSampleGrab2Dlg::GrabFrameFromMovie(void) { HRESULT hr = CoInitialize(NULL); //定义IMediaDet接口实例 CComPtr<IMediaDet> pDet; hr = CoCreateInstance(CLSID_MediaDet, NULL, CLSCTX_INPROC_SERVER,IID_IMediaDet,(void**)&pDet); if(FAILED(hr)) return hr; //将影片文件名转换成BSTR类型 CComBSTR openBSTR(m_editOpenDir); //设置IMediaDet接口的文件关联 hr = pDet ->put_Filename(openBSTR); if(FAILED(hr)) return hr; //从影片中检索视频流和音频流 long lStreams; hr = pDet ->get_OutputStreams(&lStreams); if(FAILED(hr)) return hr; //取出影片的视频流,因为帧的信息是保存在视频流中的 bool bFound = false; for (int i=0; i<lStreams; i++) { GUID major_type; hr = pDet->put_CurrentStream(i); if (SUCCEEDED(hr)) hr = pDet->get_StreamType(&major_type); if (FAILED(hr)) break; if (major_type == MEDIATYPE_Video) { bFound = true; break; } } if (!bFound) return VFW_E_INVALIDMEDIATYPE; long width = 0, height = 0; // 存储位图的宽和高(单位:象素) AM_MEDIA_TYPE mt; hr = pDet->get_StreamMediaType(&mt); if (SUCCEEDED(hr)) { if ((mt.formattype == FORMAT_VideoInfo) && (mt.cbFormat >= sizeof(VIDEOINFOHEADER))) { // 得到VIDEOINFOHEADER结构指针,VIDEOINFOHEADER结构包含一些与视频 // 有关的信息,其中含有BITMAPINFORHEADER结构 VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(mt.pbFormat); width = pVih->bmiHeader.biWidth; height = pVih->bmiHeader.biHeight; } else hr = VFW_E_INVALIDMEDIATYPE; MyFreeMediaType(mt); // 释放AM_MEDIA_TYPE结构???????????????????? } if (FAILED(hr)) return hr; CComBSTR saveBSTR(m_editSaveDir); // 将第一帧保存为指定路径的位图文件 hr = pDet->WriteBitmapBits(0, width, height, saveBSTR); if (FAILED(hr)) return hr; return S_OK; } // 释放结构体 void CSampleGrab2Dlg::MyFreeMediaType(AM_MEDIA_TYPE& mt) { if (mt.cbFormat != 0) { CoTaskMemFree((PVOID)mt.pbFormat); mt.cbFormat = 0; mt.pbFormat = NULL; } if (mt.pUnk != NULL) { // Unecessary because pUnk should not be used, but safest. mt.pUnk->Release(); mt.pUnk = NULL; } } void CSampleGrab2Dlg::OnBnClickedFileOpen1() { // TODO: 在此添加控件通知处理程序代码 CString pcsun("视频文件(*.mpg)|*.mpg||"); CFileDialog dlg(TRUE,NULL,0,OFN_OVERWRITEPROMPT,(LPCTSTR)pcsun,NULL);///TRUE为OPEN对话框,FALSE为SAVE AS对话框 if(dlg.DoModal() == IDOK) m_editOpenDir = dlg.GetPathName(); OnPaint(); UpdateData(FALSE); } void CSampleGrab2Dlg::OnBnClickedFileOpen2() { // TODO: 在此添加控件通知处理程序代码 CString m_FileDir; BROWSEINFO bi; ZeroMemory(&bi, sizeof(BROWSEINFO)); bi.hwndOwner = m_hWnd; bi.ulFlags = BIF_RETURNONLYFSDIRS; LPITEMIDLIST pidl = SHBrowseForFolder(&bi); BOOL bRet = FALSE; TCHAR szFolder[MAX_PATH*2]; szFolder[0] = _T('/0'); if (pidl) { if (SHGetPathFromIDList(pidl, szFolder)) bRet = TRUE; IMalloc *pMalloc = NULL; if (SUCCEEDED(SHGetMalloc(&pMalloc)) && pMalloc) { pMalloc->Free(pidl); pMalloc->Release(); } } m_FileDir = szFolder;//选择的文件夹路径 TRACE("/n&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&/n"); TRACE(m_FileDir); TRACE("/n&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&/n"); m_editSaveDir = m_FileDir; OnPaint(); } void CSampleGrab2Dlg::OnBnClickedGrab() { // TODO: 在此添加控件通知处理程序代码 if(m_editOpenDir != ""&&m_editSaveDir != "") { HRESULT hr; hr = GrabFrameFromMovie(); if( hr != S_OK) AfxMessageBox((CString)"无法抓取帧!"); else AfxMessageBox((CString)"抓取成功!"); } else AfxMessageBox((CString)"请选择完整路径!"); }