C# wpf视频控件实现全屏显示功能(vlc全屏、视频SDK全屏)

由于最近需要在项目中使用视频全屏的功能,而因为使用了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

你可能感兴趣的:(C#)