using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; using Vanara.Extensions; namespace Vanara.Windows.Forms { internal class CollapsiblePanelHeader : Control { private const int tbpadding = 8; private const string bgClass = "LISTVIEW", btnClass = "TASKDIALOG", txtClass = btnClass; private const int bgPart = 6, btnPart = 13, txtPart = 2; private readonly VisualStyleRenderer bgRnd, btnRnd, txtRnd; private int headerHeight; private Size imgSz; private Rectangle buttonBounds; private Rectangle textBounds; public CollapsiblePanelHeader() { SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true); if (VisualStyleRenderer.IsSupported) try { bgRnd = new VisualStyleRenderer(bgClass, bgPart, 0); btnRnd = new VisualStyleRenderer(btnClass, btnPart, 0); txtRnd = new VisualStyleRenderer(txtClass, txtPart, 0); } catch { } } [DefaultValue(false)] public bool Collapsed { get; set; } internal PushButtonState ButtonState { get; set; } = PushButtonState.Normal; internal int HorzPadding { get; set; } = 12; /// /// Retrieves the default size for the control. /// /// /// /// The default of the control. /// protected override Size DefaultSize => new Size(200, 200); /// /// Retrieves the size of a rectangular area into which a control can be fitted. /// /// The custom-sized area for a control. /// /// An ordered pair of type representing the width and height of a rectangle. /// public override Size GetPreferredSize(Size proposedSize) => DefaultSize; protected override void OnClick(EventArgs e) { Collapsed = !Collapsed; base.OnClick(e); } /// /// Process Enabled property changed /// /// The instance containing the event data. protected override void OnEnabledChanged(EventArgs e) { ButtonState = Enabled ? PushButtonState.Normal : PushButtonState.Disabled; Invalidate(); base.OnEnabledChanged(e); } /// /// Raises the event. /// /// The instance containing the event data. protected override void OnGotFocus(EventArgs e) { Invalidate(); base.OnGotFocus(e); } /// /// Raises the event. /// /// The instance containing the event data. protected override void OnLostFocus(EventArgs e) { Invalidate(); base.OnLostFocus(e); } /// /// Raises the event. /// /// A that contains the event data. protected override void OnMouseDown(MouseEventArgs e) { if ((e.Button & MouseButtons.Left) != MouseButtons.Left) return; ButtonState = PushButtonState.Pressed; Invalidate(); base.OnMouseDown(e); } /// /// Raises the event. /// /// An that contains the event data. protected override void OnMouseEnter(EventArgs e) { ButtonState = PushButtonState.Hot; Invalidate(); base.OnMouseEnter(e); } /// /// Raises the event. /// /// An that contains the event data. protected override void OnMouseLeave(EventArgs e) { ButtonState = Enabled ? PushButtonState.Normal : PushButtonState.Disabled; Invalidate(); base.OnMouseLeave(e); } /// /// Raises the event. /// /// A that contains the event data. protected override void OnMouseUp(MouseEventArgs e) { if ((e.Button & MouseButtons.Left) != MouseButtons.Left) return; ButtonState = Enabled ? PushButtonState.Hot : PushButtonState.Disabled; Invalidate(); base.OnMouseUp(e); } /// /// Raises the event. /// /// A that contains the event data. protected override void OnPaint(PaintEventArgs e) { if (Visible) { var g = e.Graphics; g.SmoothingMode = SmoothingMode.HighQuality; g.CompositingQuality = CompositingQuality.HighQuality; g.InterpolationMode = InterpolationMode.HighQualityBicubic; if (bgRnd == null) try { e.Graphics.Clear(ButtonState == PushButtonState.Hot || ButtonState == PushButtonState.Pressed ? SystemColors.Highlight : SystemColors.Window); TextRenderer.DrawText(e.Graphics, Text, SystemFonts.CaptionFont, textBounds.Location, ButtonState == PushButtonState.Hot || ButtonState == PushButtonState.Pressed ? SystemColors.HighlightText : SystemColors.WindowText); } catch { } else { LayoutElements(e.Graphics, e.ClipRectangle); bgRnd.DrawBackground(e.Graphics, ClientRectangle); btnRnd.DrawBackground(e.Graphics, buttonBounds, null, this.GetRightToLeftProperty() == RightToLeft.Yes); var tff = TextFormatFlags.SingleLine; if (this.GetRightToLeftProperty() == RightToLeft.Yes) tff |= TextFormatFlags.RightToLeft; txtRnd.DrawText(e.Graphics, textBounds, Text, !Enabled, tff); } base.OnPaint(e); } } private void LayoutElements(IDeviceContext g, Rectangle clipRect) { if (btnRnd == null) return; var state = (int)ButtonState; if (state == 4) state = Collapsed ? 7 : 8; else if (!Collapsed) state += 3; btnRnd.SetState(state); state = (ButtonState == PushButtonState.Hot || ButtonState == PushButtonState.Pressed) ? 2 : 1; bgRnd.SetState(state); var r = txtRnd.GetTextExtent(g, "W", TextFormatFlags.Default); headerHeight = (tbpadding * 2) + r.Height; imgSz = new Size(btnRnd.GetInteger(IntegerProperty.Width), btnRnd.GetInteger(IntegerProperty.Height)); buttonBounds = new Rectangle(clipRect.Width - imgSz.Width - HorzPadding, (headerHeight - imgSz.Height) / 2, imgSz.Width, imgSz.Height); textBounds = new Rectangle(HorzPadding, tbpadding, clipRect.Width - HorzPadding - imgSz.Width, tbpadding + r.Height); Height = headerHeight; } } }