前言

曾有做过一个产品,有一个功能是视频监控模块,视频监控首先想到的是视频多画面切换功能,由于前端是用WPF开发的,所以当时就做了一个多画面切换组件,效果如下:

  功能设计前提:

  由于要使用海康大华天地伟业等视频厂家的视频,对接的方式是通过各个厂家提供的SDK(官网下载),由于播放视频的时候需要传递控件的句柄(Handle),所以要在WPF中使用System.Windows.Forms下的控件Panel

  具体实现:

  1、  实现多画面类MultiView,主要提供页面初始化、设置当前画面等功能

  public static class MultiView
{
public static int CurrentModel = ;
public static Dictionary<int, CellPanel> DictPanel = null;
private static Grid OriginalGrid = null;
private static Grid TempGrid1 = new Grid();
private static Grid TempGrid2 = new Grid();
private static int MaxCellNums = ; /// <summary>
/// 初始化页面
/// </summary>
/// <param name="grid">主体</param>
/// <param name="cellNums">最大画面数</param>
public static void InitGrid(Grid grid, int cellNums)
{
MultiView.OriginalGrid = grid;
MultiView.MaxCellNums = cellNums; MultiView.DictPanel = new Dictionary<int, CellPanel>();
for (int index = ; index <= MultiView.MaxCellNums; index++)
{
CellPanel cellPanel = new CellPanel();
cellPanel.Index = index;
MultiView.DictPanel.Add(index, cellPanel);
}
} /// <summary>
/// 设置当前画面数
/// </summary>
/// <param name="model"></param>
public static void SetCurrentModel(int model)
{
switch (model)
{
case :
MultiView.SetModelByColumnAndRow(, );
break;
case :
MultiView.SetModel3();
break;
case :
MultiView.SetModelByColumnAndRow(, );
break;
case :
MultiView.SetModel6();
break;
case :
MultiView.SetModel8();
break;
case :
MultiView.SetModelByColumnAndRow(, );
break;
case :
MultiView.SetModel10();
break;
case :
MultiView.SetModelByColumnAndRow(, );
break;
case :
MultiView.SetModelByColumnAndRow(, );
break;
} MultiView.CurrentModel = model;
}
/// <summary>
/// 获取当前画面
/// </summary>
/// <returns></returns>
public static CellPanel CurrentCellPanel()
{
for (int index = ; index <= MultiView.MaxCellNums; index++)
{
if (MultiView.DictPanel[index].Selected)
{
return MultiView.DictPanel[index];
}
}
return null;
} /// <summary>
/// 通过行列数设置画面分割
/// </summary>
/// <param name="column">列</param>
/// <param name="row">行</param>
public static void SetModelByColumnAndRow(int column, int row)
{
MultiView.Clear();
MultiView.CreateColumnAndRow(MultiView.OriginalGrid, row, column); int num = ;
for (int rowIndex = ; rowIndex < row; rowIndex++)
{
for (int columnIndex = ; columnIndex < column; columnIndex++)
{
CellPanel cellPanel = MultiView.DictPanel[num];
Grid.SetColumn(cellPanel, columnIndex);
Grid.SetRow(cellPanel, rowIndex);
MultiView.OriginalGrid.Children.Add(cellPanel);
num++;
}
}
}
/// <summary>
/// 三画面
/// </summary>
public static void SetModel3()
{
MultiView.Clear();
ColumnDefinition columnDefinition1 = new ColumnDefinition();
ColumnDefinition columnDefinition2 = new ColumnDefinition();
columnDefinition1.Width = new GridLength(0.618, GridUnitType.Star);
columnDefinition2.Width = new GridLength(0.382, GridUnitType.Star);
MultiView.OriginalGrid.ColumnDefinitions.Add(columnDefinition1);
MultiView.OriginalGrid.ColumnDefinitions.Add(columnDefinition2);
CellPanel cellPanel = MultiView.DictPanel[];
Grid.SetColumn(cellPanel, );
MultiView.OriginalGrid.Children.Add(cellPanel); for (int index1 = ; index1 < ; ++index1)
{
cellPanel = MultiView.DictPanel[index1 + ];
MultiView.TempGrid1.RowDefinitions.Add(new RowDefinition());
Grid.SetRow(cellPanel, index1);
MultiView.TempGrid1.Children.Add(cellPanel);
} Grid.SetColumn(MultiView.TempGrid1, );
MultiView.OriginalGrid.Children.Add(MultiView.TempGrid1);
}
/// <summary>
/// 六画面
/// </summary>
public static void SetModel6()
{
MultiView.Clear();
MultiView.CreateColumnAndRow(MultiView.OriginalGrid, , );
MultiView.OriginalGrid.ColumnDefinitions[].Width = new GridLength(0.66, GridUnitType.Star);
MultiView.OriginalGrid.ColumnDefinitions[].Width = new GridLength(0.34, GridUnitType.Star);
MultiView.OriginalGrid.RowDefinitions[].Height = new GridLength(0.67, GridUnitType.Star);
MultiView.OriginalGrid.RowDefinitions[].Height = new GridLength(0.33, GridUnitType.Star); CellPanel cellPanel = MultiView.DictPanel[];
Grid.SetColumn(cellPanel, );
Grid.SetRow(cellPanel, );
MultiView.OriginalGrid.Children.Add(cellPanel); //p2,p3 画面
Grid.SetColumn(MultiView.TempGrid1, );
Grid.SetRow(MultiView.TempGrid1, ); for (int index = ; index < ; ++index)
{
cellPanel = MultiView.DictPanel[index + ];
MultiView.TempGrid1.RowDefinitions.Add(new RowDefinition());
Grid.SetRow(cellPanel, index);
MultiView.TempGrid1.Children.Add(cellPanel);
}
MultiView.OriginalGrid.Children.Add(MultiView.TempGrid1);
//p4,p5 画面
Grid.SetColumn(MultiView.TempGrid2, );
Grid.SetRow(MultiView.TempGrid2, ); for (int index = ; index < ; ++index)
{
cellPanel = MultiView.DictPanel[index + ]; MultiView.TempGrid2.ColumnDefinitions.Add(new ColumnDefinition());
Grid.SetColumn(cellPanel, index);
MultiView.TempGrid2.Children.Add(cellPanel);
}
MultiView.OriginalGrid.Children.Add(MultiView.TempGrid2); cellPanel = MultiView.DictPanel[];
Grid.SetRow(cellPanel, );
Grid.SetColumn(cellPanel, );
MultiView.OriginalGrid.Children.Add(cellPanel);
}
/// <summary>
/// 八画面
/// </summary>
public static void SetModel8()
{
MultiView.Clear();
MultiView.CreateColumnAndRow(MultiView.OriginalGrid, , );
MultiView.OriginalGrid.ColumnDefinitions[].Width = new GridLength(0.75, GridUnitType.Star);
MultiView.OriginalGrid.ColumnDefinitions[].Width = new GridLength(0.25, GridUnitType.Star);
MultiView.OriginalGrid.RowDefinitions[].Height = new GridLength(0.75, GridUnitType.Star);
MultiView.OriginalGrid.RowDefinitions[].Height = new GridLength(0.25, GridUnitType.Star); CellPanel cellPanel = MultiView.DictPanel[];
Grid.SetColumn(cellPanel, );
Grid.SetRow(cellPanel, );
MultiView.OriginalGrid.Children.Add(cellPanel); //p2,p3,p4 画面
Grid.SetColumn(MultiView.TempGrid1, );
Grid.SetRow(MultiView.TempGrid1, ); for (int index = ; index < ; ++index)
{
cellPanel = MultiView.DictPanel[index + ]; MultiView.TempGrid1.RowDefinitions.Add(new RowDefinition());
Grid.SetRow(cellPanel, index);
MultiView.TempGrid1.Children.Add(cellPanel);
}
MultiView.OriginalGrid.Children.Add(MultiView.TempGrid1);
//p5,p6,p7 画面
Grid.SetColumn(MultiView.TempGrid2, );
Grid.SetRow(MultiView.TempGrid2, ); for (int index = ; index < ; ++index)
{
cellPanel = MultiView.DictPanel[index + ]; MultiView.TempGrid2.ColumnDefinitions.Add(new ColumnDefinition());
Grid.SetColumn(cellPanel, index);
MultiView.TempGrid2.Children.Add(cellPanel);
}
MultiView.OriginalGrid.Children.Add(MultiView.TempGrid2); cellPanel = MultiView.DictPanel[];
Grid.SetRow(cellPanel, );
Grid.SetColumn(cellPanel, );
MultiView.OriginalGrid.Children.Add(cellPanel);
}
/// <summary>
/// 十画面
/// </summary>
public static void SetModel10()
{
MultiView.Clear();
MultiView.CreateColumnAndRow(MultiView.OriginalGrid, , );
MultiView.OriginalGrid.ColumnDefinitions[].Width = new GridLength(0.77, GridUnitType.Star);
MultiView.OriginalGrid.ColumnDefinitions[].Width = new GridLength(0.23, GridUnitType.Star);
MultiView.OriginalGrid.RowDefinitions[].Height = new GridLength(0.8, GridUnitType.Star);
MultiView.OriginalGrid.RowDefinitions[].Height = new GridLength(0.2, GridUnitType.Star); CellPanel cellPanel = MultiView.DictPanel[];
Grid.SetColumn(cellPanel, );
Grid.SetRow(cellPanel, );
MultiView.OriginalGrid.Children.Add(cellPanel); //p2,p3,p4,p5 画面
Grid.SetColumn(MultiView.TempGrid1, );
Grid.SetRow(MultiView.TempGrid1, ); for (int index = ; index < ; ++index)
{
cellPanel = MultiView.DictPanel[index + ]; MultiView.TempGrid1.RowDefinitions.Add(new RowDefinition());
Grid.SetRow(cellPanel, index);
MultiView.TempGrid1.Children.Add(cellPanel);
}
MultiView.OriginalGrid.Children.Add(MultiView.TempGrid1);
//p6,p7,p8,p9 画面
Grid.SetColumn(MultiView.TempGrid2, );
Grid.SetRow(MultiView.TempGrid2, ); for (int index = ; index < ; ++index)
{
cellPanel = MultiView.DictPanel[index + ]; MultiView.TempGrid2.ColumnDefinitions.Add(new ColumnDefinition());
Grid.SetColumn(cellPanel, index);
MultiView.TempGrid2.Children.Add(cellPanel);
}
MultiView.OriginalGrid.Children.Add(MultiView.TempGrid2); cellPanel = MultiView.DictPanel[];
Grid.SetRow(cellPanel, );
Grid.SetColumn(cellPanel, );
MultiView.OriginalGrid.Children.Add(cellPanel);
}
/// <summary>
/// 索引画面全屏
/// </summary>
/// <param name="index">画面索引</param>
public static void SetFullScreen(int index)
{
MultiView.Clear();
CellPanel cellPanel = MultiView.DictPanel[index];
Grid.SetColumn(cellPanel, );
Grid.SetRow(cellPanel, );
MultiView.OriginalGrid.Children.Add(cellPanel);
} private static void Clear()
{
MultiView.OriginalGrid.RowDefinitions.Clear();
MultiView.OriginalGrid.ColumnDefinitions.Clear();
MultiView.OriginalGrid.Children.Clear();
MultiView.TempGrid1.Children.Clear();
MultiView.TempGrid1.RowDefinitions.Clear();
MultiView.TempGrid1.ColumnDefinitions.Clear();
MultiView.TempGrid2.Children.Clear();
MultiView.TempGrid2.RowDefinitions.Clear();
MultiView.TempGrid2.ColumnDefinitions.Clear(); } private static void CreateColumnAndRow(Grid grid, int row, int column)
{
for (int index = ; index < row; ++index)
{
grid.RowDefinitions.Add(new RowDefinition());
} for (int index = ; index < column; ++index)
{
grid.ColumnDefinitions.Add(new ColumnDefinition());
}
}
}

