WinForm 分屏 [ WinForm | Panel | 视频监控分屏 ]

前言
      视频监控的分屏技术实际上就是通过动态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;
        }

  

    5.2  示例代码  2010-5-25

      分屏示例下载


结束语
      这个功能也是在最近代码重构的时候补上来的,也欢迎大家提供其他算法来分屏 :)

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值