MFC 基于VLC的视频播放器(五)---全屏显示以及按钮函数的实现

北京时间16点43分 2018年12月28号

前面的文章完成了双击播放列表播放文件以及播放时的时间轴显示,这次将实现全屏显示以及按钮函数的实现。

对于全屏显示,想法是处理PICTURE控件的双击显示消息函数,但是发现在添加处理函数后,双击后程序并不响应消息函数。

后来发现是libvlc自己就拦截处理了播放时控件双击函数,所以我们写的程序才没有响应。

所以,想要实现双击全屏有两种方法:

1、http://blog.jianchihu.net/player-based-on-libvlc.html

这里面讲到的是添加一个定时器和回调。

1)在MFC对话框程序中,首先添加一个控件,这里我添加了一个Picture Contron:IDC_PLAYWND;
2)获得IDC_PLAYWND控件句柄;

 

1

gPlayHwnd = GetDlgItem(IDC_PLAYWND)->GetSafeHwnd();

3)让libVLC播放对象设置gPlayHwnd 为播放窗口句柄,这样libVLC播放窗口就成为IDC_PLAYWND控件的子窗口;

 

1

libvlc_media_player_set_hwnd (mp, gPlayHwnd );

4)开始播放后创建一个定时器;

C++

 

1

::SetTimer(NULL, 1, 1000, TimeProc);

5)定时器回调函数以及处理过程如下:

C++

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

//定时器回调

void CALLBACK TimeProc(

    HWND hwnd,

    UINT message,

    UINT idTimer,

    DWORD dwTime)

{

    EnumChildWindows(gPlayHwnd, EnumerateVLC, NULL);

}

 

BOOL CALLBACK EnumerateVLC(HWND hWndvlc, LPARAM lParam)

{

    TCHAR szWndTitle[1024];

    int nLen = GetWindowText(hWndvlc, szWndTitle, 1024);

    if (0 != nLen)

    {

        //禁用鼠标消息

        EnableWindow(hWndvlc, FALSE);

        KillTimer(NULL, 1);

    }

    

    return TRUE;

}

 

在上述代码中,我们通过之前得到的IDC_PLAYWND控件句柄枚举得到子窗口VLC播放窗口句柄,接着通过EnableWindow函数禁止VLC播放窗口接受鼠标键盘输入。这时我们的程序就可以响应鼠标点击libVLC播放窗口的消息了;
6)设置全屏,主要是设置IDC_PLAYWND控件全屏时占满整个屏幕,然后隐藏其他控件以及标题栏,这样VLC子窗口就可以全屏播放了。不需要使用libvlc_set_fullscreen这个内置api,使用这个api无法达到效果。

 

2、第二种方法就是在vlclib处理拦截双击信息之前,我们添加处理函数PreTranslateMessage,拦截信息。

添加相应的函数,流程大概就是接受到双击的消息后,判断是不是在播放的PICTURE控件上,如果是,则执行全屏的函数OnDblclkPlay();如果不在PICTURE控件上,则不做处理。

BOOL CVlcPlayerCsdnDlg::PreTranslateMessage(MSG* pMsg)
{
	//双击放大整个屏幕
	if (pMsg->message == WM_LBUTTONDBLCLK)  //只要接收到双击就放大屏幕
	{
		CRect rect;
		GetDlgItem(IDC_PLAY)->GetWindowRect(rect);
		//ScreenToClient(rect);

		if (rect.PtInRect(pMsg->pt))
			OnDblclkPlay();
	}
	//屏蔽ESC按键的退出机制,因为一般的对话框程序一按到ESC就退出了
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE)
	{
		if (bFullScreen)//如果是全屏状态下,不退出。而是退出全屏
		{
			OnDblclkPlay();
			return TRUE;
		}
		else
			return TRUE;
	}
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
		return TRUE;
	return CDialogEx::PreTranslateMessage(pMsg);
}

OnDblclkPlay是全屏显示的函数,全屏的函数首先是放大整个对话框,隐藏其他的控件和标题栏后,放大PICTURE控件,它的定义为:

