L'intégration de fonctionnalités d'affichage multi-écrans est une caractéristique essentielle des systèmes de vidéosurveillance modernes. Cet article explore une méthode pour concevoir et appliquer dynamiquement différentes configurations de zones d'affichage pour les flux vidéo au sein d'une application.
Pour définir les régions d'fafichage de manière flexible, nous commençons par créer une structure simple. Cette structure, nommée ZoneAffichage, encapsule les coordonnées de début de la zone sur une grille logique, ainsi que son étendue en termes de nombre de colonnes et de lignes occupées.
using System.Drawing; // Nécessaire pour Point
using System.Windows.Forms; // Nécessaire pour Control et Panel
/// <summary>
/// Représente une zone rectangulaire au sein d'une grille d'affichage.
/// </summary>
public struct ZoneAffichage
{
/// <summary>
/// Index de la colonne de départ sur la grille (base zéro).
/// </summary>
public int IndexColDebut { get; set; }
/// <summary>
/// Index de la ligne de départ sur la grille (base zéro).
/// </summary&m
public int IndexLigneDebut { get; set; }
/// <summary>
/// Nombre de colonnes que cette zone doit s'étendre.
/// </summary>
public int SpanCols { get; set; }
/// <summary>
/// Nombre de lignes que cette zone doit s'étendre.
/// </summary>
public int SpanLignes { get; set; }
/// <summary>
/// Initialise une nouvelle instance de la structure ZoneAffichage.
/// </summary>
/// <param name="col">Colonne de départ.</param>
/// <param name="row">Ligne de départ.</param>
/// <param name="spanCols">Nombre de colonnes couvertes.</param>
/// <param name="spanLignes">Nombre de lignes couvertes.</param>
public ZoneAffichage(int col, int row, int spanCols, int spanLignes)
{
IndexColDebut = col;
IndexLigneDebut = row;
SpanCols = spanCols;
SpanLignes = spanLignes;
}
}
En utilisant cette strucutre, il est possible de définir diverses dispositions d'écran sous forme de tableaux d'objets ZoneAffichage. Chaque élément du tableau décrit un panneau vidéo ou une région spécifique dans la cofniguration choisie. Voici quelques exemples de schémas d'affichage courants :
/// <summary>
/// Définit un ensemble de configurations d'affichage prédéfinies.
/// </summary>
public static class DispositionsEcran
{
// Disposition 1x1 : Un écran unique occupant toute la surface
public static ZoneAffichage[] DispositionPleineEcran = new ZoneAffichage[]
{
new ZoneAffichage(0, 0, 1, 1)
};
// Disposition 2x2 : Quatre écrans de taille égale disposés en grille
public static ZoneAffichage[] DispositionDeuxParDeux = new ZoneAffichage[]
{
new ZoneAffichage(0, 0, 1, 1), new ZoneAffichage(1, 0, 1, 1),
new ZoneAffichage(0, 1, 1, 1), new ZoneAffichage(1, 1, 1, 1)
};
// Disposition 3x3 : Neuf écrans de taille égale
public static ZoneAffichage[] DispositionTroisParTrois = new ZoneAffichage[]
{
new ZoneAffichage(0, 0, 1, 1), new ZoneAffichage(1, 0, 1, 1), new ZoneAffichage(2, 0, 1, 1),
new ZoneAffichage(0, 1, 1, 1), new ZoneAffichage(1, 1, 1, 1), new ZoneAffichage(2, 1, 1, 1),
new ZoneAffichage(0, 2, 1, 1), new ZoneAffichage(1, 2, 1, 1), new ZoneAffichage(2, 2, 1, 1)
};
// Disposition 4x4 : Seize écrans de taille égale
public static ZoneAffichage[] DispositionQuatreParQuatre = new ZoneAffichage[]
{
new ZoneAffichage(0, 0, 1, 1), new ZoneAffichage(1, 0, 1, 1), new ZoneAffichage(2, 0, 1, 1), new ZoneAffichage(3, 0, 1, 1),
new ZoneAffichage(0, 1, 1, 1), new ZoneAffichage(1, 1, 1, 1), new ZoneAffichage(2, 1, 1, 1), new ZoneAffichage(3, 1, 1, 1),
new ZoneAffichage(0, 2, 1, 1), new ZoneAffichage(1, 2, 1, 1), new ZoneAffichage(2, 2, 1, 1), new ZoneAffichage(3, 2, 1, 1),
new ZoneAffichage(0, 3, 1, 1), new ZoneAffichage(1, 3, 1, 1), new ZoneAffichage(2, 3, 1, 1), new ZoneAffichage(3, 3, 1, 1)
};
// Disposition asymétrique : Un grand écran principal et plusieurs plus petits (exemple basé sur une grille 3x3)
public static ZoneAffichage[] DispositionGrandPrincipalEtCompagnons = new ZoneAffichage[]
{
new ZoneAffichage(0, 0, 2, 2), // Grand écran en haut à gauche, couvrant 2x2 cellules
new ZoneAffichage(2, 0, 1, 1), // Écran 1 à droite du grand
new ZoneAffichage(2, 1, 1, 1), // Écran 2 en bas à droite du grand
new ZoneAffichage(0, 2, 1, 1), // Écran 3 en bas à gauche
new ZoneAffichage(1, 2, 1, 1), // Écran 4 en bas au centre
new ZoneAffichage(2, 2, 1, 1) // Écran 5 en bas à droite
};
// Disposition centrée : Un écran central plus grand entouré d'écrans périphériques (exemple basé sur une grille 3x3)
public static ZoneAffichage[] DispositionCentraleEtendue = new ZoneAffichage[]
{
new ZoneAffichage(0, 0, 1, 1), // Haut-gauche
new ZoneAffichage(1, 0, 1, 1), // Haut-centre
new ZoneAffichage(2, 0, 1, 1), // Haut-droit
new ZoneAffichage(0, 1, 1, 1), // Milieu-gauche
new ZoneAffichage(1, 1, 1, 1), // CENTRE (occupe 1x1 ici, peut être ajusté)
new ZoneAffichage(2, 1, 1, 1), // Milieu-droit
new ZoneAffichage(0, 2, 1, 1), // Bas-gauche
new ZoneAffichage(1, 2, 1, 1), // Bas-centre
new ZoneAffichage(2, 2, 1, 1) // Bas-droit
};
}
La méthode ci-dessous permet d'appliquer une de ces configurations à un conteneur d'interface utilisateur (comme un Panel ou un UserControl Windows Forms). Elle calcule la taille de base de chaque cellule de la grille en divisant la largeur et la hauteur du conteneur par le nombre de divisions souhaitées par axe (par exemple, 2 pour une grille 2x2, 3 pour 3x3, etc.), puis positionne et redimensionne chaque panneau vidéo en fonction de sa définition dans la configuration.
/// <summary>
/// Applique une configuration de zones d'affichage à un conteneur spécifié.
/// </summary>
/// <param name="conteneurParent">Le contrôle parent où les panneaux vidéo seront ajoutés.</param>
/// <param name="nombreDivisionsParAxe">Le nombre de divisions pour chaque axe de la grille logique (ex: 2 pour 2x2, 3 pour 3x3).</param>
/// <param name="configurationZones">Le tableau des définitions de zones d'affichage à appliquer.</param>
public static void AppliquerDispositionEcran(Control conteneurParent, int nombreDivisionsParAxe, ZoneAffichage[] configurationZones)
{
if (conteneurParent == null)
throw new ArgumentNullException(nameof(conteneurParent), "Le conteneur parent ne peut pas être nul.");
if (configurationZones == null)
throw new ArgumentNullException(nameof(configurationZones), "La configuration des zones ne peut pas être nulle.");
if (nombreDivisionsParAxe <= 0)
throw new ArgumentOutOfRangeException(nameof(nombreDivisionsParAxe), "Le nombre de divisions par axe doit être supérieur à zéro.");
// Efface tous les contrôles enfants existants du conteneur
conteneurParent.Controls.Clear();
// Calcule la largeur et la hauteur de base d'une seule cellule de la grille
int largeurCellule = conteneurParent.Width / nombreDivisionsParAxe;
int hauteurCellule = conteneurParent.Height / nombreDivisionsParAxe;
foreach (var zone in configurationZones)
{
// Supposons que 'PlayItem' est un UserControl ou un Panel personnalisé
// dédié à l'affichage de flux vidéo.
// Pour cet exemple, nous utilisons un Panel standard de Windows Forms.
Panel panneauVideo = new Panel();
panneauVideo.Width = largeurCellule * zone.SpanCols;
panneauVideo.Height = hauteurCellule * zone.SpanLignes;
panneauVideo.Location = new Point(zone.IndexColDebut * largeurCellule, zone.IndexLigneDebut * hauteurCellule);
panneauVideo.BorderStyle = BorderStyle.FixedSingle; // Ajoute une bordure pour visualiser les zones
panneauVideo.BackColor = Color.LightGray; // Définit une couleur de fond pour la visualisation
// Ici, un contrôle de lecteur vidéo spécifique (ex: VLC, FFMPEG) pourrait être ajouté
// ou instancié à l'intérieur de ce 'panneauVideo'.
conteneurParent.Controls.Add(panneauVideo);
}
}