博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WinForm 分屏 [ WinForm | Panel | 视频监控分屏 ]
阅读量:5807 次
发布时间:2019-06-18

本文共 3226 字,大约阅读时间需要 10 分钟。

前言
      视频监控的分屏技术实际上就是通过动态Panel + 动态指定其Location和Size来实现的,还需要一个计算分屏数目的算法,本文将弥补中动态分屏的功能,权当续文吧 : )

正文
      1.      先“上菜”再讲做法:——上图~~
 

 

 

 

 2.      动态Panel

 

        
///
 
<summary>
        
///
 动态创建面板
         
///
 
</summary>
        
///
 
<param name="xy">
Panel的XY坐标
</param>
        
///
 
<param name="wh">
Panel的大小
</param>
        
private
 Panel CreatePanel(Point xy, Size wh)
        {
            Panel panel 
=
 
new
 Panel();
            panel.BackColor 
=
 System.Drawing.Color.Transparent;
            panel.BackgroundImageLayout 
=
 System.Windows.Forms.ImageLayout.Stretch;
            panel.Location 
=
 xy;
            panel.Name 
=
 
string
.Concat(
"
pVideo
"
);
            panel.Size 
=
 wh;
            panel.TabIndex 
=
 
0
;
            panel.BackColor 
=
 Color.Black;
            
return
 panel;
        }

      3.      分屏算法

 

        
///
 
<summary>
        
///
 根据通道数动态计算Panel的坐标和大小
        
///
 
</summary>
        
///
 
<param name="channelCount">
通道数
</param>
        
///
 
<param name="xy">
返回运算后每个Panel的坐标
</param>
        
///
 
<param name="wh">
返回运算后每个Panel的大小
</param>
        
private
 
void
 MathDynamicPanel(
int
 channelCount, 
out
 Point[] xy, 
out
 Size[] wh)
        {
            xy 
=
 
new
 Point[channelCount];
            wh 
=
 
new
 Size[channelCount];
            
//
第一个Panel的起始坐标——不变
            xy[
0
=
 
new
 Point(
2
38
);
            
//
模数
            
int
 modulo;
            
if
 (channelCount 
<=
 
4
)
                modulo 
=
 
2
;
            
else
 
if
 (channelCount 
<=
 
9
)
                modulo 
=
 
3
;
            
else
 
if
 (channelCount 
<=
 
16
)
                modulo 
=
 
4
;
            
else
 
if
 (channelCount 
<=
 
25
)
                modulo 
=
 
5
;
            
else
 
if
 (channelCount 
<=
 
36
)
                modulo 
=
 
6
;
            
else
 
if
 (channelCount 
<=
 
49
)
                modulo 
=
 
7
;
            
else
//
 if (channelCount <= 64)
                modulo 
=
 
8
;
            
int
 width, height;
            
//
610 为整个预览区的宽
            width 
=
 (
610
 
-
 modulo 
*
 
1
/
 modulo;
            
//
532 为整个预览区的高
            height 
=
 (
532
 
-
 modulo 
*
 
1
/
 modulo;
            
for
 (
int
 i 
=
 
0
; i 
<
 channelCount; i
++
)
            {
                wh[i] 
=
 
new
 Size(width, height);
                
if
 (i 
>
 
0
)
                {
                    
//
同一行的Y坐标相等
                    
//
同一列的X坐标相等
                    
if
 (i 
%
 modulo 
==
 
0
)
                        xy[i] 
=
 
new
 Point(xy[i 
-
 modulo].X, xy[i 
-
 modulo].Y 
+
 height 
+
 
1
);
                    
else
                        xy[i] 
=
 
new
 Point(xy[i 
-
 
1
].X 
+
 width 
+
 
1
, xy[i 
-
 
1
].Y);
                }
            }
        }

            代码说明:

                  a).      采用平方算法,即4个头4个Panel(2 ^ 2),8个头9个Panel(3 ^ 3),算是比较简单也满足基本需求的算法了。
                  b).      注意需要固定左上角顶点坐标和总面积,即(2,38)和610,532,这个可以根据自己的时间情况加以修改,可以定义成const int 就行。
                  c).      注意里面算坐标的时候有+1,这个是Panel之间的间隙。
      4.      使用例子
        在Form_Load中加入如下代码:
 

            Point[] xy;
            Size[] wh;
            
