前言:这一篇,分为三个部分,第一部分是添加对简易播放器的补充,第二部分是解码器的安装、配置。
简易播放器的补充
主要内容:添加对双击全屏的代码
注意:有些朋友可能会想,这个有这么麻烦吗,直接添加对IDC_VIDEOWND的STN_CLICKED响应不就行了,你可以添加一下对该消息的响应,就会明白了,根本执行不进去!这是为什么呢,主要是因为视频信号已经覆盖在图片控件上面了,所以点击的时候根本接收不到点击消息,当然也就没有办法执行我们写在双击响应里面的代码了。由此可知我们可以拦截双击动作,然后对拦截的消息添加处理代码,要实现拦截就先添加CplayerDlg中的PreTranslateMessage()虚函数,此函数主要是为了方便用户对消息的处理
实现代码如下:
- BOOL CPlayerDlg::PreTranslateMessage(MSG* pMsg)
- {
-
- if (pMsg->message == WM_KEYDOWN)
- {
- if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
- {
- RestoreFromFullScreen();
- return 1;
- }
- }
- if(pMsg->message==WM_LBUTTONDBLCLK)
- {
- CPoint pt;
- pt.x=LOWORD(pMsg->lParam);
- pt.y=HIWORD(pMsg->lParam);
-
- CRect rect;
- GetDlgItem(IDC_VIDEOWND)->GetWindowRect(&rect);
- this->ScreenToClient(&rect);
-
- CRgn rgn;
- rgn.CreateEllipticRgnIndirect(&rect);
-
- if(this->GetFullScreen())
- {
- this->m_VideoWindow->put_FullScreenMode(OAFALSE);
- return true;
- }
-
- if(rgn.PtInRegion(pt))
- {
- RestoreFromFullScreen();
- return true;
- }
- }
-
- return CDialog::PreTranslateMessage(pMsg);
- }
上面我们先添加了对按键的响应,主要是为了方便用户在全屏状态时,通过按“ESC”键来返回原来的状态,代码如下:
- if (pMsg->message == WM_KEYDOWN)
- {
- if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
- {
- RestoreFromFullScreen();
- return 1;
- }
- }
然后是添加对左键双击信息的响应,消息为WM_LBUTTONDBLCLK
首先是获取双击点的坐标,用pt.x=LOWORD(pMsg->lParam);获取X坐标, pt.y=HIWORD(pMsg->lParam);来获取Y坐标,然后根据显示窗口的大小(IDC_VIDEOWND)创建一个Rgn对象,然后判断当前的点是否在这个RGN区域内,如果在,就根据当前的状态来放大和缩小
其中有个函数RestoreFromFullScreen()主要是根据当前的显示状态来放大和缩小窗口的,代码如下:
- bool CPlayerDlg::RestoreFromFullScreen()
- {
- if (this->m_Graph)
- {
- if (this->GetFullScreen())
- {
- this->SetFullScreen(FALSE);
- return true;
- }else
- {
- this->SetFullScreen(TRUE);
- return true;
- }
- }
- return false;
- }
以上就实现了双击全屏和双击退出全屏,但你可能会发现这里还是存在了点问题,主要是,全屏后,鼠标不见了,下面我们采用另一种方法来实现全屏。
1、先申请几个CPlayerDlg的成员变量
- public:
- WINDOWPLACEMENT m_OldWndPlacement;
- CRect m_OldPlayWndRect;
- CRect m_OldProgressRect;
- CRect m_OldOpenBtnRect;
- CRect m_OldPlayBtnRect;
- CRect m_OldPauseBtnRect;
- CRect m_OldStopBtnRect;
- BOOL m_bFullScreen;
初始化时,将m_bFullScreen=false;其它变量无需初始化。
2、先贴实现代码,等下讲解
先将RestoreFromFullScreen()函数更改为以下代码:
- bool CPlayerDlg::RestoreFromFullScreen()
- {
- if (this->m_Graph)
- {
- this->SetFullScreen2();
- return true;
- }
- return false;
- }
SetFullScreen2()是新实现的函数,实现代码如下:
- bool CPlayerDlg::SetFullScreen2()
- {
- if(m_bFullScreen)
- {
- ModifyStyle(WS_POPUP,WS_CAPTION);
-
- SetWindowPlacement(&m_OldWndPlacement);
-
-
- this->m_VideoWindowPlay.SetWindowPos(&wndTop,m_OldPlayWndRect.left,m_OldPlayWndRect.top,m_OldPlayWndRect.Width(),m_OldPlayWndRect.Height(),SWP_NOACTIVATE);
-
- this->SetDisplayWindow(m_VideoWindowPlay.GetSafeHwnd());
-
- this->GetDlgItem(IDC_PROGRESS)->MoveWindow(m_OldProgressRect.left,m_OldProgressRect.top,m_OldProgressRect.Width(),m_OldProgressRect.Height(),true);
- this->GetDlgItem(IDC_BTN_OPEN)->MoveWindow(m_OldOpenBtnRect.left,m_OldOpenBtnRect.top,m_OldOpenBtnRect.Width(),m_OldOpenBtnRect.Height(),true);
- this->GetDlgItem(IDC_BTN_PLAY)->MoveWindow(m_OldPlayBtnRect.left,m_OldPlayBtnRect.top,m_OldPlayBtnRect.Width(),m_OldPlayBtnRect.Height(),true);
- this->GetDlgItem(IDC_BTN_PAUSE)->MoveWindow(m_OldPauseBtnRect.left,m_OldPauseBtnRect.top,m_OldPauseBtnRect.Width(),m_OldPauseBtnRect.Height(),true);
- this->GetDlgItem(IDC_BTN_STOP)->MoveWindow(m_OldStopBtnRect.left,m_OldStopBtnRect.top,m_OldStopBtnRect.Width(),m_OldStopBtnRect.Height(),true);
-
- m_bFullScreen=false;
- return true;
-
- }else
- {
-
- GetWindowPlacement(&m_OldWndPlacement);
- CRect m_RectOfCurrentWindow,m_RectOfClient;
- GetWindowRect(&m_RectOfCurrentWindow);
- RepositionBars(0,0xffff,AFX_IDW_PANE_FIRST,reposQuery,&m_RectOfClient);
- ClientToScreen(&m_RectOfClient);
- int nFullWidth = GetSystemMetrics(SM_CXSCREEN);
- int nFullHeight = GetSystemMetrics(SM_CYSCREEN);
- CRect m_FSRect;
- m_FSRect.left = m_RectOfCurrentWindow.left-m_RectOfClient.left;
- m_FSRect.top = m_RectOfCurrentWindow.top - m_RectOfClient.top;
- m_FSRect.right = m_RectOfCurrentWindow.right - m_RectOfClient.right+nFullWidth;
- m_FSRect.bottom = m_RectOfCurrentWindow.bottom - m_RectOfClient.bottom + nFullHeight;
- MoveWindow(&m_FSRect,TRUE);
-
- CRect rect;
- ::GetWindowRect(::GetDesktopWindow(),rect);
-
-
- this->m_VideoWindowPlay.GetWindowRect(this->m_OldPlayWndRect);
- this->GetDlgItem(IDC_PROGRESS)->GetWindowRect(m_OldProgressRect);
- this->GetDlgItem(IDC_BTN_OPEN)->GetWindowRect(m_OldOpenBtnRect);
- this->GetDlgItem(IDC_BTN_PLAY)->GetWindowRect(m_OldPlayBtnRect);
- this->GetDlgItem(IDC_BTN_PAUSE)->GetWindowRect(m_OldPauseBtnRect);
- this->GetDlgItem(IDC_BTN_STOP)->GetWindowRect(m_OldStopBtnRect);
-
-
- this->m_VideoWindowPlay.SetWindowPos(&wndTop,rect.left,rect.top,rect.Width(),rect.Height()-100,SWP_NOACTIVATE);
-
- this->m_VideoWindow->put_Left(rect.left);
- this->m_VideoWindow->put_Top(rect.top);
- this->m_VideoWindow->put_Width(rect.right - rect.left);
- this->m_VideoWindow->put_Height( rect.bottom - rect.top);
-
-
- this->GetDlgItem(IDC_PROGRESS)->MoveWindow(rect.left,rect.bottom-90,rect.Width(),20,true);
- CRect rectTemp;
- this->GetDlgItem(IDC_BTN_OPEN)->GetWindowRect(rectTemp);
- this->GetDlgItem(IDC_BTN_OPEN)->MoveWindow(rect.left+rect.Width()/2-300,rect.bottom-50,rectTemp.Width(),rectTemp.Height(),true);
- this->GetDlgItem(IDC_BTN_PLAY)->MoveWindow(rect.left+rect.Width()/2-100,rect.bottom-50,rectTemp.Width(),rectTemp.Height(),true);
- this->GetDlgItem(IDC_BTN_PAUSE)->MoveWindow(rect.left+rect.Width()/2+100,rect.bottom-50,rectTemp.Width(),rectTemp.Height(),true);
- this->GetDlgItem(IDC_BTN_STOP)->MoveWindow(rect.left+rect.Width()/2+300,rect.bottom-50,rectTemp.Width(),rectTemp.Height(),true);
-
- ShowCaret();
-
- m_bFullScreen=true;
- return true;
- }
- return false;
- }
代码讲解:
这里只讲解SetFullScreen2()的实现过程:
首先根据m_bFullScreen的值来判断当前窗口是全屏(值为TRUE)还是缩小状态(值为FALSE),如果全屏则缩小,如果缩小状态则全屏
先讲ELSE的全屏部分
先用GetWindowPlacement(&m_OldWndPlacement);函数保存当前框架的位置信息;
通过下面代码实现全屏
- CRect m_RectOfCurrentWindow,m_RectOfClient;
- GetWindowRect(&m_RectOfCurrentWindow);
- RepositionBars(0,0xffff,AFX_IDW_PANE_FIRST,reposQuery,&m_RectOfClient);
- ClientToScreen(&m_RectOfClient);
- int nFullWidth = GetSystemMetrics(SM_CXSCREEN);
- int nFullHeight = GetSystemMetrics(SM_CYSCREEN);
- CRect m_FSRect;
- m_FSRect.left = m_RectOfCurrentWindow.left-m_RectOfClient.left;
- m_FSRect.top = m_RectOfCurrentWindow.top - m_RectOfClient.top;
- m_FSRect.right = m_RectOfCurrentWindow.right - m_RectOfClient.right+nFullWidth;
- m_FSRect.bottom = m_RectOfCurrentWindow.bottom - m_RectOfClient.bottom + nFullHeight;
- MoveWindow(&m_FSRect,TRUE);
然后是保存原来各个控件的位置,以便缩小时还原,代码如下:
-
- this->m_VideoWindowPlay.GetWindowRect(this->m_OldPlayWndRect);
- this->GetDlgItem(IDC_PROGRESS)->GetWindowRect(m_OldProgressRect);
- this->GetDlgItem(IDC_BTN_OPEN)->GetWindowRect(m_OldOpenBtnRect);
- this->GetDlgItem(IDC_BTN_PLAY)->GetWindowRect(m_OldPlayBtnRect);
- this->GetDlgItem(IDC_BTN_PAUSE)->GetWindowRect(m_OldPauseBtnRect);
- this->GetDlgItem(IDC_BTN_STOP)->GetWindowRect(m_OldStopBtnRect);
再下面是设置播放窗口的位置及视频显示窗口的大小
- CRect rect;
- ::GetWindowRect(::GetDesktopWindow(),rect);
-
- this->m_VideoWindowPlay.SetWindowPos(&wndTop,rect.left,rect.top,rect.Width(),rect.Height()-100,SWP_NOACTIVATE);
-
- this->m_VideoWindow->put_Left(rect.left);
- this->m_VideoWindow->put_Top(rect.top);
- this->m_VideoWindow->put_Width(rect.right - rect.left);
- this->m_VideoWindow->put_Height( rect.bottom - rect.top);
然后是设置各个控件在放大后的新位置
-
- this->GetDlgItem(IDC_PROGRESS)->MoveWindow(rect.left,rect.bottom-90,rect.Width(),20,true);
- CRect rectTemp;
- this->GetDlgItem(IDC_BTN_OPEN)->GetWindowRect(rectTemp);
- this->GetDlgItem(IDC_BTN_OPEN)->MoveWindow(rect.left+rect.Width()/2-300,rect.bottom-50,rectTemp.Width(),rectTemp.Height(),true);
- this->GetDlgItem(IDC_BTN_PLAY)->MoveWindow(rect.left+rect.Width()/2-100,rect.bottom-50,rectTemp.Width(),rectTemp.Height(),true);
- this->GetDlgItem(IDC_BTN_PAUSE)->MoveWindow(rect.left+rect.Width()/2+100,rect.bottom-50,rectTemp.Width(),rectTemp.Height(),true);
- this->GetDlgItem(IDC_BTN_STOP)->MoveWindow(rect.left+rect.Width()/2+300,rect.bottom-50,rectTemp.Width(),rectTemp.Height(),true);
最后是显示鼠标语句,及设置m_bFullScreen,代码如下:
- ShowCaret();
- m_bFullScreen=true;
下面是IF语句部分的讲解:
缩小时正好是放大的反过程,相比之下,比前面的步骤要简单很多
首先用SetWindowPlacement(&m_OldWndPlacement);还原框架的大小及位置
然后是还原视频显示窗口的位置及大小,因为我们已经保存了以前位置,所以直接用SetWindowPos就完全可以实现了。
- this->m_VideoWindowPlay.SetWindowPos(&wndTop,m_OldPlayWndRect.left,m_OldPlayWndRect.top,m_OldPlayWndRect.Width(),m_OldPlayWndRect.Height(),SWP_NOACTIVATE);
设置视频显示大小
- this->SetDisplayWindow(m_VideoWindowPlay.GetSafeHwnd());
还原其它控件位置
- this->GetDlgItem(IDC_PROGRESS)->MoveWindow(m_OldProgressRect.left,m_OldProgressRect.top,m_OldProgressRect.Width(),m_OldProgressRect.Height(),true);
- this->GetDlgItem(IDC_BTN_OPEN)->MoveWindow(m_OldOpenBtnRect.left,m_OldOpenBtnRect.top,m_OldOpenBtnRect.Width(),m_OldOpenBtnRect.Height(),true);
- this->GetDlgItem(IDC_BTN_PLAY)->MoveWindow(m_OldPlayBtnRect.left,m_OldPlayBtnRect.top,m_OldPlayBtnRect.Width(),m_OldPlayBtnRect.Height(),true);
- this->GetDlgItem(IDC_BTN_PAUSE)->MoveWindow(m_OldPauseBtnRect.left,m_OldPauseBtnRect.top,m_OldPauseBtnRect.Width(),m_OldPauseBtnRect.Height(),true);
- this->GetDlgItem(IDC_BTN_STOP)->MoveWindow(m_OldStopBtnRect.left,m_OldStopBtnRect.top,m_OldStopBtnRect.Width(),m_OldStopBtnRect.Height(),true);
-
- m_bFullScreen=false;
放大时的效果图:
缩小图:
解码器的安装及配置
解码器我使用的是K-Lite解码器,它能够实现全格式的解码
一、安装
到下面的位置去下载K-Lite解码器,我上传上去的,不要分,就是我现在使用的版本,下载,根据默认选项安装即可。
http://download.csdn.net/detail/harvic880925/4575369
二、配置
在“开始”-》“所有程序”-》“K-Lite codec pack”-》“configuration”-》“ffdshow video decoder”
选中左边栏中的“codecs”,将左边的“decoder”列,全部选择上其中一个解码器,部分截图如下,其它类似:
配置好之后,即可播放任意格式的视频了。
至此,我们就基本实现了全格式的播放器了
本文的源码下载地址:
http://download.csdn.net/detail/harvic880925/4575507 不收分,有需要的朋友可以去下载
声明:本文仅供交流,如需转载,请标明出处哦!
第二篇就先写到这吧,下篇将讲解GraphEdit.exe的使用方法,最后一篇讲解如何用代码连接指定FILTER。