参考:自定义控件使其填充方格且自动变换大小文章,据此生成了多分屏的视频播放器。这里需要注意Controls的数组的无序性。
这里看下自定义控件的代码:
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Data;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- using CvNetVideo.Event;
- using System.Runtime.InteropServices;
- using CvNetVideo.Play;
- using static CvNetVideo.UCVideo;
-
- namespace CvNetVideo
- {
- [Guid("f3943464-829d-4bb8-8b05-10516831ceed")]
- //指示应用该属性的对象对COM可见
- [ComVisible(true)]
- //将事件接收接口连接到托管类
- [ComSourceInterfacesAttribute(typeof(MulitiControlEvents))]
- public partial class UserControlVideo : UserControl
- {
- #region 属性变量
- /// <summary>
- /// 选择的分屏索引
- /// </summary>
- public int SelectedIndex { set; get; }
-
- /// <summary>
- /// 操作的分屏索引
- /// </summary>
- private int OperationIndex;
-
-
- /// <summary>
- /// 控件原始宽度
- /// </summary>
- public int OldWidth { set; get; }
- /// <summary>
- /// 控件原始高度
- /// </summary>
- public int OldHeight { set; get; }
- public bool IsFullScreenInSystem { get; set; }
-
- public bool IsFullScreen = false;
-
- #endregion
-
- public UserControlVideo()
- {
- InitializeComponent();
- }
-
- # region 事件回调
-
- /// <summary>
- /// 全屏或退出全屏事件
- /// </summary>
- public event MulitiFullScreenEvent OnFullScreenEvent;
- /// <summary>
- /// 直播退出事件
- /// </summary>
- public event MulitiRealTimeLiveAllStopEvent OnRealTimeLiveAllStopEvent;
- /// <summary>
- /// 控件双击事件(控制全屏)
- /// </summary>
- public event MulitiControlDoubleClickEvent OnControlDoubleClickEvent;
- /// <summary>
- /// 异步远程视频回放事件
- /// </summary>
- public event MulitiAsyncRemoteVideoPlaybackEvent OnAsyncRemoteVideoPlaybackEvent;
- /// <summary>
- /// 发生某个事件触发事件
- /// </summary>
- public event MulitidglEventTrigger OnEventTrigger;
- /// <summary>
- /// 异步FTP文件上传事件
- /// </summary>
- public event MulitiAsyncFtpFileUploadEvent OnAsyncFtpFileUploadEvent;
- /// <summary>
- /// 实时视频播放超时事件
- /// </summary>
- public event MulitiRealtimeVideoOuttimeEvent OnRealtimeVideoOuttimeEvent;
- /// <summary>
- /// OCX操作优先级通知事件
- /// </summary>
- public event MulitiRealtimeVideoPriorityNotifyEvent OnRealtimeVideoPriorityNotifyEvent;
- /// <summary>
- /// 视频截图完成回调事件
- /// </summary>
- public event MulitiScreenshotCompletedEvent OnScreenshotCompletedEvent;
- /// <summary>
- /// 视频点击选中回调事件
- /// </summary>
- public event MulitiScreenSelectEvent OnScreenSelectEvent;
- /// <summary>
- /// 视频分屏重载回调事件
- /// </summary>
- public event MulitiReloadControlScreenEvent OnReloadControlScreenEvent;
- /// <summary>
- /// 全部关闭实时视频回调事件
- /// </summary>
- public event MulitiStopAllRealtimeVideoScreenEvent OnStopAllRealtimeVideoScreenEvent;
-
- /// <summary>
- /// 视频控件选中事件回调
- /// </summary>
- /// <param name="id"></param>
- public void ControlSelectdCallback(int id)
- {
- this.SelectedIndex = id;
- this.OperationIndex = this.SelectedIndex;
- for (var i = 0; i < this.Controls.Count; i++)
- {
- UCVideo video = this.Controls[i] as UCVideo;
- if (this.SelectedIndex == video.Id)
- {
- video.BorderStyle = BorderStyle.Fixed3D;
- }
- else
- {
- video.BorderStyle = BorderStyle.FixedSingle;
- }
- }
- // 网页选中视频事件回调
- OnScreenSelectEvent?.Invoke(id);
- }
-
- /// <summary>
- /// 全屏回调事件回调
- /// </summary>
- /// <param name="id"></param>
- /// <param name="isFullScreen"></param>
- public void ControlFullScreenEventCallback(int id, bool isFullScreen)
- {
- OpenOrCloseFullScreen(id, isFullScreen);
- OnFullScreenEvent?.Invoke(id, isFullScreen);
- }
-
- /// <summary>
- /// 视频关闭事件回调
- /// </summary>
- /// <param name="id"></param>
- public void ControlRealTimeLiveAllStopEventCallback(int id)
- {
- OnRealTimeLiveAllStopEvent?.Invoke(id);
- }
-
- /// <summary>
- /// 视频双击(全屏/退出全屏)事件回调
- /// </summary>
- /// <param name="id"></param>
- /// <param name="isFullScreen"></param>
- public void ControlDoubleClickEventCallback(int id, bool isFullScreen)
- {
- OnControlDoubleClickEvent?.Invoke(id, isFullScreen);
- }
-
- /// <summary>
- /// 视频回放异步远程事件回调
- /// </summary>
- /// <param name="id"></param>
- /// <param name="json"></param>
- public void ControlAsyncRemoteVideoPlaybackEventCallback(int id, string json)
- {
- OnAsyncRemoteVideoPlaybackEvent?.Invoke(id, json);
- }
-
- /// <summary>
- /// 触发ID事件回调
- /// </summary>
- /// <param name="id"></param>
- /// <param name="eventId"></param>
- public void ControldglEventTriggerCallback(int id, int eventId)
- {
- OnEventTrigger?.Invoke(id,eventId);
- }
-
- /// <summary>
- /// 视频异步FTP文件上传事件回调
- /// </summary>
- /// <param name="id"></param>
- /// <param name="json"></param>
- public void ControlAsyncFtpFileUploadEventCallback(int id, string json)
- {
- OnAsyncFtpFileUploadEvent?.Invoke(id,json);
- }
-
- /// <summary>
- /// 实时视频播放超时事件回调
- /// </summary>
- /// <param name="id"></param>
- public void ControlRealtimeVideoOuttimeEventCallback()
- {
- OnRealtimeVideoOuttimeEvent?.Invoke();
- }
-
- /// <summary>
- /// 视频操作优先级通知回调
- /// </summary>
- /// <param name="id"></param>
- /// <param name="priority"></param>
- public void ControlRealtimeVideoPriorityNotifyEventCallback(int id, int priority)
- {
- OnRealtimeVideoPriorityNotifyEvent?.Invoke(id,priority);
- }
-
- /// <summary>
- /// 视频截图完成事件回调
- /// </summary>
- /// <param name="id"></param>
- /// <param name="fileLocation"></param>
- public void ControlScreenshotCompletedEventCallback(int id, string fileLocation)
- {
- OnScreenshotCompletedEvent?.Invoke(id,fileLocation);
- }
-
- /// <summary>
- /// 全部关闭实时视频事件回调
- /// </summary>
- public void ControlStopAllRealtimeVideoScreenEventCallback()
- {
- OnStopAllRealtimeVideoScreenEvent?.Invoke();
- }
- #endregion
-
- #region 全屏操作
- FullScreenObject fullScreenObject;
- /// <summary>
- /// 打开或关闭全屏
- /// </summary>
- public void OpenOrCloseFullScreen(int id,bool isOpen)
- {
- int Count = (int)Math.Sqrt(this.Controls.Count);
- int perWidth = OldWidth / Count;
- int perHeight = OldHeight / Count;
- if (isOpen)
- {
- OldWidth = this.Width;
- OldHeight = this.Height;
- if (fullScreenObject == null)
- {
- if (IsFullScreenInSystem)
- {
- // 系统级别的全屏
- fullScreenObject = new FullScreenHelper(this);
- }
- else
- {
- // 容器内的全屏
- fullScreenObject = new FullScreenInContainerHelper(this);
- }
- }
- fullScreenObject.FullScreen(isOpen);
- IsFullScreen = isOpen;
- Console.WriteLine("Entrance FullScreen Mode");
-
- // 全屏显示选择的屏幕视频窗口
- UCVideo fullscreenUcVideo = null;
- foreach (var ucVideo in this.Controls)
- {
- fullscreenUcVideo = ucVideo as UCVideo;
- if (id == fullscreenUcVideo.Id)
- {
-
- fullscreenUcVideo.Width = this.Width;
- fullscreenUcVideo.Height = this.Height;
- fullscreenUcVideo.Location = new Point(0, 0);
- fullscreenUcVideo.Visible = true;
- Console.WriteLine(">>>>>>>>>>>全屏Full ID=" + fullscreenUcVideo.Id);
- break;
- }
- }
- }
- else
- {
- if (fullScreenObject != null && IsFullScreen)
- {
- fullScreenObject.FullScreen(isOpen);
- IsFullScreen = isOpen;
-
- // 复位全屏元素
- UCVideo fullscreenUcVideo = null;
- foreach (var ucVideo in this.Controls)
- {
- fullscreenUcVideo = ucVideo as UCVideo;
- if (id == fullscreenUcVideo.Id)
- {
-
- fullscreenUcVideo.Width = perWidth;
- fullscreenUcVideo.Height = perHeight;
- fullscreenUcVideo.Location = new Point(fullscreenUcVideo.X, fullscreenUcVideo.Y);
- fullscreenUcVideo.Visible = true;
- Console.WriteLine(">>>>>>>>>>>复位Full ID=" + fullscreenUcVideo.Id);
- break;
- }
- }
- this.Width = OldWidth;
- this.Height = OldHeight;
- Console.WriteLine("Exit FullScreen Mode");
- }
- }
- }
-
- #endregion
-
- #region 分屏处理
- /// <summary>
- /// 获取视频对象
- /// </summary>
- /// <param name="id"></param>
- /// <returns></returns>
- public UCVideo GetUCVideoById(int id)
- {
- return this.Controls[id] as UCVideo;
- }
-
- /// 填充视频
- /// </summary>
- /// <param name="num">数量</param>
- public void FillUCVideo(int num)
- {
- // 触发重载事件
- OnReloadControlScreenEvent?.Invoke();
- this.OperationIndex = 0;
- this.Controls.Clear();
- //填充num*num个方格,现在放置的是罗列着的
- for (int i = 0; i < num * num; i++)
- {
- UCVideo uCVideo = new UCVideo();
- // 设置默认ID
- uCVideo.Id = i;
- // 注册视频选择事件
- uCVideo.ControlSelectdCallback = ControlSelectdCallback;
- // 注册视频全屏事件
- uCVideo.ControlFullScreenEventCallback = ControlFullScreenEventCallback;
- // 注册视频退出事件
- uCVideo.ControlRealTimeLiveAllStopEventCallback = ControlRealTimeLiveAllStopEventCallback;
- // 注册视频双击(全屏/退出全屏)事件
- uCVideo.ControlForDoubleClickEventCallback = ControlDoubleClickEventCallback;
- // 注册视频回放查询回调事件
- uCVideo.ControlAsyncRemoteVideoPlaybackEventCallback = ControlAsyncRemoteVideoPlaybackEventCallback;
- // 注册触发视频执行ID事件
- uCVideo.ControldglEventTriggerCallback = ControldglEventTriggerCallback;
- // 注册视频异步FTP文件上传事件
- uCVideo.ControlAsyncFtpFileUploadEventCallback = ControlAsyncFtpFileUploadEventCallback;
- // 注册实时视频播放超时事件
- //uCVideo.ControlRealtimeVideoOuttimeEventCallback = ControlRealtimeVideoOuttimeEventCallback;
- // 注册实时视频操作优先级通知事件
- uCVideo.ControlRealtimeVideoPriorityNotifyEventCallback = ControlRealtimeVideoPriorityNotifyEventCallback;
- // 注册视频截图完成回调事件
- uCVideo.ControlScreenshotCompletedEventCallback = ControlScreenshotCompletedEventCallback;
- // 是否开启桌面超时事件
- uCVideo.SetStartOuttimeListener(false);
- this.Controls.Add(uCVideo);
- }
- //定义方法,因为需要改变大小,所以单独
- this.LayoutUCVideos();
- }
-
- /// 填充视频
- /// </summary>
- /// <param name="num">数量</param>
- /// <param name="controlExeSelectd">选择代理函数</param>
- public void FillUCVideo(int num, ControlExeSelectd controlExeSelectd)
- {
- this.Controls.Clear();
- //填充num*num个方格,现在放置的是罗列着的
- for (int i = 0; i < num*num; i++)
- {
- UCVideo uCVideo = new UCVideo();
- // 设置默认ID
- uCVideo.Id = i;
- // 注册视频选择事件
- uCVideo.ControlSelectdCallback = ControlSelectdCallback;
- // 注册exe视频选择事件
- uCVideo.ControlExeSelectdCallback = controlExeSelectd;
- //注册视频全屏事件
- uCVideo.ControlFullScreenEventCallback = ControlFullScreenEventCallback;
- this.Controls.Add(uCVideo);
- }
- //定义方法,因为需要改变大小,所以单独
- this.LayoutUCVideos();
- }
-
- /// <summary>
- /// 布局视频
- /// </summary>
- /// <returns></returns>
- public void LayoutUCVideos()
- {
- OldWidth = this.Width;
- OldHeight = this.Height;
- //去除启动状态,以免开启的时候FillBtn_SizeChanged会报错
- if (this.Controls.Count == 0)
- {
- return;
- }
- //循环多少次?计算出来
- int Count = (int)Math.Sqrt(this.Controls.Count);
- //计算每个视频的的宽度和高度
- int perWidth = this.Width / Count;
- int perHeight = this.Height / Count;
-
- int Index = 0;
- int X = 0, Y = 0;
- //竖向的循环嵌套横着的循环
- for (int verticalIndex = 0; verticalIndex < Count; verticalIndex++)
- {
- Y = verticalIndex * perHeight;
- //水平向的循环
- for (int horizontalIndex = 0; horizontalIndex < Count; horizontalIndex++)
- {
- X = horizontalIndex * perWidth;
- //获取要放置的方格
- foreach (var ucVideo in this.Controls)
- {
- UCVideo video = ucVideo as UCVideo;
- if (video.Id==Index)
- {
- video.X = X;
- video.Y = Y;
- video.Width = perWidth;
- video.Height = perHeight;
- //设置当前方格的位置
- video.Location = new Point(X, Y);
- Console.WriteLine("=========ID:" + video.Id);
- break;
- }
-
- }
- //下一个方格
- Index++;
-
- }
- }
- }
- #endregion
-
- #region 控件事件
- /// <summary>
- /// 控件初始化时加载默认分屏
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void UserControlVideo_Load(object sender, EventArgs e)
- {
- FillUCVideo(4);
- LayoutUCVideos();
- }
-
- private void UserControlVideo_Resize(object sender, EventArgs e)
- {
- if (!IsFullScreen)
- {
- LayoutUCVideos();
- }
- }
- #endregion
- }
- }
关键代码处理:
- //获取要放置的方格
- foreach (var ucVideo in this.Controls)
- {
- UCVideo video = ucVideo as UCVideo;
- if (video.Id==Index)
- {
- video.X = X;
- video.Y = Y;
- video.Width = perWidth;
- video.Height = perHeight;
- //设置当前方格的位置
- video.Location = new Point(X, Y);
- Console.WriteLine("=========ID:" + video.Id);
- break;
- }
-
- }
这里的id不能理解为数组下标,因为是可变的。