using CPM; using CustomMessageBox; using System; using System.Drawing; using System.Windows.Forms; // Atalhos estáticos — eliminam o prefixo "ScreenProfile." em todo o arquivo using static UI.ScreenProfile; namespace UI { public class OrdensCadastroPanel : FormularioModelo { #region Campos private Label lblNumeroOS = null!; private Panel cardCliente = null!; private Panel cardDatas = null!; private Panel cardFinanceiro = null!; private Panel cardRodape = null!; private TabControl tabDetalhes = null!; private LV_TEXTBOX1 txtCliente = null!; private LV_TEXTBOX1 txtEndereco = null!; private LV_TEXTBOX1 txtTelefones = null!; private LV_TEXTBOX1 txtDocs = null!; private LV_TEXTBOX1 txtEmail = null!; private LV_TEXTBOX1 txtGarantia = null!; private LV_TEXTBOX1 txtAdiantamento = null!; private LV_TEXTBOX1 txtMaoObra = null!; private LV_TEXTBOX1 txtPecas = null!; private LV_TEXTBOX1 txtDeslocamento = null!; private LV_TEXTBOX1 txtServicosTerceiros = null!; private LV_TEXTBOX1 txtOutros = null!; private LV_TEXTBOX1 txtTotal = null!; private DateTimePicker dtpEntrada = null!; private DateTimePicker dtpPronto = null!; private DateTimePicker dtpSaida = null!; private DateTimePicker dtpGarantia = null!; private ComboBox cbSituacao = null!; private ComboBox cbTecnico = null!; private ComboBox cbPrioridade = null!; #endregion // ══════════════════════════════════════════════════════════════ // Layout base: desenhado para 1920x1080 @ 96 DPI (Scale = 1.0) // Tudo que está em pixels aqui é o valor ANTES da escala. // Use sempre S(), P(), Sz(), R(), F() para aplicar o Scale. // ══════════════════════════════════════════════════════════════ public OrdensCadastroPanel() { Titulo = "Ordem de Serviço"; content.Width = S(1180); content.Height = S(870); content.BackColor = Color.FromArgb(245, 247, 250); BuildInterface(); #if DEBUG if (ParentForm != null) ParentForm.Text += $" [{ScreenProfile.Diagnostico()}]"; #endif } #region Build private void BuildInterface() { BuildHeader(); BuildCliente(); BuildDatasStatus(); BuildFinanceiro(); BuildTabs(); BuildRodape(); } // Card interno (com borda simples, sem sombra) private Panel CreateInternalCard(string title, Rectangle rect) { var pnl = new Panel { Location = rect.Location, Size = rect.Size, BackColor = Color.White, BorderStyle = BorderStyle.FixedSingle }; var lbl = new Label { Text = title, Font = new Font("Segoe UI", F(8.5f), FontStyle.Bold), ForeColor = AccentBlue, Location = P(8, 6), AutoSize = true }; pnl.Controls.Add(lbl); return pnl; } #endregion // ────────────────────────────────────────────────────────────── // HEADER (y=10, h=60) // ────────────────────────────────────────────────────────────── #region Header private void BuildHeader() { var header = new Panel { Location = P(10, 10), Size = Sz(1160, 60), BackColor = Color.White }; header.Paint += CardPaint; lblNumeroOS = new Label { Text = "O.S. nº 1771", Font = new Font("Segoe UI", F(20f), FontStyle.Bold), ForeColor = Color.FromArgb(210, 38, 38), Location = P(12, 8), AutoSize = true }; var lblSub = new Label { Text = "Cadastro e gerenciamento da ordem de serviço", Font = new Font("Segoe UI", F(8f)), ForeColor = Color.Gray, Location = P(15, 42), AutoSize = true }; header.Controls.Add(lblNumeroOS); header.Controls.Add(lblSub); content.Controls.Add(header); } #endregion // ────────────────────────────────────────────────────────────── // CLIENTE (y=80, h=160) // ────────────────────────────────────────────────────────────── #region Cliente private void BuildCliente() { cardCliente = CreateCard(R(10, 80, 850, 170), "Dados do Cliente"); // Calcula tudo em pixels JA ESCALADOS para evitar dupla escala int m = S(12); int iw = cardCliente.Width - m * 2; int gap = S(8); int col = (iw - gap * 2) / 3; int h26 = S(26); int h16 = S(16); int y1 = S(35); int y2 = S(80); int y3 = S(125); // Helper local: coordenadas ja em pixels escalados LV_TEXTBOX1 Inp(Control p, string lbl, int x, int y, int w) { p.Controls.Add(new Label { Text = lbl, Font = new Font("Segoe UI", F(8f), FontStyle.Bold), ForeColor = TextDark, Location = new Point(x, y), AutoSize = true }); var tb = new LV_TEXTBOX1 { Location = new Point(x, y + h16), Size = new Size(w, h26), BorderColor = BorderColor, BorderFocusColor = AccentBlue, BackColor = Color.White }; p.Controls.Add(tb); return tb; } txtCliente = Inp(cardCliente, "Cliente", m, y1, iw); txtEndereco = Inp(cardCliente, "Endereço", m, y2, iw); txtTelefones = Inp(cardCliente, "Telefones", m, y3, col); txtDocs = Inp(cardCliente, "Documentos", m + col + gap, y3, col); txtEmail = Inp(cardCliente, "E-mail", m + (col + gap) * 2, y3, iw - (col + gap) * 2); content.Controls.Add(cardCliente); txtCliente.Text = "Nicolas Felipe G. dos santos"; } #endregion // ────────────────────────────────────────────────────────────── // STATUS E DATAS (y=248, h=130) // ────────────────────────────────────────────────────────────── #region Datas private void BuildDatasStatus() { cardDatas = CreateCard(R(10, 248, 850, 130), "Status e Datas"); // Linha 1 AddSmallLabel(cardDatas, "Entrada", 12, 35); dtpEntrada = CreatePicker(12, 52, 175); cardDatas.Controls.Add(dtpEntrada); AddSmallLabel(cardDatas, "Saída", 200, 35); dtpSaida = CreatePicker(200, 52, 175); cardDatas.Controls.Add(dtpSaida); cbSituacao = AddComboBox(cardDatas, "Situação da OS", 390, 35, 445); // Linha 2 AddSmallLabel(cardDatas, "Pronto", 12, 85); dtpPronto = CreatePicker(12, 102, 175); cardDatas.Controls.Add(dtpPronto); AddSmallLabel(cardDatas, "Garantia até", 200, 85); dtpGarantia = CreatePicker(200, 102, 175); cardDatas.Controls.Add(dtpGarantia); var btnHistorico = new Button { Text = "🕘 Histórico", Location = P(390, 97), Size = Sz(210, 28), FlatStyle = FlatStyle.Flat, BackColor = Color.White, ForeColor = TextDark, Font = new Font("Segoe UI Semibold", F(8.5f)), Cursor = Cursors.Hand }; btnHistorico.FlatAppearance.BorderColor = BorderColor; btnHistorico.FlatAppearance.MouseOverBackColor = Color.FromArgb(235, 240, 255); btnHistorico.Click += (s, e) => MessageBox.Show("Abrir histórico da OS", "Histórico", MessageBoxButtons.OK, MessageBoxIcon.Information); cardDatas.Controls.Add(btnHistorico); content.Controls.Add(cardDatas); } #endregion // ────────────────────────────────────────────────────────────── // FINANCEIRO (x=870, y=80, w=300, h=298) // — alinhado com Cliente + Datas somados // ────────────────────────────────────────────────────────────── #region Financeiro private void BuildFinanceiro() { // altura = 160(cliente) + 8(gap) + 130(datas) = 298 cardFinanceiro = CreateCard(R(870, 80, 300, 298), "Financeiro"); int y = 35; int step = 34; // espaço entre linhas — compacto txtAdiantamento = AddFinanceRow(cardFinanceiro, "Adiantamento", y); y += step; txtMaoObra = AddFinanceRow(cardFinanceiro, "Mão-de-obra", y); y += step; txtPecas = AddFinanceRow(cardFinanceiro, "Peças", y); y += step; txtDeslocamento = AddFinanceRow(cardFinanceiro, "Deslocamento", y); y += step; txtServicosTerceiros = AddFinanceRow(cardFinanceiro, "Serv. terceiros", y); y += step; txtOutros = AddFinanceRow(cardFinanceiro, "Outros", y); y += step + 8; var line = new Panel { BackColor = BorderColor, Location = P(10, y), Size = Sz(278, 1) }; cardFinanceiro.Controls.Add(line); y += 10; var lblTotal = new Label { Text = "TOTAL", Font = new Font("Segoe UI", F(10f), FontStyle.Bold), ForeColor = Color.FromArgb(220, 38, 38), Location = P(12, y + 6), AutoSize = true }; txtTotal = new LV_TEXTBOX1 { Location = P(110, y), Size = Sz(168, 32), Font = new Font("Segoe UI", F(12f), FontStyle.Bold), TextAlign = HorizontalAlignment.Right, BorderColor = Color.FromArgb(220, 38, 38), BorderFocusColor = Color.FromArgb(220, 38, 38), ForeColor = Color.FromArgb(220, 38, 38) }; cardFinanceiro.Controls.Add(lblTotal); cardFinanceiro.Controls.Add(txtTotal); content.Controls.Add(cardFinanceiro); } #endregion // ────────────────────────────────────────────────────────────── // TABS (y=386, h=420) // ────────────────────────────────────────────────────────────── #region Tabs private void BuildTabs() { tabDetalhes = new TabControl { Location = P(10, 386), Size = Sz(1160, 430), Font = new Font("Segoe UI", F(8.5f)), DrawMode = TabDrawMode.OwnerDrawFixed, SizeMode = TabSizeMode.Fixed, ItemSize = Sz(170, 30) }; tabDetalhes.DrawItem += DrawTab; BuildTabAparelho(); BuildTabServicos(); BuildTabPecas(); BuildTabLaudo(); BuildTabMiscelanea(); content.Controls.Add(tabDetalhes); } // ── Aparelho ───────────────────────────────────────────────── private void BuildTabAparelho() { var tab = new TabPage("Aparelho") { BackColor = Color.White }; AddModernInput(tab, "Modelo", 12, 12, 490); AddModernInput(tab, "Marca", 520, 12, 490); AddModernInput(tab, "Operadora", 12, 70, 280); AddModernInput(tab, "Serial", 310, 70, 280); AddModernInput(tab, "Nº Patrimônio", 608, 70, 402); var txtAcessorios = AddModernInput(tab, "Acessórios", 12, 128, 490, 80); txtAcessorios.Multiline = true; var txtDefeito = AddModernInput(tab, "Defeito / Reclamação", 520, 128, 490, 80); txtDefeito.Multiline = true; tabDetalhes.TabPages.Add(tab); } // ── Mão de obra / Serviços ─────────────────────────────────── private void BuildTabServicos() { var tab = new TabPage("Mão de obra / Serviços") { BackColor = Color.White }; tab.Controls.Add(new Label { Text = "Serviços executados nesta OS", Font = new Font("Segoe UI", F(8.5f), FontStyle.Bold), ForeColor = TextDark, Location = P(12, 10), AutoSize = true }); var grid = CriarGrid(P(12, 30), Sz(940, 230)); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Descrição", Width = S(310) }); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Tipo", Width = S(80) }); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Início", Width = S(70) }); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Fim", Width = S(70) }); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Qtd", Width = S(55) }); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Valor", Width = S(90) }); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Técnico", Width = S(290) }); tab.Controls.Add(grid); // menu lateral var pnl = new Panel { Location = P(962, 30), Size = Sz(170, 230), BackColor = Color.White }; pnl.Controls.Add(BotaoLateral("Padrões", 0, AccentBlue, (s, e) => NT_MessageBox.Show("Testando evento click padrão", "Padrão", MessageBoxButtons.OK, MessageBoxIcon.Information))); pnl.Controls.Add(BotaoLateral("Avulsos", 44, Color.FromArgb(34, 197, 94))); pnl.Controls.Add(BotaoLateral("Excluir", 88, Color.FromArgb(239, 68, 68))); pnl.Controls.Add(new Label { Text = "Total horas", Font = new Font("Segoe UI", F(8f), FontStyle.Bold), ForeColor = TextDark, Location = P(8, 130), AutoSize = true }); pnl.Controls.Add(new LV_TEXTBOX1 { Location = P(8, 146), Size = Sz(148, 26), BorderColor = BorderColor, BorderFocusColor = AccentBlue, Font = new Font("Segoe UI", F(9f), FontStyle.Bold) }); pnl.Controls.Add(new Label { Text = "Total", Font = new Font("Segoe UI", F(8.5f), FontStyle.Bold), ForeColor = Color.Red, Location = P(8, 175), AutoSize = true }); pnl.Controls.Add(new LV_TEXTBOX1 { Location = P(8, 193), Size = Sz(148, 28), BorderColor = Color.Red, BorderFocusColor = Color.Red, Font = new Font("Segoe UI", F(10f), FontStyle.Bold), ForeColor = Color.Red }); tab.Controls.Add(pnl); // observações tab.Controls.Add(new Label { Text = "Observações internas", Font = new Font("Segoe UI", F(8f), FontStyle.Bold), ForeColor = TextDark, Location = P(12, 272), AutoSize = true }); tab.Controls.Add(new LV_TEXTBOX1 { Location = P(12, 288), Size = Sz(940, 80), Multiline = true, BorderColor = BorderColor, BorderFocusColor = AccentBlue }); tab.Controls.Add(BotaoLateral("Deslocamentos", 288, AccentBlue, location: P(962, 288), size: Sz(148, 32))); tabDetalhes.TabPages.Add(tab); } // ── Peças utilizadas ───────────────────────────────────────── private void BuildTabPecas() { var tab = new TabPage("Peças utilizadas") { BackColor = Color.White }; tab.Controls.Add(new Label { Text = "Peças utilizadas nesta OS", Font = new Font("Segoe UI", F(8.5f), FontStyle.Bold), ForeColor = TextDark, Location = P(12, 10), AutoSize = true }); var grid = CriarGrid(P(12, 30), Sz(940, 340)); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Peça nº", Width = S(115) }); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Descrição", Width = S(295) }); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Valor un", Width = S(105) }); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Qtd.", Width = S(75) }); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Valor Total", Width = S(115) }); grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Técnico", Width = S(190) }); tab.Controls.Add(grid); var pnl = new Panel { Location = P(962, 30), Size = Sz(170, 340), BackColor = Color.White }; pnl.Controls.Add(BotaoLateral("Peças do Estoque", 0, AccentBlue)); pnl.Controls.Add(BotaoLateral("Peças avulsas", 44, Color.FromArgb(34, 197, 94))); pnl.Controls.Add(BotaoLateral("KIT Montado", 88, Color.FromArgb(245, 158, 11))); pnl.Controls.Add(BotaoLateral("Excluir", 132, Color.FromArgb(239, 68, 68))); pnl.Controls.Add(BotaoLateral("Inserir orçamento", 176, Color.FromArgb(99, 102, 241))); pnl.Controls.Add(BotaoLateral("Requisição", 220, Color.FromArgb(107, 114, 128))); tab.Controls.Add(pnl); tabDetalhes.TabPages.Add(tab); } // ── Laudo técnico ──────────────────────────────────────────── private void BuildTabLaudo() { var tab = new TabPage("Obs / Laudo técnico") { BackColor = Color.White }; tab.Controls.Add(new Label { Text = "Laudo técnico / detalhes do conserto", Font = new Font("Segoe UI", F(8.5f), FontStyle.Bold), ForeColor = TextDark, Location = P(12, 10), AutoSize = true }); tab.Controls.Add(new Label { Text = "(SHIFT + Enter para nova linha)", Font = new Font("Segoe UI", F(7.5f)), ForeColor = Color.Gray, Location = P(820, 12), AutoSize = true }); var txtLaudo = new LV_TEXTBOX1 { Location = P(12, 30), Size = Sz(1118, 330), Multiline = true, BorderColor = BorderColor, BorderFocusColor = AccentBlue, Font = new Font("Segoe UI", F(9f)), BackColor = Color.White }; tab.Controls.Add(txtLaudo); var btnPreencher = new Button { Text = "📝 Preencher Laudo", Location = P(12, 372), Size = Sz(165, 32), FlatStyle = FlatStyle.Flat, BackColor = AccentBlue, ForeColor = Color.White, Font = new Font("Segoe UI Semibold", F(8.5f)), Cursor = Cursors.Hand }; btnPreencher.FlatAppearance.BorderSize = 0; btnPreencher.Click += (s, e) => { txtLaudo.Text = "Equipamento analisado e testado em bancada.\r\n\r\n" + "Foi identificado defeito no componente principal.\r\n\r\n" + "Realizado:\r\n- limpeza interna\r\n- substituição de peças\r\n- testes finais\r\n\r\n" + "Equipamento funcionando normalmente."; }; tab.Controls.Add(btnPreencher); tabDetalhes.TabPages.Add(tab); } // ── Miscelânea ─────────────────────────────────────────────── private void BuildTabMiscelanea() { var tab = new TabPage("Miscelânea") { BackColor = Color.White }; // ── Card Garantia (x=10, y=10, w=640, h=260) var cardGarantia = CreateInternalCard("Garantia / Garantidor", R(10, 10, 640, 260)); var cbGarantidor = AddComboBox(cardGarantia, "Fábrica / Garantidor", 10, 22, 290); cbGarantidor.Items.AddRange(new object[] { "Nenhum", "Samsung", "LG", "Motorola", "Dell" }); cbGarantidor.SelectedIndex = 0; AddSmallLabel(cardGarantia, "Senha garantidor", 10, 68); cardGarantia.Controls.Add(new LV_TEXTBOX1 { Location = P(10, 84), Size = Sz(210, 26), BorderColor = BorderColor, BorderFocusColor = AccentBlue }); cardGarantia.Controls.Add(new Label { Text = "A fábrica/Garantidor é aquele que pagará pelo reparo.", Font = new Font("Segoe UI", F(7.5f)), ForeColor = Color.FromArgb(120, 53, 15), BackColor = Color.FromArgb(254, 249, 195), Location = P(235, 84), Size = Sz(385, 36), TextAlign = ContentAlignment.MiddleCenter }); AddSmallLabel(cardGarantia, "Nº NF de venda", 10, 126); cardGarantia.Controls.Add(new LV_TEXTBOX1 { Location = P(10, 142), Size = Sz(170, 26), BorderColor = BorderColor, BorderFocusColor = AccentBlue }); AddSmallLabel(cardGarantia, "Nº certificado de garantia", 198, 126); cardGarantia.Controls.Add(new LV_TEXTBOX1 { Location = P(198, 142), Size = Sz(422, 26), BorderColor = BorderColor, BorderFocusColor = AccentBlue }); AddSmallLabel(cardGarantia, "Data da compra", 10, 184); cardGarantia.Controls.Add(new DateTimePicker { Location = P(10, 200), Width = S(170), Format = DateTimePickerFormat.Short, Font = new Font("Segoe UI", F(8.5f)) }); AddSmallLabel(cardGarantia, "Revendedor", 198, 184); cardGarantia.Controls.Add(new LV_TEXTBOX1 { Location = P(198, 200), Size = Sz(422, 26), BorderColor = BorderColor, BorderFocusColor = AccentBlue }); tab.Controls.Add(cardGarantia); // ── Card NF Entrada (x=660, y=10, w=480, h=120) var cardNF = CreateInternalCard("Nota Fiscal Entrada / Remessa", R(660, 10, 490, 120)); AddSmallLabel(cardNF, "Número da NF", 10, 22); cardNF.Controls.Add(new LV_TEXTBOX1 { Location = P(10, 38), Size = Sz(145, 26), BorderColor = BorderColor, BorderFocusColor = AccentBlue }); AddSmallLabel(cardNF, "Valor da NF", 168, 22); cardNF.Controls.Add(new LV_TEXTBOX1 { Location = P(168, 38), Size = Sz(290, 26), BorderColor = BorderColor, BorderFocusColor = AccentBlue }); var cbFornecedorNF = AddComboBox(cardNF, "Emissor (Fornecedor)", 10, 72, 448); cbFornecedorNF.Items.Add("Nenhum"); cbFornecedorNF.SelectedIndex = 0; tab.Controls.Add(cardNF); // ── Card Terceiros (x=660, y=138, w=480, h=132) var cardTerceiros = CreateInternalCard("OS de Terceiros / Parceiros", R(660, 138, 490, 132)); AddSmallLabel(cardTerceiros, "Nº OS terceiros", 10, 22); cardTerceiros.Controls.Add(new LV_TEXTBOX1 { Location = P(10, 38), Size = Sz(140, 26), BorderColor = BorderColor, BorderFocusColor = AccentBlue }); AddSmallLabel(cardTerceiros, "Nº OS Fabricante", 162, 22); cardTerceiros.Controls.Add(new LV_TEXTBOX1 { Location = P(162, 38), Size = Sz(165, 26), BorderColor = BorderColor, BorderFocusColor = AccentBlue }); var cbFornecedor = AddComboBox(cardTerceiros, "Emissor (Fornecedor)", 10, 72, 448); cbFornecedor.Items.Add("Nenhum"); cbFornecedor.SelectedIndex = 0; tab.Controls.Add(cardTerceiros); tabDetalhes.TabPages.Add(tab); } #endregion // ────────────────────────────────────────────────────────────── // RODAPÉ (y=824, h=56) // ────────────────────────────────────────────────────────────── #region Rodapé private void BuildRodape() { cardRodape = CreateCard(R(10, 824, 1160, 46), ""); cbTecnico = AddComboBox(cardRodape, "Técnico Responsável", 12, 5, 320); cbPrioridade = AddComboBox(cardRodape, "Prioridade", 348, 5, 160); cbPrioridade.Items.AddRange(new object[] { "Baixa", "Normal", "Alta", "Urgente", "Emergencial" }); cbPrioridade.SelectedIndex = 1; var btnFotos = new Button { Text = "Fotos / Docs", Location = P(980, 8), Size = Sz(155, 30), FlatStyle = FlatStyle.Flat, BackColor = AccentBlue, ForeColor = Color.White, Font = new Font("Segoe UI Semibold", F(8.5f)), Cursor = Cursors.Hand }; btnFotos.FlatAppearance.BorderSize = 0; cardRodape.Controls.Add(btnFotos); content.Controls.Add(cardRodape); } #endregion // ────────────────────────────────────────────────────────────── // HELPERS // ────────────────────────────────────────────────────────────── #region Helpers private Panel CreateCard(Rectangle rect, string title) { var pnl = new Panel { Location = rect.Location, Size = rect.Size, BackColor = Color.White }; pnl.Paint += CardPaint; if (!string.IsNullOrWhiteSpace(title)) { pnl.Controls.Add(new Label { Text = title, Font = new Font("Segoe UI", F(9f), FontStyle.Bold), ForeColor = AccentBlue, Location = P(12, 10), AutoSize = true }); pnl.Controls.Add(new Panel { BackColor = BorderColor, Location = P(12, 30), Size = new Size(rect.Width - S(24), 1) }); } return pnl; } private LV_TEXTBOX1 AddModernInput( Control parent, string label, int x, int y, int width, int height = 26) { parent.Controls.Add(new Label { Text = label, Font = new Font("Segoe UI", F(8f), FontStyle.Bold), ForeColor = TextDark, Location = P(x, y), AutoSize = true }); var txt = new LV_TEXTBOX1 { Location = P(x, y + 16), Size = Sz(width, height), BorderColor = BorderColor, BorderFocusColor = AccentBlue, BackColor = Color.White }; parent.Controls.Add(txt); return txt; } private LV_TEXTBOX1 AddFinanceRow(Control parent, string text, int y) { parent.Controls.Add(new Label { Text = text, Font = new Font("Segoe UI", F(8f), FontStyle.Bold), ForeColor = TextDark, Location = P(10, y + 5), AutoSize = true }); var txt = new LV_TEXTBOX1 { Location = P(118, y), Size = Sz(164, 26), TextAlign = HorizontalAlignment.Right, BorderColor = BorderColor, BorderFocusColor = AccentBlue }; parent.Controls.Add(txt); return txt; } private void AddSmallLabel(Control parent, string text, int x, int y) { parent.Controls.Add(new Label { Text = text, Font = new Font("Segoe UI", F(8f), FontStyle.Bold), ForeColor = TextDark, Location = P(x, y), AutoSize = true }); } private DateTimePicker CreatePicker(int x, int y, int width) { return new DateTimePicker { Location = P(x, y), Width = S(width), Format = DateTimePickerFormat.Custom, CustomFormat = "dd/MM/yyyy HH:mm", Font = new Font("Segoe UI", F(8.5f)) }; } private ComboBox AddComboBox(Control parent, string label, int x, int y, int width) { AddSmallLabel(parent, label, x, y); var cb = new ComboBox { Location = P(x, y + 16), Size = Sz(width, 26), Font = new Font("Segoe UI", F(8.5f)), DropDownStyle = ComboBoxStyle.DropDownList }; parent.Controls.Add(cb); return cb; } // Grid padrão reutilizável private DataGridView CriarGrid(Point location, Size size) { var grid = new DataGridView { Location = location, Size = size, BackgroundColor = Color.White, BorderStyle = BorderStyle.FixedSingle, AllowUserToAddRows = false, AllowUserToDeleteRows = false, AllowUserToResizeRows = false, RowHeadersVisible = false, SelectionMode = DataGridViewSelectionMode.FullRowSelect, MultiSelect = false, AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None, EnableHeadersVisualStyles = false, Font = new Font("Segoe UI", F(8f)), GridColor = BorderColor, ColumnHeadersHeight = S(26) }; grid.ColumnHeadersDefaultCellStyle.BackColor = Color.FromArgb(245, 247, 250); grid.ColumnHeadersDefaultCellStyle.ForeColor = TextDark; grid.ColumnHeadersDefaultCellStyle.Font = new Font("Segoe UI", F(8f), FontStyle.Bold); return grid; } // Botão lateral padronizado — overload simples private Button BotaoLateral(string texto, int y, Color cor, EventHandler? click = null) { var btn = new Button { Text = texto, Location = P(8, y), Size = Sz(148, 38), FlatStyle = FlatStyle.Flat, BackColor = cor, ForeColor = Color.White, Font = new Font("Segoe UI Semibold", F(8f)), Cursor = Cursors.Hand }; btn.FlatAppearance.BorderSize = 0; if (click != null) btn.Click += click; return btn; } // Botão lateral com posição e tamanho explícitos private Button BotaoLateral(string texto, int y, Color cor, Point location, Size size, EventHandler? click = null) { var btn = new Button { Text = texto, Location = location, Size = size, FlatStyle = FlatStyle.Flat, BackColor = cor, ForeColor = Color.White, Font = new Font("Segoe UI Semibold", F(8f)), Cursor = Cursors.Hand }; btn.FlatAppearance.BorderSize = 0; if (click != null) btn.Click += click; return btn; } #endregion // ────────────────────────────────────────────────────────────── // EVENTOS VISUAIS // ────────────────────────────────────────────────────────────── #region Eventos Visuais private void CardPaint(object? sender, PaintEventArgs e) { var pnl = sender as Panel; using var pen = new Pen(BorderColor); e.Graphics.DrawRectangle(pen, 0, 0, pnl!.Width - 1, pnl.Height - 1); } private void DrawTab(object? sender, DrawItemEventArgs e) { var tab = tabDetalhes.TabPages[e.Index]; bool selected = e.Index == tabDetalhes.SelectedIndex; using var back = new SolidBrush(selected ? AccentBlue : Color.FromArgb(230, 233, 238)); using var fore = new SolidBrush(selected ? Color.White : TextDark); e.Graphics.FillRectangle(back, e.Bounds); e.Graphics.DrawString( tab.Text, new Font("Segoe UI", F(8.5f), FontStyle.Bold), fore, e.Bounds, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }); } #endregion // ────────────────────────────────────────────────────────────── // MÉTODOS ABSTRATOS // ────────────────────────────────────────────────────────────── #region Métodos Abstratos protected override void OnNovo() { } protected override void OnAlterar() { } protected override void OnExcluir() { } protected override void OnLocalizar() { } protected override void OnSalvar() { } protected override void OnCancelar() { } #endregion } }