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

          分屏示例下载


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

  • 相关阅读:
    可闭环、可沉淀、可持续的企业级数据赋能体系
    案例解读|迁云的灵魂3问,降多少本,增多少效,真平滑否?
    Serverless 实战——使用 Rendertron 搭建 Headless Chrome 渲染解决方案
    从零开始入门 K8s | etcd 性能优化实践
    State Processor API:如何读取,写入和修改 Flink 应用程序的状态
    阿里云叔同:以容器为代表的云原生技术,已成为释放云价值的最短路径
    Flink SQL 如何实现数据流的 Join?
    仅1年GitHub Star数翻倍,Flink 做了什么?
    codeforces div2_603 F. Economic Difficulties(树dfs预处理+dp)
    codeforces div2_604 E. Beautiful Mirrors(期望+费马小定理)
  • 原文地址:https://www.cnblogs.com/ywsoftware/p/2892552.html
Copyright © 2011-2022 走看看