void CVlcPlayerCsdnDlg::OnDblclkPlay()
{
	if (!bFullScreen)
	{
		//播放列表在全屏时出错处理
		if (m_listPlay.IsWindowVisible()) isshowlist = TRUE;
		else isshowlist = FALSE;
		bFullScreen = true;

		//获取系统屏幕宽高  
		int g_iCurScreenWidth = GetSystemMetrics(SM_CXSCREEN);
		int g_iCurScreenHeight = GetSystemMetrics(SM_CYSCREEN);

		//用m_struOldWndpl得到当前窗口的显示状态和窗体位置,以供退出全屏后使用  
		GetWindowPlacement(&m_struOldWndpl);
		GetDlgItem(IDC_PLAY)->GetWindowPlacement(&m_struOldWndpPic);

		//计算出窗口全屏显示客户端所应该设置的窗口大小,主要为了将不需要显示的窗体边框等部分排除在屏幕外  
		CRect rectWholeDlg;
		CRect rectClient;
		GetWindowRect(&rectWholeDlg);//得到当前窗体的总的相对于屏幕的坐标  
		RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery, &rectClient);//得到客户区窗口坐标  
		ClientToScreen(&rectClient);//将客户区相对窗体的坐标转为相对屏幕坐标  
									//GetDlgItem(IDC_STATIC_PICSHOW)->GetWindowRect(rectClient);//得到PICTURE控件坐标  

		rectFullScreen.left = rectWholeDlg.left - rectClient.left;
		rectFullScreen.top = rectWholeDlg.top - rectClient.top;
		rectFullScreen.right = rectWholeDlg.right + g_iCurScreenWidth - rectClient.right;
		rectFullScreen.bottom = rectWholeDlg.bottom + g_iCurScreenHeight - rectClient.bottom;

		//设置窗口对象参数,为全屏做好准备并进入全屏状态  
		WINDOWPLACEMENT struWndpl;
		struWndpl.length = sizeof(WINDOWPLACEMENT);
		struWndpl.flags = 0;
		struWndpl.showCmd = SW_SHOWNORMAL;
		struWndpl.rcNormalPosition = rectFullScreen;
		SetWindowPlacement(&struWndpl);//该函数设置指定窗口的显示状态和显示大小位置等,是我们该程序最为重要的函数  



		GetDlgItem(IDC_BUTTON_UP)->ShowWindow(FALSE);
		GetDlgItem(IDC_BUTTON_PLAY)->ShowWindow(FALSE);
		GetDlgItem(IDC_BUTTON_DOWN)->ShowWindow(FALSE);
		GetDlgItem(IDC_BUTTON_FORWARD)->ShowWindow(FALSE);
		GetDlgItem(IDC_BUTTON_BACKWARD)->ShowWindow(FALSE);
		GetDlgItem(IDC_BUTTON_SHOWLIST)->ShowWindow(FALSE);
		
		GetDlgItem(IDC_LIST_PLAY)->ShowWindow(FALSE);
		GetDlgItem(IDC_SLIDER1)->ShowWindow(FALSE);
		GetDlgItem(IDC_STATIC)->ShowWindow(FALSE);
		GetDlgItem(IDC_LIST_MUSINFO)->ShowWindow(FALSE);
		//将PICTURE控件的坐标设为全屏大小  
		GetDlgItem(IDC_PLAY)->MoveWindow(CRect(0, 0, g_iCurScreenWidth, g_iCurScreenHeight));

		

	}
	else
	{
		GetDlgItem(IDC_PLAY)->SetWindowPlacement(&m_struOldWndpPic);
		SetWindowPlacement(&m_struOldWndpl);
		bFullScreen = false;
		GetDlgItem(IDC_BUTTON_UP)->ShowWindow(TRUE);
		GetDlgItem(IDC_BUTTON_PLAY)->ShowWindow(TRUE);
		GetDlgItem(IDC_BUTTON_DOWN)->ShowWindow(TRUE);
		GetDlgItem(IDC_BUTTON_FORWARD)->ShowWindow(TRUE);
		GetDlgItem(IDC_BUTTON_BACKWARD)->ShowWindow(TRUE);
		GetDlgItem(IDC_BUTTON_SHOWLIST)->ShowWindow(TRUE);

		GetDlgItem(IDC_SLIDER1)->ShowWindow(TRUE);
		GetDlgItem(IDC_STATIC)->ShowWindow(TRUE);

		if (isshowlist == TRUE)
		{
			GetDlgItem(IDC_LIST_PLAY)->ShowWindow(TRUE);
			GetDlgItem(IDC_LIST_MUSINFO)->ShowWindow(TRUE);
		}
		else
		{
			GetDlgItem(IDC_LIST_MUSINFO)->ShowWindow(FALSE);
			GetDlgItem(IDC_LIST_PLAY)->ShowWindow(FALSE);
		}
		
	}
}

