// ShowReplayDlg.cpp : 实现文件 // #include "stdafx.h" #include "CH91PayloadSoftware.h" #include "ShowReplayDlg.h" #include "afxdialogex.h" #include "Global.h" #include "GlobalMessage.h" // 多媒体定时器 #include "MMSystem.h" #pragma comment(lib, "winmm") //timeSetEvent中的回调函数,名字随便起,但是内容固定 void CALLBACK TimerPlayFunc(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) { // 目的:调用ReadandPlay,将dwUser强制转换为ptr,可以使用ptr格式,更加方便 CShowReplayDlg* ptr = reinterpret_cast(dwUser); // 读取文件并播放 if (ptr != NULL) { ptr->ReadAndPlay(); } } // CShowReplayDlg 对话框 IMPLEMENT_DYNAMIC(CShowReplayDlg, CDialogEx) CShowReplayDlg::CShowReplayDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CShowReplayDlg::IDD, pParent) { m_TimerID = 0; m_TimerPeriod = 20; // 默认20ms 调用一次多媒体时钟函数,由于EO和IR穿插,因此一秒钟调用50次,EO和IR帧频各25 m_bFileOpen = FALSE; m_bIsPlay = FALSE; m_bPauseSliderReflect = FALSE; m_bService = FALSE; // 初始情况下后台服务程序未打开 m_bTransParent = FALSE; // 初始情况下不透明 } CShowReplayDlg::~CShowReplayDlg() { } void CShowReplayDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_SLIDER_REPLAYRATIO, m_SliderReplayRatio); } BEGIN_MESSAGE_MAP(CShowReplayDlg, CDialogEx) ON_BN_CLICKED(IDC_BTN_OPENFILE, &CShowReplayDlg::OnBnClickedBtnOpenfile) ON_BN_CLICKED(IDC_BTN_FILEPLAYPAUSE, &CShowReplayDlg::OnBnClickedBtnFileplaypause) ON_BN_CLICKED(IDC_BTN_FILESTOP, &CShowReplayDlg::OnBnClickedBtnFilestop) ON_BN_CLICKED(IDC_BTN_FILESLOW, &CShowReplayDlg::OnBnClickedBtnFileslow) ON_BN_CLICKED(IDC_BTN_FILEFAST, &CShowReplayDlg::OnBnClickedBtnFilefast) ON_CBN_SELCHANGE(IDC_COMBOX_PLAYTYPE, &CShowReplayDlg::OnCbnSelchangeComboxPlaytype) ON_WM_DESTROY() ON_MESSAGE(WM_BITMAPSLIDER_MOVING, OnBitmapSliderMoving) ON_MESSAGE(WM_RETURN_PAYLOAD_TYPE_WARNING, &CShowReplayDlg::ReturnPayloadTypeWarning) END_MESSAGE_MAP() // CShowReplayDlg 消息处理程序 BOOL CShowReplayDlg::PreTranslateMessage(MSG* pMsg) { // TODO: 在此添加专用代码和/或调用基类 // 键盘消息 if (pMsg->message == WM_KEYDOWN) { // 忽略ESC和回车键 if (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN) { return TRUE; } // F1键控制“视频控制”窗口的现实/隐藏 if (pMsg->wParam == VK_F1) { // 关闭窗口 OnOK(); } } return CDialogEx::PreTranslateMessage(pMsg); } BOOL CShowReplayDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 设置对话框标题 SetWindowText(g_str_TitleReplay); // 设置文件路径名称 GetDlgItem(IDC_STATIC_HF_FILE_PATH) -> SetWindowText(g_str_FilePath); //设置回放进度条各参数 m_SliderReplayRatio.SetBitmapChannel( IDB_MP_CHANNEL, IDB_MP_CHANNEL_ACTIVE ); m_SliderReplayRatio.SetBitmapThumb( IDB_MP_THUMB, IDB_MP_THUMB_ACTIVE, TRUE ); m_SliderReplayRatio.DrawFocusRect( FALSE ); m_SliderReplayRatio.SetMargin( 2, 3, 2, 0 ); m_SliderReplayRatio.SetRange(0, 5000); m_SliderReplayRatio.SetPos(0); // 获取窗口句柄 g_ReplayDlgHwnd = GetSafeHwnd(); // 工作模式 ((CComboBox*)GetDlgItem(IDC_COMBOX_PLAYTYPE))->AddString("回放"); ((CComboBox*)GetDlgItem(IDC_COMBOX_PLAYTYPE))->AddString("实时"); ((CComboBox*)GetDlgItem(IDC_COMBOX_PLAYTYPE))->SetCurSel(1); OnCbnSelchangeComboxPlaytype(); // 设置界面按钮 // 打开文件 m_Btn_OpenFile.SubclassDlgItem(IDC_BTN_OPENFILE, this); m_Btn_OpenFile.SetIcon(IDI_ICON_OPENFILE); m_Btn_OpenFile.DrawTransparent(TRUE); m_Btn_OpenFile.SetTooltipText("文件"); m_Btn_OpenFile.DrawBorder(FALSE); // 开始/暂停 m_Btn_PlayPause.SubclassDlgItem(IDC_BTN_FILEPLAYPAUSE, this); m_Btn_PlayPause.SetIcon(IDI_ICON_PLAY); m_Btn_PlayPause.DrawTransparent(TRUE); m_Btn_PlayPause.SetTooltipText("开始/暂停"); m_Btn_PlayPause.DrawBorder(FALSE); // 停止 m_Btn_Stop.SubclassDlgItem(IDC_BTN_FILESTOP, this); m_Btn_Stop.SetIcon(IDI_ICON_STOP); m_Btn_Stop.DrawTransparent(TRUE); m_Btn_Stop.SetTooltipText("停止"); m_Btn_Stop.DrawBorder(FALSE); // 加速 m_Btn_SpeedUp.SubclassDlgItem(IDC_BTN_FILEFAST, this); m_Btn_SpeedUp.SetIcon(IDI_ICON_SPEEDUP); m_Btn_SpeedUp.DrawTransparent(TRUE); m_Btn_SpeedUp.SetTooltipText("加速"); m_Btn_SpeedUp.DrawBorder(FALSE); // 减速 m_Btn_SpeedDown.SubclassDlgItem(IDC_BTN_FILESLOW, this); m_Btn_SpeedDown.SetIcon(IDI_ICON_SPEEDDOWN); m_Btn_SpeedDown.DrawTransparent(TRUE); m_Btn_SpeedDown.SetTooltipText("减速"); m_Btn_SpeedDown.DrawBorder(FALSE); // 设置播放比率初始值 GetDlgItem(IDC_STATIC_REPLAY_RATIO)->SetWindowText(_T("0%")); return TRUE; } // 打开回放视频文件 void CShowReplayDlg::OnBnClickedBtnOpenfile() { // 首先停止播放视频 OnBnClickedBtnFilestop(); // 打开文件夹 CFileDialog Dialog( TRUE, NULL, NULL, OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY, _T("Video Files (*.tx) |*.tx| All Files (*.*) |*.*||"), NULL); Dialog.m_ofn.lpstrTitle = _T("Open Files"); if (Dialog.DoModal()!=IDOK) { return; } if (m_bIsPlay == FALSE) { m_HFfilePath = Dialog.GetPathName(); // 显示文件路径 GetDlgItem(IDC_STATIC_HF_FILE_PATH)->SetWindowText(g_str_FilePath + m_HFfilePath); } else { } } //启动定时器——多媒体定时器,与 void CShowReplayDlg::StartTimer() { // 启动定时器,回调函数:TimerPlayFunc,固定格式,只需编译回调函数TimerPlayFunc m_TimerID = timeSetEvent(m_TimerPeriod, 1, TimerPlayFunc, (DWORD_PTR)this, TIME_PERIODIC); } //停止定时器 void CShowReplayDlg::StopTimer() { if (m_TimerID != 0) { timeKillEvent(m_TimerID); m_TimerID = 0; } } // 播放及暂停视频 void CShowReplayDlg::OnBnClickedBtnFileplaypause() { if (m_bFileOpen == FALSE) { // 显示文件名之后打开文件,获取文件长度,文件内容当前进度以及文件 if (m_ReplayFile.Open(m_HFfilePath, CFile::modeRead) == TRUE) { m_bFileOpen = TRUE; m_FileInfo.FileTotalLen = m_ReplayFile.GetLength(); // 获取文件长度 m_FileInfo.curFilePos = 0; //获取文件当前内容位置为0 m_FileInfo.FrameLen = 1024;//1024; //设定读取一帧的字节大小(10KB) } else { return; } } if (m_bFileOpen == TRUE) { //如果没有播放 if (m_bIsPlay == FALSE) { // 如果上一次定时器(或者其他情况下)处于意外没有停止,则停止当前定时器 if (m_TimerID != 0) { timeKillEvent(m_TimerID); m_TimerID = 0; } m_bIsPlay = TRUE; //设定新的定时器,并用定时器调用读取每一帧进行播放 StartTimer(); //GetDlgItem(IDC_BTN_FILEPLAYPAUSE)->SetWindowTextA("暂停"); m_Btn_PlayPause.SetIcon(IDI_ICON_PAUSE); } //如果正在播放,则暂停 else { if (m_TimerID != 0) { timeKillEvent(m_TimerID); m_TimerID = 0; } m_bIsPlay = FALSE; g_bEOImgUpdate = FALSE; g_bIRImgUpdate = FALSE; //GetDlgItem(IDC_BTN_FILEPLAYPAUSE)->SetWindowTextA("播放"); m_Btn_PlayPause.SetIcon(IDI_ICON_PLAY); } } g_bReplayPlay = m_bIsPlay; } //读文件并播放,在TimerPlayFunc中调用 void CShowReplayDlg::ReadAndPlay() { //如果正在播放且滑动条没有暂停相应 if(m_bIsPlay == TRUE && m_bPauseSliderReflect == FALSE) { if (m_bFileOpen == FALSE) { return; } int readLen = 0; //时钟设定之后,每次调用函数,每次顺次读一下文件 readLen = m_ReplayFile.Read(m_FileInfo.Buffer, m_FileInfo.FrameLen); //当前文件位置 m_FileInfo.curFilePos += readLen; // 判断是否已到文件结尾 if(m_FileInfo.curFilePos < m_FileInfo.FileTotalLen) { // 输出原始数据 ReplayInputData(m_FileInfo.Buffer, readLen); // 输出播放百分比 double ratio = 0.0; ratio = m_FileInfo.curFilePos * 1.0 / m_FileInfo.FileTotalLen; int rangeMax = m_SliderReplayRatio.GetRangeMax(); int currentPos = static_cast(ratio * rangeMax + 0.5); // int类型强制转换为向下取整,加上0.5可以保证取整时四舍五入 m_bPauseSliderReflect = TRUE; // 暂停滑动条响应 m_SliderReplayRatio.SetPos(currentPos); CString str; str.Format("%.1f", ratio * 100); str = str + "%"; /* UpdateData(TRUE);*/ GetDlgItem(IDC_STATIC_REPLAY_RATIO)->SetWindowText(str); m_bPauseSliderReflect = FALSE; // 所有关于输出百分比设置的事情结束之后,开始滑动条响应 } else { } } } // 设置回放进度 void CShowReplayDlg::SetFileReplayRatio(double ratio) { if (ratio < 0 || ratio > 1) { return; } else { if (m_bFileOpen == TRUE) { // 计算文件大小 m_FileInfo.curFilePos = ULONGLONG(m_FileInfo.FileTotalLen * ratio); m_ReplayFile.Seek(LONGLONG(m_FileInfo.curFilePos), CFile::begin); } } } // 拖动滑动条响应函数 LRESULT CShowReplayDlg::OnBitmapSliderMoving(WPARAM wParam, LPARAM lParam) { if (m_bPauseSliderReflect == FALSE) { // 滑动条暂停响应 m_bPauseSliderReflect = TRUE; // 确定当前读取文件位置 int pos = m_SliderReplayRatio.GetPos(); int rangeMax = m_SliderReplayRatio.GetRangeMax(); double ratio = pos * 1.0 / rangeMax; SetFileReplayRatio(ratio); // 滑动条开始响应 m_bPauseSliderReflect = FALSE; } return 0; } // 停止播放 void CShowReplayDlg::OnBnClickedBtnFilestop() { if (g_bWorkMode == true) { StopTimer(); // 读取图像缓存清零 if (m_bFileOpen == TRUE) { m_ReplayFile.Close(); m_bFileOpen = FALSE; m_FileInfo.ClearStru(); } m_bIsPlay = FALSE; Sleep(20); // 播放进度条复位 m_SliderReplayRatio.SetPos(0); // 播放比率置零 GetDlgItem(IDC_STATIC_REPLAY_RATIO)->SetWindowText(_T("0%")); //GetDlgItem(IDC_BTN_FILEPLAYPAUSE)->SetWindowTextA("播放"); m_Btn_PlayPause.SetIcon(IDI_ICON_PLAY); // ::PostMessage(g_mainDlgHwnd, WM_SHOW_STOP, 0, 0); } } // 减速——通过设定每帧字节的大小来控制播放的快慢 void CShowReplayDlg::OnBnClickedBtnFileslow() { if(m_bFileOpen == TRUE && m_bIsPlay == TRUE) { if ((m_FileInfo.FrameLen - 1024) >= g_MinReadLen) { m_FileInfo.FrameLen = m_FileInfo.FrameLen - 1024; } else { m_FileInfo.FrameLen = g_MinReadLen; } } } // 加速——通过设定每帧字节的大小来控制播放的快慢 void CShowReplayDlg::OnBnClickedBtnFilefast() { if(m_bFileOpen == TRUE && m_bIsPlay == TRUE) { if (m_FileInfo.FrameLen + 1024 <= g_MaxReadLen) { m_FileInfo.FrameLen = m_FileInfo.FrameLen + 1024; } else { m_FileInfo.FrameLen = g_MaxReadLen; } } } void CShowReplayDlg::OnCbnSelchangeComboxPlaytype() { int state = ((CComboBox*)GetDlgItem(IDC_COMBOX_PLAYTYPE))->GetCurSel(); // 视频回放功能 if (state == 0) { g_bWorkMode = true; // 回放 GetDlgItem(IDC_BTN_OPENFILE)->EnableWindow(TRUE); GetDlgItem(IDC_BTN_FILEPLAYPAUSE)->EnableWindow(TRUE); GetDlgItem(IDC_BTN_FILESTOP)->EnableWindow(TRUE); GetDlgItem(IDC_BTN_FILESLOW)->EnableWindow(TRUE); GetDlgItem(IDC_BTN_FILEFAST)->EnableWindow(TRUE); } // 实时接收数据显示功能 else { // 停止文件回放 OnBnClickedBtnFilestop(); GetDlgItem(IDC_BTN_OPENFILE)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_FILEPLAYPAUSE)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_FILESTOP)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_FILESLOW)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_FILEFAST)->EnableWindow(FALSE); g_bWorkMode = false; // 实时 } } void CShowReplayDlg::OnDestroy() { CDialogEx::OnDestroy(); // 停止文件回放 OnBnClickedBtnFilestop(); } // 判断进程是否正在运行函数 返回0说明没有运行 DWORD CShowReplayDlg::GetProcessIdFromName(LPCTSTR name) { PROCESSENTRY32 pe; DWORD id = 0; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); pe.dwSize = sizeof(PROCESSENTRY32); if( !Process32First(hSnapshot,&pe) ) return 0; while(1) { pe.dwSize = sizeof(PROCESSENTRY32); if( Process32Next(hSnapshot,&pe)==FALSE ) break; if(strcmp(pe.szExeFile,name) == 0) { id = pe.th32ProcessID; break; } } CloseHandle(hSnapshot); return id; } LRESULT CShowReplayDlg::ReturnPayloadTypeWarning(WPARAM wParam, LPARAM lParam) { UpdateData(FALSE); return 0; }