• 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

          分屏示例下载


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

  • 相关阅读:
    Ubuntu中VisualBox无法识别USB设备
    SpaceVim的基本安装和常见问题
    Linux下配置ssh免密远程登录
    PhantomJS在Selenium中被标记为过时的应对措施
    Linux下Vim编辑器访问系统剪切板
    Linux下将使用rm删除的文件显示在回收站中
    Java基础之创建窗口——使用卡片布局管理器(TryCardLayout)
    Java基础之创建窗口——使用边界布局管理器(TryBorderLayout)
    Java基础之创建窗口——使用流布局管理器(TryFlowLayout)
    Java基础之创建窗口——颜色和光标(TryWindow4)
  • 原文地址:https://www.cnblogs.com/ywsoftware/p/2892552.html
Copyright © 2020-2023  润新知