1. 先“上菜”再讲做法:——上图~~
2. 动态Panel
a). 采用平方算法,即4个头4个Panel(2 ^ 2),8个头9个Panel(3 ^ 3),算是比较简单也满足基本需求的算法了。
b). 注意需要固定左上角顶点坐标和总面积,即(2,38)和610,532,这个可以根据自己的时间情况加以修改,可以定义成const int 就行。
c). 注意里面算坐标的时候有+1,这个是Panel之间的间隙。
4. 使用例子
在Form_Load中加入如下代码:
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>
/// <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;
}
///
<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);
}
}
}
代码说明:
/// 根据通道数动态计算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]));
}
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;
}
/// 计算视频面板位置和面积
/// </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
本文转自博客园农民伯伯的博客,原文链接:WinForm 分屏 [ WinForm | Panel | 视频监控分屏 ],如需转载请自行联系原博主。