int
 channel 
=
 
8
;
            
//
计算面板坐标
            MathDynamicPanel(channel, 
out
 xy, 
out
 wh);
            
//
创建面板
            
for
 (
int
 i 
=
 
0
; i 
<
 channel; i
++
)
            {
                
this
.Controls.Add(CreatePanel(xy[i], wh[i]));
            }

            运行即可见到截图中的样子,最大支持64个屏幕,满足基本需求,自己加上放大、缩小和全屏的代码功能就比较完整了。

 

  5.文章更新维护

    5.1  2010-5-22  修改一下方法,更加好用点

        
///
 
<summary>
        
///
 计算视频面板位置和面积
        
///
 
</summary>
        
///
 
<param name="channelCount"></param>
        
///
 
<param name="TotalSquare">
总面积和坐标
</param>
        
///
 
<returns></returns>
        
private
 IList
<
Rectangle
>
 CalcPanelRectangle(
int
 channelCount, Size TotalArea)
        {
            IList
<
Rectangle
>
 result 
=
 
new
 List
<
Rectangle
>
();
            
//
模数
            
int
 modulo;
            
if
 (channelCount 
<=
 
4
)
                modulo 
=
 
2
;
            
else
 
if
 (channelCount 
>
 
64
)
                modulo 
=
 
8
;
            
else
                modulo 
=
 (
int
)Math.Ceiling(Math.Sqrt(channelCount));         
//
平方根
            
int
 width, height;
            
//
单个画面大小
            width 
=
 (TotalArea.Width 
-
 modulo 
*
 
1
/
 modulo;
            height 
=
 (TotalArea.Height 
-
 modulo 
*
 
1
/
 modulo;
            
for
 (
int
 i 
=
 
0
; i 
<
 channelCount; i
++
)
            {
                Rectangle rect 
=
 
new
 Rectangle();
                rect.Width 
=
 width;
                rect.Height 
=
 height;
                
if
 (i 
%
 modulo 
==
 
0
)
                {
                    rect.X 
=
 
1
;
                    
if
 (i 
==
 
0
)
                        rect.Y 
=
 
1
;
                    
else
                        rect.Y 
=
 result[i 
-
 modulo].Y 
+
 height 
+
 
1
;
                }
                
else
                {
                    rect.X 
=
 result[i 
-
 
1
].X 
+
 width 
+
 
1
;
                    rect.Y 
=
 result[i 
-
 
1
].Y;
                }
                result.Add(rect);
            }
            
return
 result;
        }
本文转自over140 51CTO博客,原文链接:http://blog.51cto.com/over140/586624,如需转载请自行联系原作者
你可能感兴趣的文章
C/C++编程可用的Linux自带工具
查看>>
如何判断webview是不是滑到底部
查看>>
海贼王十大悲催人物
查看>>
org.hibernate.MappingException: No Dialect mapping for JDBC type: -1 搞定!
查看>>
热点热词新闻资讯API开放接口(永久免费开放)
查看>>
8.1_Linux习题和作业
查看>>
11.排序算法_6_归并排序
查看>>
Redis redis-cli 命令列表
查看>>
.NET框架设计—常被忽视的框架设计技巧
查看>>
BigDecimal 舍入模式(Rounding mode)介绍
查看>>
开源 免费 java CMS - FreeCMS1.2-标签 infoSign
查看>>
开源 免费 java CMS - FreeCMS1.9 移动APP生成栏目列表数据
查看>>
git reset 三种用法总结
查看>>
hdfs笔记
查看>>
虚拟机新增加硬盘,不用重启读到新加的硬盘
查看>>
Java IO流详尽解析
查看>>
邮件服务系列之四基于虚拟用户的虚拟域的邮件系统(安装courier-authlib以及部分配置方法)...
查看>>
Linux VSFTP服务器
查看>>
DHCP中继数据包互联网周游记
查看>>
Squid 反向代理服务器配置
查看>>