我们在Windows平台实现RTSP或者RTMP播放的时候,有个功能是绕不开的,那就是播放窗口全屏。本文就以大牛直播SDK(官方)的Windows播放器为例,大概讲下大概实现:

全屏播放需要考虑的点不多:

第一:视频播放后,全屏的意义;

第二:全屏后,是否等比例显示,我们的设计原则是,之前等比例显示的,继续等比例显示,之前铺满的,继续铺满;

第三:ESC退出全屏。

本文以C++的demo为例,具体实现如下:

void nt_wrapper_render_wnd::FullScreenSwitch()
{
	if ( !::IsWindow(m_hWnd) )
		return;

	if (player_handle_ != nullptr)
	{
		player_api_.SetRenderARGBLogo(player_handle_, nullptr, 0, 0, 0, 0, 0, 0, 0);
	}

	if ( !IsFullScreen() )
	{
		if ( !IsCanFullScreen() )
			return;

		auto old_wnd = GetParent();
		if ( old_wnd == NULL )
			return;

		old_parent_wnd_ = old_wnd->m_hWnd;
		ASSERT(::IsWindow(old_parent_wnd_));

		GetWindowRect(&old_rect_);
		old_wnd->ScreenToClient(old_rect_);
	
		HMONITOR hMonitor = ::MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
		if (hMonitor == NULL)
			return;

		MONITORINFOEX mi;
		mi.cbSize = sizeof(mi);

		if ( !GetMonitorInfo(hMonitor, &mi) )
			return;


		::SetParent(m_hWnd, NULL);

		auto wnd_styles = GetWindowLongPtr(m_hWnd, GWL_STYLE);
		wnd_styles = wnd_styles & (~WS_CHILD);	
		wnd_styles |= WS_POPUP;
		::SetWindowLongPtr(m_hWnd, GWL_STYLE, wnd_styles);

		// 隐藏老窗口
		::ShowWindow(old_parent_wnd_, SW_HIDE);

		is_full_screen_ = true;

		::SetWindowPos(m_hWnd, HWND_TOP, mi.rcMonitor.left,
			mi.rcMonitor.top,
			mi.rcMonitor.right - mi.rcMonitor.left,
			mi.rcMonitor.bottom - mi.rcMonitor.top,
			SWP_FRAMECHANGED);

		::SetForegroundWindow(m_hWnd);

		::RedrawWindow(m_hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW
			| RDW_ERASE);

		::RedrawWindow(NULL, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW
			| RDW_ERASE);
	}
	else
	{
		::ShowWindow(old_parent_wnd_, SW_SHOW);

		auto wnd_styles = GetWindowLongPtr(m_hWnd, GWL_STYLE);
		wnd_styles = wnd_styles & (~WS_POPUP);
		wnd_styles |= WS_CHILD;
		auto ret = SetWindowLongPtr(m_hWnd, GWL_STYLE, wnd_styles);

		::SetParent(m_hWnd, old_parent_wnd_);

		is_full_screen_ = false;

		MoveWindow(old_rect_, TRUE);
	}
}

ESC处理:

void nt_wrapper_render_wnd::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	// TODO: Add your message handler code here and/or call default
	
	// 全屏的时候,按ESC将退出全屏
	if ( nChar == VK_ESCAPE )
	{
		if ( IsFullScreen() )
		{
			FullScreenSwitch();
		}
	}

	CWnd::OnChar(nChar, nRepCnt, nFlags);
}

C#的实现也非常简单,感兴趣的可自行研究。