zoukankan      html  css  js  c++  java
  • 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(238);

                
    //模数
                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

          分屏示例下载


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

  • 相关阅读:
    C# 实现任务栏图标程序
    C#实现的木马之客户端
    sql基本语法
    水晶报表引用DataSet做数据源
    解决多线程操作控件时可能出现的异常:“在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级”
    电子书籍制作工具软件大全
    C#实现的木马之服务端
    2进制、8进制、10进制、16进制...各种进制间的轻松转换
    VC# .Net中使用Crystal Report水晶报表
    P2P技术学习
  • 原文地址:https://www.cnblogs.com/ywsoftware/p/2892552.html
Copyright © 2011-2022 走看看