Winforms – Comment créer une bordure de fenêtres personnalisée et fermer / réduire les boutons?

Je voudrais pouvoir créer une fenêtre personnalisée noire (avec bordure et contrôles) comme celle livrée dans le cadre du mélange d’expressions, Twirl ou Adobe Lightroom.

Existe-t-il une méthode conseillée pour créer une fenêtre dessinée par le propriétaire?

Plate-forme: C # et WindowsForms (toute version)

Barres de titre personnalisées / chrome dans une application WinForms

Si les outils de chrome personnalisés ne vous fournissent pas l’apparence que vous souhaitez, ce genre de chose est facile à faire vous-même en C #. Fondamentalement, vous créez un formulaire sans bordure (FormBorderStyle = None), puis créez vous-même tous les contrôles et bordures en plaçant des contrôles là où vous en avez besoin (une étiquette pour la barre de titre, des boutons de commande pour fermer et réduire, etc.) directement sur la surface du formulaire à l’aide de l’object Graphics.

Vous devez également implémenter du code pour permettre au formulaire d’être déplacé par sa barre de titre “fausse” (voir cette réponse pour un exemple de la façon de procéder). Vous devrez peut-être également implémenter votre propre mécanisme de redimensionnement (si vous avez besoin que les formulaires soient redimensionnables).

Enfin, bien que le code personnalisé puisse être un peu compliqué, vous pouvez l’implémenter sur un seul formulaire, puis faire en sorte que toutes les autres formes de votre application héritent de ce formulaire, ce qui en fait une technique très utile pour personnaliser application.

Ma tâche consistait à rendre la fenêtre active plus visible, plus claire que les autres fenêtres inactives de l’application. App a beaucoup de fenêtres ouvertes, certaines modales, certaines non modales – et le parent MDI.

Vous pouvez utiliser quelque chose comme pas un cadre – un cadre dans la zone client. Voici l’extrait de code, une partie d’une classe de base (utilisable directement dans un formulaire):

#region Кастомизированное поведение - рамки, активность и т.д. private bool isCurrentlyActive = false; private bool childControlsAreHandled = false; private Pen activeWindowFramePen, inactiveWindowFramePen; private Point[] framePoints; private void AddControlPaintHandler(Control ctrl) { ctrl.Paint += DrawWindowFrame; if (ctrl.Controls != null) { foreach (Control childControl in ctrl.Controls) { AddControlPaintHandler(childControl); } } } protected override void OnActivated(EventArgs e) { base.OnActivated(e); if ((this.childControlsAreHandled == false) && (WindowFrameType != Forms.WindowFrameType.NoFrame) && (this.MdiParent == null)) { RecalculateWindowFramePoints(); AddControlPaintHandler(this); this.childControlsAreHandled = true; } this.isCurrentlyActive = true; if (InactiveWindowOpacity < 1) { base.Opacity = 1; } base.Invalidate(true); } protected override void OnDeactivate(EventArgs e) { base.OnDeactivate(e); this.isCurrentlyActive = false; if (InactiveWindowOpacity < 1) { base.Opacity = InactiveWindowOpacity; } base.Invalidate(true); } protected override void OnResizeEnd(EventArgs e) { base.OnResizeEnd(e); this.framePoints = null; RecalculateWindowFramePoints(); this.Invalidate(true); } private Pen ActivePen { get { if (this.isCurrentlyActive) { if (this.activeWindowFramePen == null) { this.activeWindowFramePen = new Pen(Color.FromArgb((int)(WindowFrameOpacity*255), WindowFrameActiveColor), WindowFrameSize * 2); } return this.activeWindowFramePen; } else { if (this.inactiveWindowFramePen == null) { this.inactiveWindowFramePen = new Pen(Color.FromArgb((int)(WindowFrameOpacity*255), WindowFrameInactiveColor), WindowFrameSize * 2); } return this.inactiveWindowFramePen; } } } private Point[] RecalculateWindowFramePoints() { if ((WindowFrameType == Forms.WindowFrameType.AllSides) && (this.framePoints != null) && (this.framePoints.Length != 5)) { this.framePoints = null; } if ((WindowFrameType == Forms.WindowFrameType.LeftLine) && (this.framePoints != null) && (this.framePoints.Length != 2)) { this.framePoints = null; } if (this.framePoints == null) { switch (WindowFrameType) { case Forms.WindowFrameType.AllSides: this.framePoints = new Point[5] { new Point(this.ClientRectangle.X, this.ClientRectangle.Y), new Point(this.ClientRectangle.X + this.ClientRectangle.Width, this.ClientRectangle.Y), new Point(this.ClientRectangle.X + this.ClientRectangle.Width, this.ClientRectangle.Y + this.ClientRectangle.Height), new Point(this.ClientRectangle.X, this.ClientRectangle.Y + this.ClientRectangle.Height), new Point(this.ClientRectangle.X, this.ClientRectangle.Y) }; break; case Forms.WindowFrameType.LeftLine: this.framePoints = new Point[2] { new Point(this.ClientRectangle.X, this.ClientRectangle.Y), new Point(this.ClientRectangle.X, this.ClientRectangle.Y + this.ClientRectangle.Height) }; break; } } return this.framePoints; } private void DrawWindowFrame(object sender, PaintEventArgs e) { if (WindowFrameType == Forms.WindowFrameType.NoFrame) { return; } if ((this.framePoints == null) || (this.framePoints.Length == 0)) { return; } Control ctrl = (Control)(sender); // пересчитаем точки в координатах контрола. List pts = new List(); foreach (var p in this.framePoints) { pts.Add(ctrl.PointToClient(this.PointToScreen(p))); } e.Graphics.DrawLines(ActivePen, pts.ToArray()); } public static int WindowFrameSize = 2; public static WindowFrameType WindowFrameType = Forms.WindowFrameType.NoFrame; public static Color WindowFrameActiveColor = Color.YellowGreen; public static Color WindowFrameInactiveColor = SystemColors.ControlDark; public static double InactiveWindowOpacity = 1.0; public static double WindowFrameOpacity = 0.3; #endregion 

Les champs statiques de la classe sont initialisés à partir du formulaire de configuration de l’application (classe). Ainsi, tous les formulaires de l’application ont le même comportement.

J’espère que ça aide quelqu’un.