2、 实现单通道画面控件CellPanel

1) 前台页面

<UserControl x:Class="MultiviewControl.CellPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
BorderThickness="" BorderBrush="Silver">
<Grid Background="Black">
<wfi:WindowsFormsHost >
<wf:Panel x:Name="panel" AutoSize="true" Dock="Fill"/>
</wfi:WindowsFormsHost>
</Grid>
</UserControl>

2) 后台实现

  public partial class CellPanel : System.Windows.Controls.UserControl
{
public int Index;
public bool Selected; private bool isFull = false;
private SolidColorBrush SelectedColor = new SolidColorBrush(Colors.YellowGreen);
private SolidColorBrush MouseEnterColor = new SolidColorBrush(Colors.Red);
private SolidColorBrush NormalColor = new SolidColorBrush(Colors.Silver); public CellPanel()
{
this.InitializeComponent();
this.panel.Click += new EventHandler(this.panel_Click);
this.panel.DoubleClick += new EventHandler(this.panel_DoubleClick);
this.panel.MouseEnter += new EventHandler(this.panel_MouseEnter);
this.panel.MouseLeave += new EventHandler(this.panel_MouseLeave);
this.panel.SizeChanged += new EventHandler(this.panel_SizeChange);
this.Selected = false;
} public void panel_Click(object sender, EventArgs e)
{
foreach (CellPanel cellPanel in MultiView.DictPanel.Values)
{
cellPanel.Selected = false;
cellPanel.BorderBrush = NormalColor;
}
this.Selected = true;
this.BorderBrush = SelectedColor;
}
public void panel_DoubleClick(object sender, EventArgs e)
{
if (this.isFull)
{
MultiView.SetCurrentModel(MultiView.CurrentModel);
}
else
{
MultiView.SetFullScreen(this.Index);
} this.isFull = !this.isFull;
}
private void panel_MouseEnter(object sender, EventArgs e)
{
if (!this.Selected)
{
this.BorderBrush = MouseEnterColor;
}
} private void panel_MouseLeave(object sender, EventArgs e)
{
if (!this.Selected)
{
this.BorderBrush = NormalColor;
}
}
private void panel_SizeChange(object sender, EventArgs e)
{
this.panel.Size = new System.Drawing.Size((int)this.Width - , (int)this.Height - );
} }

  3、新建一个窗体MainWindow,调用MutiView类

     1) 前台页面

 <Window x:Class="MultiviewControl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="" Width="">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="" />