这两个函数用到的变量定义有:

	BOOL bFullScreen;
	CRect rectFullScreen;
	WINDOWPLACEMENT m_struOldWndpl;//结构中包含了有关窗口在屏幕上位置的信息 
	WINDOWPLACEMENT m_struOldWndpPic;//PICTURE控件在屏幕上位置的信息
	
	BOOL isshowlist;//列表是否显示了

运行,效果如下(图一正常情况,图二为放大后):

好啦,全屏显示的代码就这样啦,接下来就是按钮的实现了。直接为那六个按钮添加消息处理函数,然后代码如下:

void CVlcPlayerCsdnDlg::OnBnClickedButtonPlay()  //播放按钮
{
	if (!m_cAVPlayer.IsOpen())
	{
		return;
	}

	if (m_cAVPlayer.IsPlaying())
	{
		m_cAVPlayer.Pause();
	
	}
	else
	{
		m_cAVPlayer.Play();

	}
}
void CVlcPlayerCsdnDlg::OnBnClickedButtonUp() //上一集按钮
{
	int nIndex = m_listPlay.GetCurSel();
	if (LB_ERR == nIndex)
	{
		return;
	}

	if (nIndex - 1 < 0)
	{
		nIndex = m_listPlay.GetCount();
	}

	m_listPlay.SetCurSel(nIndex - 1);
	OnDblclkListPlay();
}
void CVlcPlayerCsdnDlg::OnBnClickedButtonDown() //下一集按钮
{
	int nIndex = m_listPlay.GetCurSel();
	if (LB_ERR == nIndex)
	{
		return;
	}

	if (nIndex + 1 >= m_listPlay.GetCount())
	{
		nIndex = -1;
	}

	m_listPlay.SetCurSel(nIndex + 1);
	OnDblclkListPlay();
}
void CVlcPlayerCsdnDlg::OnBnClickedButtonForward() //快进
{
	m_cAVPlayer.SeekBackward();
}


void CVlcPlayerCsdnDlg::OnBnClickedButtonBackward()  //快退
{
	m_cAVPlayer.SeekForward();
}


void CVlcPlayerCsdnDlg::OnBnClickedButtonShowlist()  //显示播放列表按钮
{
	ShowPlaylist(!m_listPlay.IsWindowVisible());
}

好啦,现在基本的完成啦,这里有源码下载地址。大家如果觉得在播放音频文件时PICTURE控件为空,可以再播放一个gif动画,在这里我就只上传源码(下载地址——mp3显示gif动画、系统有菜单栏)。

注意:1、本人是萌新,大佬们可以直接跳过阅读我的文章,写这个目的就是为了赚点分数以后可以用,当然也是想和其他萌新一起学习。

2、我会尽力快点更新,如果有什么问题大家可以在底下评论,我看到便会回复的,我的个人邮箱iszhangyongxin@163.com

3、每一期我都会尽量放上源代码,希望能帮到大家的学习。

已标记关键词 清除标记
相关推荐