Winforms – Come posso creare un bordo di Windows personalizzato e chiudere / ridurre a icona i pulsanti?

Mi piacerebbe essere in grado di creare una finestra personalizzata nera (con bordo e controlli) come quella spedita come parte della miscela di espressioni, Twirl o Adobe Lightroom.

Esiste un modo migliore per creare una finestra disegnata dal proprietario?

Piattaforma: C # e WindowsForms (qualsiasi versione)

Barre del titolo personalizzate / chrome in un’app WinForms

Se gli strumenti personalizzati di Chrome non ti danno l’aspetto e la sensazione che desideri, questo tipo di cose è facile da fare da te in C #. Fondamentalmente, si crea un modulo senza bordi (FormBorderStyle = None) e quindi si creano tutti i controlli e i bordi da soli, posizionando i controlli dove sono necessari (un’etichetta per la barra del titolo, i pulsanti di comando per chiudere e ridurre a icona ecc.) E / o il disegno direttamente sulla superficie del modulo usando l’object Graphics.

È inoltre necessario implementare il codice per consentire al modulo di essere trascinato dalla sua barra del titolo “falso” (vedere questa risposta per un esempio di come farlo). Potrebbe anche essere necessario implementare il proprio meccanismo di ridimensionamento (se è necessario ridimensionare i moduli).

Infine, anche se il codice in forma personalizzata potrebbe essere un po ‘goffo, è ansible implementarlo su un unico modulo e poi ereditare tutti gli altri moduli nell’applicazione da questo modulo, il che lo rende una tecnica molto utile per personalizzare lo skin su un’intera applicazione.

Il mio compito era rendere la finestra triggers più visibile, luminosa – rispetto ad altre, le windows inattive dell’app. L’app ha molte windows aperte, alcune modali, alcune non modali e quella MDI.

Puoi usare qualcosa come non-un-confine: una cornice all’interno dell’area cliente. Ecco lo snippet di codice, una parte di una class base (può essere utilizzata direttamente in un modulo):

#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 

I campi statici della class vengono inizializzati dal modulo delle impostazioni dell’applicazione (class), quindi tutti i moduli nell’app hanno lo stesso comportamento.

Spero che aiuti qualcuno.