</Grid.RowDefinitions>
<Grid x:Name="grid" />
<StackPanel Orientation="Horizontal" Grid.Row="">
<Button Content="1画 面" Tag="" Click="btn_Click" Margin="" Width=""/>
<Button Content="3画 面" Tag="" Click="btn_Click" Margin="" Width=""/>
<Button Content="4画 面" Tag="" Click="btn_Click" Margin="" Width=""/>
<Button Content="6画 面" Tag="" Click="btn_Click" Margin="" Width=""/>
<Button Content="8画 面" Tag="" Click="btn_Click" Margin="" Width=""/>
<Button Content="9画 面" Tag="" Click="btn_Click" Margin="" Width=""/>
<Button Content="10画 面" Tag="" Click="btn_Click" Margin="" Width=""/>
</StackPanel>
</Grid>
</Window>

2) 后台实现

  public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MultiView.InitGrid(this.grid, );
MultiView.SetCurrentModel();
} private void btn_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
int index = ;
if(btn.Tag != null)
{
MultiView.SetCurrentModel(Convert.ToInt32( btn.Tag));
} } }

多画面切换就OK了!希望能对大家有用!

使用WPF制作视频监控多画面切换的更多相关文章

  1. Qt编写视频监控画面分割界面(开源)

    其实qt应用在安防领域还是蛮多的,尤其是视频监控系统,但是网上几乎没有看到qt做的最基础的视频监控画面分割的demo,今天特意花几分钟提取出来,开源放出来.欢迎大家多多点赞!源码下载:点击打开链接 运 ...

  2. Qt编写安防视频监控系统7-全屏切换

    一.前言 全屏切换这个功能点属于简单的,一般会做到右键菜单中,也提供了快捷键比如alt+enter来触发,恢复全屏则按esc即可,全屏处理基本上都是隐藏通道面板以外的窗体,保持最大化展示,由于采用了模 ...

  3. Qt编写安防视频监控系统1-通道切换

    一.前言 通道切换在视频监控系统中是最基础的必备功能,一般都会提供1通道+4通道+6通道+8通道+9通道+16通道这几个通道切换,可能做得比较好的还会提供24通道+32通道的,这个可能对电脑的配置就有 ...

  4. [视频监控]用状态机图展示Layout切换关系

    监控系统通常会提供多种Layout给用户,用于满足不同需求,如:高清显示单路视频或者同时观察多路监控情况. 文中系统只提供了单路.2x2(2行2列共4路).8路(4行4列布局,从左上角算起,有个核心显 ...

  5. C# 实现IP视频监控(摄像头)画面推送(简单的不能再简单的DEMO)

    最近继续在家休息,在完成上一个Python抓取某音乐网站爬虫后,琢磨着实现一个基于HTTP推送的 IP视频监控,比如外出的时候,在家里 开启一个监控端(摄像头+服务端),可以看到实时画面,如果再加上自 ...

  6. Qt编写项目作品大全(自定义控件+输入法+大屏电子看板+视频监控+楼宇对讲+气体安全等)

    一.自定义控件大全 (一).控件介绍 超过160个精美控件,涵盖了各种仪表盘.进度条.进度球.指南针.曲线图.标尺.温度计.导航条.导航栏,flatui.高亮按钮.滑动选择器.农历等.远超qwt集成的 ...

  7. Qt编写安防视频监控系统(界面很漂亮)

    一.前言 视频监控系统在整个安防领域,已经做到了烂大街的程序,全国起码几百家公司做过类似的系统,当然这一方面的需求量也是非常旺盛的,各种定制化的需求越来越多,尤其是这几年借着人脸识别的东风,发展更加迅 ...

  8. Qt编写安防视频监控系统18-云台控制

    一.前言 云台控制是视频监控系统中必备的一个功能,对球机进行上下左右的移动,还有焦距的控制,其实核心就是控制XYZ三个坐标轴,为了开发这个模块,特意研究了各种云台控制的方法和开源库比如soap,有些厂 ...

  9. Qt编写安防视频监控系统15-远程回放

    一.前言 远程回放有两种处理方式,一种是采用NVR厂家提供的SDK开发包来登录到NVR上,然后根据SDK的函数接口指定的视频文件,当然也有接口查询视频文件列表等:一种是采用视频监控行业的国标GB281 ...

随机推荐

  1. ios微信打开网页键盘弹起后页面上滑,导致弹框里的按钮响应区域错位

    input失去焦点,页面被顶起没有还原,所以就有以下的方法来处理 $("input").blur(function(){   setTimeout(() => {    co ...

  2. 秒懂 this

    一:全局执行 console.log(this); // Window 可以看出在全局作用域中 this 指向当前的全局对象 Window. 二:函数中执行 1.非严格模式中 function fun ...

  3. MySQL正则表达式 REGEXP详解

    在开始这个话题之前我们首先来做一个小实验,比较一下REGEXP和Like他们两个哪个效率高,如果效率太低,我们就没有必要做过多的研究了,实验的代码如下:<?phpRequire("co ...

  4. go基础知识之变量,类型,常量,函数

    3 变量 变量是什么 变量指定了某存储单元(Memory Location)的名称,该存储单元会存储特定类型的值.在 Go 中,有多种语法用于声明变量. 声明单个变量 var name type 是声 ...

  5. django之补充

    一 QuerySet类型 QuerySet类型:只和orm有关,如果一涉及数据库,就会有QuerySet类型的出现. QuerySet切片操作:QuerySet是支持切片操作的,不过不能放负数.查询集 ...

  6. poj-3667(线段树区间合并)

    题目链接:传送门 参考文章:传送门 思路:线段树区间合并问题,每次查询到满足线段树的区间最左值,然后更新线段树. #include<iostream> #include<cstdio ...

  7. Lyft Level 5 Challenge 2018 - Final Round (Open Div. 2) C. The Tower is Going Home(思维+双指针)

    https://codeforces.com/contest/1075/problem/C 题意 一个宽为1e9*1e9的矩阵中的左下角,放置一个车(车可以移动到同一行或同一列),放置一些墙,竖的占据 ...

  8. querySelectorAll()方法

    querySelectorAll()方法 调用的对象包括:Document(文档) DocumentFragment(文档片段) Element(元素) querySelectorAll()方法接收的 ...

  9. 何时使用Delegate或接口

    在以下情况下使用Delegates很有用: 调用一个单一方法: 一个类要进行方法规范(method specification)的多种执行: 使用一个静态方法来执行规范: 想获得类似事件设计的模式: ...

  10. Swift: 用UserDefaults保存复杂对象

    一直木有看过这个细节,用UserDefaults是能不能存复杂一点的对象.大家可能都看到过UserDefaults的一个方法setObject: forKey:,用这个方法存过NSDictionary ...