using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace CPM { /// /// ComboBox customizado do sistema LevelOS. /// Segue o mesmo padrão visual do LV_TEXTBOX1. /// public class LV_COMBOBOX : UserControl { // ── CAMPOS INTERNOS ─────────────────────────────────────────────────── private ComboBox _combo; private bool _isFocused = false; // ── PROPRIEDADES VISUAIS ────────────────────────────────────────────── private Color _borderColor = Color.FromArgb(226, 232, 240); private Color _borderFocusColor = Color.FromArgb(37, 99, 235); private Color _arrowColor = Color.FromArgb(100, 116, 139); private int _borderRadius = 6; private int _borderSize = 1; public Color BorderColor { get => _borderColor; set { _borderColor = value; Invalidate(); } } public Color BorderFocusColor { get => _borderFocusColor; set { _borderFocusColor = value; Invalidate(); } } public Color ArrowColor { get => _arrowColor; set { _arrowColor = value; Invalidate(); } } public int BorderRadius { get => _borderRadius; set { _borderRadius = value; Invalidate(); } } public int BorderSize { get => _borderSize; set { _borderSize = value; Invalidate(); } } // ── PROPRIEDADES DO COMBOBOX ────────────────────────────────────────── public ComboBoxStyle DropDownStyle { get => _combo.DropDownStyle; set => _combo.DropDownStyle = value; } public System.Windows.Forms.ComboBox.ObjectCollection Items => _combo.Items; public object? SelectedItem { get => _combo.SelectedItem; set => _combo.SelectedItem = value; } public int SelectedIndex { get => _combo.SelectedIndex; set => _combo.SelectedIndex = value; } public string Text { get => _combo.Text; set => _combo.Text = value; } public override Font Font { get => base.Font; set { base.Font = value; _combo.Font = value; AjustarAltura(); } } public new bool Enabled { get => base.Enabled; set { base.Enabled = value; _combo.Enabled = value; BackColor = value ? Color.White : Color.FromArgb(241, 245, 249); Invalidate(); } } // ── EVENTOS REPASSADOS ──────────────────────────────────────────────── public event EventHandler? SelectedIndexChanged { add => _combo.SelectedIndexChanged += value; remove => _combo.SelectedIndexChanged -= value; } public new event EventHandler? TextChanged { add => _combo.TextChanged += value; remove => _combo.TextChanged -= value; } // ── CONSTRUTOR ──────────────────────────────────────────────────────── public LV_COMBOBOX() { _combo = new ComboBox { DropDownStyle = ComboBoxStyle.DropDownList, FlatStyle = FlatStyle.Flat, Font = new Font("Segoe UI", 9f), BackColor = Color.White, ForeColor = Color.FromArgb(30, 41, 59), Dock = DockStyle.None, IntegralHeight = false }; // Configura o controle pai Padding = new Padding(8, 0, 30, 0); // espaço para seta customizada BackColor = Color.White; ForeColor = Color.FromArgb(30, 41, 59); Font = new Font("Segoe UI", 9f); Size = new Size(200, 36); DoubleBuffered = true; Controls.Add(_combo); AjustarAltura(); // Eventos de foco _combo.GotFocus += (s, e) => { _isFocused = true; Invalidate(); }; _combo.LostFocus += (s, e) => { _isFocused = false; Invalidate(); }; // Propaga clique na área do controle para o combo this.Click += (s, e) => _combo.Focus(); _combo.DropDown += (s, e) => Invalidate(); _combo.DropDownClosed += (s, e) => Invalidate(); } // ── AJUSTE DE ALTURA ────────────────────────────────────────────────── private void AjustarAltura() { int altura = _combo.PreferredHeight; this.Height = altura + 10; _combo.Width = this.Width - 38; // reserva espaço para seta _combo.Left = 8; _combo.Top = (this.Height - _combo.Height) / 2; } // ── RESIZE ──────────────────────────────────────────────────────────── protected override void OnResize(EventArgs e) { base.OnResize(e); _combo.Width = this.Width - 38; _combo.Left = 8; _combo.Top = (this.Height - _combo.Height) / 2; Invalidate(); } // ── PAINT ───────────────────────────────────────────────────────────── protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); var g = e.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias; var cor = _isFocused ? _borderFocusColor : _borderColor; var rect = new Rectangle(0, 0, Width - 1, Height - 1); var bgRect = new Rectangle(1, 1, Width - 2, Height - 2); // Fundo using var bgBrush = new SolidBrush(Enabled ? BackColor : Color.FromArgb(241, 245, 249)); g.FillRoundedRectangle(bgBrush, bgRect, _borderRadius); // Borda using var pen = new Pen(cor, _borderSize); g.DrawRoundedRectangle(pen, rect, _borderRadius); // Seta customizada DesenharSeta(g); } private void DesenharSeta(Graphics g) { int arrowX = Width - 22; int arrowY = Height / 2; using var brush = new SolidBrush(_isFocused ? _borderFocusColor : _arrowColor); var pontos = new Point[] { new Point(arrowX - 5, arrowY - 3), new Point(arrowX + 5, arrowY - 3), new Point(arrowX, arrowY + 4) }; g.FillPolygon(brush, pontos); } } // ── EXTENSÕES DE GRAPHICS PARA ROUNDED RECT ─────────────────────────────── internal static class GraphicsExtensions { public static void FillRoundedRectangle(this Graphics g, Brush brush, Rectangle rect, int radius) { using var path = GetRoundedPath(rect, radius); g.FillPath(brush, path); } public static void DrawRoundedRectangle(this Graphics g, Pen pen, Rectangle rect, int radius) { using var path = GetRoundedPath(rect, radius); g.DrawPath(pen, path); } private static GraphicsPath GetRoundedPath(Rectangle rect, int radius) { int r = Math.Min(radius, Math.Min(rect.Width, rect.Height) / 2); var d = r * 2; var path = new GraphicsPath(); path.AddArc(rect.X, rect.Y, d, d, 180, 90); path.AddArc(rect.Right - d, rect.Y, d, d, 270, 90); path.AddArc(rect.Right - d, rect.Bottom - d, d, d, 0, 90); path.AddArc(rect.X, rect.Bottom - d, d, d, 90, 90); path.CloseFigure(); return path; } } }