由于最近需要在项目中使用视频全屏的功能,而因为使用了vlc来实现视频播放处理,vlc自带的视频全屏功能需要在顶级窗口中使用,经过测试,一直无法实现全屏。
项目中需要实现多屏视频显示,因此采用了wpf的自定义控件的形式,控件中使用vlc的视频处理,如下部分代码所示:
如上所示,在wpf中使用winform的自定义控件,现在需要把视频控件"VideoViewHandler"实现全屏显示,参考网上的博客设置,使用如下处理,其中根据自身项目做了一些修改,因为是在wpf项目中使用winfrom的控件,如下:
public class FullScreenHelper
{
///
/// 是否全屏
///
public bool IsFullScreen { set; get; } = false;
///
/// 父级容器句柄
///
IntPtr OldWndParent { set; get; } = IntPtr.Zero;
///
/// 父级容器位置
///
WINDOWPLACEMENT OldWndPlacement { set; get; } = new WINDOWPLACEMENT();
///
/// 需要全屏的视频控件
///
private Control VideoControl { set; get; } = null;
///
/// 父级容器
///
WindowsFormsHost FormsHost { set; get; }
///
///
///
/// 需要实现全屏的控件
/// 父级容器
public FullScreenHelper(Control control, WindowsFormsHost formsHost)
{
VideoControl = control;
OldWndParent = formsHost.Handle;
FormsHost = formsHost;
}
public struct POINT
{
int x;
int y;
};
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
};
///
/// 锁定指定窗口,禁止它更新。同时只能有一个窗口处于锁定状态。锁定指定窗口,禁止它更新。同时只能有一个窗口处于锁定状态
///
///
///
[DllImport("User32.dll")]
public static extern bool LockWindowUpdate(IntPtr hWndLock);
///
/// 函数来设置弹出式窗口,层叠窗口或子窗口的父窗口。新的窗口与窗口必须属于同一应用程序
///
///
///
///
[DllImport("User32.dll")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
///
/// 函数设置指定窗口的显示状态和恢复,最大化,最小化位置。函数功能: 函及原型
///
///
///
///
[DllImport("User32.dll")]
public static extern bool SetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
///
/// 函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号
///
///
///
[DllImport("User32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
///
/// 该函数返回桌面窗口的句柄。桌面窗口覆盖整个屏幕。桌面窗口是一个要在其上绘制所有的图标和其他窗口的区域
///
///
[DllImport("User32.dll")]
public static extern IntPtr GetDesktopWindow();
///
/// 函数名。该函数返回指定窗口的显示状态以及被恢复的、最大化的和最小化的窗口位置
///
///
///
///
[DllImport("User32.dll")]
public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
///
/// 是用于得到被定义的系统数据或者系统配置信息的一个专有名词
///
///
///
[DllImport("User32.dll")]
public static extern int GetSystemMetrics(int nIndex);
[DllImport("user32.dll", EntryPoint = "GetParent", SetLastError = true)]
public static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int Width, int Height, int flags);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern System.IntPtr GetForegroundWindow();
[DllImport("user32")]
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
[DllImport("user32.dll")]
public static extern uint ScreenToClient(IntPtr hwnd, ref POINT p);
public void FullScreen(bool flag)
{
IsFullScreen = flag;
if (!IsFullScreen)
{
LockWindowUpdate(VideoControl.Handle);
SetParent(VideoControl.Handle, OldWndParent);
//SetWindowPlacement(VideoControl.Handle, ref m_OldWndPlacement);
FormsHost.Child = VideoControl; /*需要再次把视频控件设置在父容器中,否则会显示在无标题窗口中*/
SetForegroundWindow(OldWndParent);
SetForegroundWindow(VideoControl.Handle);
LockWindowUpdate(IntPtr.Zero);
}
else
{
//GetWindowPlacement(VideoControl.Parent.Handle, ref m_OldWndPlacement);
int nScreenWidth = GetSystemMetrics(0);
int nScreenHeight = GetSystemMetrics(1);
//m_OldWndParent = GetParent(VideoControl.Parent.Handle);
SetParent(VideoControl.Handle, GetDesktopWindow());
WINDOWPLACEMENT wp1 = new WINDOWPLACEMENT();
wp1.length = (uint)Marshal.SizeOf(wp1);
wp1.showCmd = 1;
wp1.rcNormalPosition.left = 0;
wp1.rcNormalPosition.top = 0;
wp1.rcNormalPosition.right = nScreenWidth;
wp1.rcNormalPosition.bottom = nScreenHeight;
SetWindowPlacement(VideoControl.Handle, ref wp1);
SetForegroundWindow(GetDesktopWindow());
SetForegroundWindow(VideoControl.Handle);
}
}
public struct WINDOWPLACEMENT
{
public uint length;
public uint flags;
public uint showCmd;
public POINT ptMinPosition;
public POINT ptMaxPosition;
public RECT rcNormalPosition;
};
}
其中在构造函数和进行全屏退出时做了一些修改,退出全屏时需要把视频控件重新赋值到父级容器中,否则会出现,退出全屏时视频控件会显示在独立的无标题窗口中。
最后,为视频控件"VideoViewHandler"添加键盘事件,实现按键退出全屏,在这里需要注意,使用vlc播放时,控件中貌似无法接收鼠标事件,所以不实现双击退出全屏的功能了。
VideoViewHandler.KeyUp += VideoViewHandler_KeyUp;
private void VideoViewHandler_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
// ESC 退出全屏
if (FullScreenHelper.IsFullScreen && e.KeyCode == System.Windows.Forms.Keys.Escape)
{
FullScreenHelper.FullScreen(false);
}
}
至此,完成了视频全屏的功能。
参考博客:https://blog.csdn.net/boonya/article/details/79537568