using BLL; using CustomMessageBox; using DAL; using MLL; using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Windows.Forms; using AForge.Video; using AForge.Video.DirectShow; namespace UI { public class FuncionariosCadastroPanel : UserControl { private int idBanco = 0; private string _cx = DadosDaConexao.ObterConexao(); private readonly Color AccentBlue = Color.FromArgb(37, 99, 235); private readonly Color TextDark = Color.FromArgb(30, 41, 59); private readonly Color BorderColor = Color.FromArgb(226, 232, 240); private Panel pnlToolbar = null!; private Panel mainScroll = null!; private Panel content = null!; // Identificação private RoundTextBox txtId = null!, txtCodigo = null!, txtNome = null!; private RoundTextBox txtCPF = null!, txtCI = null!, txtCTPS = null!; private RoundTextBox txtCNH = null!, txtCatCNH = null!; private RoundTextBox txtECivil = null!, txtRegime = null!; // Filiação private RoundTextBox txtPai = null!, txtMae = null!; // Endereço private RoundTextBox txtcep=null!, txtEndereco = null!,txtEndNumero=null!, txtBairro = null!, txtCidade = null!, txtUF = null!; // Dados Bancários private RoundTextBox txtBanco = null!, txtAgencia = null!, txtConta = null!; private RoundComboBox cbBanco = null!; // Contato private RoundTextBox txtTelefone = null!; // Acesso private RoundTextBox txtPass = null!; private CheckBox chkMasterUser = null!, chkVendedor = null!, chkTecnico = null!; private CheckBox chkDemitido = null!, chkContador = null!, chkOutros = null!; // Outros private RoundTextBox txtFPath = null!, txtObserv = null!; // Datas private RoundTextBox txtDataAdm = null!, txtDataDem = null!, txtAniver = null!; // ── CARREGAR FUNCIONÁRIO ────────────────────────────────────────────── private void CarregarFuncionario(int id) { //var bll = new BLLFuncionarios(_cx); //var f = bll.CarregarPorId(id); //if (f == null) //{ // NT_MessageBox.Show("Funcionário não encontrado.", // "Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning); // return; //} //PreencherCampos(f); } private void PreencherCampos(ModeloFuncionarios f) { txtId.Text = f.ID_FUNCIONARIO.ToString(); txtCodigo.Text = f.CODIGO; txtNome.Text = f.NOME; txtPai.Text = f.PAI; txtMae.Text = f.MAE; txtCPF.Text = f.CPF; txtCI.Text = f.CI; txtCTPS.Text = f.CTPS; txtCNH.Text = f.CNH; txtCatCNH.Text = f.CAT_CNH; txtECivil.Text = f.ECIVIL; txtRegime.Text = f.REGIME; txtEndereco.Text = f.ENDERECO; txtBairro.Text = f.BAIRRO; txtCidade.Text = f.CIDADE; txtUF.Text = f.UF; txtBanco.Text = f.BANCO; txtAgencia.Text = f.AGENCIA; txtConta.Text = f.CONTA; txtTelefone.Text = f.TELEFONE; txtPass.Text = f.PASS; txtFPath.Text = f.FPATH; txtObserv.Text = f.OBSERV; //txtDataAdm.Text = f.DATA_ADM; //txtDataDem.Text = f.DATA_DEM; //txtAniver.Text = f.ANIVER; //chkMasterUser.Checked = f.MASTERUSER == "S"; //chkVendedor.Checked = f.VENDEDOR == "S"; //chkTecnico.Checked = f.TECNICO == "S"; //chkDemitido.Checked = f.DEMITIDO == "S"; //chkContador.Checked = f.FTECNICO == "S"; //chkOutros.Checked = f.FVENDEDOR == "S"; } private Control[] TodosOsControles() => new Control[]{ txtCodigo, txtNome, txtCPF, txtCI, txtCTPS, txtCNH, txtCatCNH, txtECivil, txtRegime, txtPai, txtMae, txtcep, txtEndereco, txtEndNumero, txtBairro, txtCidade, txtUF, // 👇 ComboBox entra aqui cbBanco, txtAgencia, txtConta, txtTelefone, txtPass, txtFPath, txtObserv, txtDataAdm, txtDataDem, txtAniver };//todos os controles private void SetCamposAtulizado(bool enabled) { foreach (var ctrl in TodosOsControles()) { ctrl.Enabled = enabled; // 🎨 Se for TextBox if (ctrl is RoundTextBox txt) { txt.BackColor = enabled ? Color.White : Color.FromArgb(241, 245, 249); } // 🎨 Se for ComboBox else if (ctrl is RoundComboBox cmb) { cmb.BackColor = enabled ? Color.White : Color.FromArgb(241, 245, 249); } } foreach (var chk in TodosOsChecks()) chk.Enabled = enabled; }//SetCampos private void CarregarComboBoxAtualizada() { BLLBancos bLLBancos = new BLLBancos(_cx); var tabela = bLLBancos.LocalizarTodos(); // 🔥 cria coluna personalizada tabela.Columns.Add("EXIBICAO", typeof(string), "NUMERO + ' - ' + NOME"); cbBanco.DataSource = tabela; cbBanco.DisplayMember = "EXIBICAO"; // 👈 aqui cbBanco.ValueMember = "ID_BANCOS"; if (cbBanco.SelectedValue != null) this.idBanco = Convert.ToInt32(cbBanco.SelectedValue); }//CarregarComboBoxAtualizada private DateTime? ConverterData(string texto) { if (string.IsNullOrWhiteSpace(texto)) return null; if (DateTime.TryParse(texto, out DateTime data)) return data; return null; }//ConverterData public FuncionariosCadastroPanel() { Dock = DockStyle.Fill; BackColor = Color.White; DoubleBuffered = true; InitializeLayout(); this.CarregarComboBoxAtualizada(); } private void InitializeLayout() { this.Controls.Clear(); // ── TOOLBAR ─────────────────────────────────────────────────────── pnlToolbar = new Panel { Dock = DockStyle.Top, Height = 55, BackColor = Color.FromArgb(248, 250, 252), BorderStyle = BorderStyle.None }; var flowButtons = new FlowLayoutPanel { Dock = DockStyle.Fill, Padding = new Padding(12, 10, 0, 0), BackColor = Color.Transparent }; var btnNovo = CreateToolbarButton("Novo", Color.FromArgb(34, 197, 94)); var btnAlterar = CreateToolbarButton("Alterar", Color.FromArgb(245, 158, 11)); var btnExcluir = CreateToolbarButton("Excluir", Color.FromArgb(239, 68, 68)); var btnLocalizar = CreateToolbarButton("Localizar", AccentBlue); var btnSalvar = CreateToolbarButton("Salvar", AccentBlue); var btnGerarFicha = CreateToolbarButton("Gerar Ficha", Color.FromArgb(255,0,0)); var btnCancelar = CreateToolbarButton("Cancelar", Color.FromArgb(148, 163, 184)); btnNovo.Click += (s, e) => BtnNovo_Click(); btnAlterar.Click += (s, e) => BtnAlterar_Click(); btnExcluir.Click += (s, e) => BtnExcluir_Click(); btnLocalizar.Click += (s, e) => BtnLocalizar_Click(); btnSalvar.Click += (s, e) => BtnSalvar_Click(); btnCancelar.Click += (s, e) => BtnCancelar_Click(); btnGerarFicha.Click += (s, e) => BtnFichaFuncionario_Click(); flowButtons.Controls.AddRange(new Control[] { btnNovo, btnAlterar, btnExcluir, btnLocalizar, btnSalvar,btnGerarFicha,btnCancelar }); pnlToolbar.Controls.Add(flowButtons); this.Controls.Add(pnlToolbar); // ── SCROLL + CONTENT ────────────────────────────────────────────── mainScroll = new Panel { Dock = DockStyle.Fill, AutoScroll = true, BackColor = Color.White }; this.Controls.Add(mainScroll); mainScroll.BringToFront(); content = new Panel { Width = 1100, Height = 900, Location = new Point(0, 0), BackColor = Color.White }; mainScroll.Controls.Add(content); const int rowH = 52; const int secGap = 10; const int secH = 28; const int inputH = 28; int y = 10; // ── 1. IDENTIFICAÇÃO DO FUNCIONÁRIO ─────────────────────────────── content.Controls.Add(CreateSectionHeader("IDENTIFICAÇÃO DO FUNCIONÁRIO", y)); y += secH + 4; txtId = AddInput(content, "ID", 20, y, 60, inputH, readOnly: true); txtCodigo = AddInput(content, "Código", 90, y, 100, inputH, readOnly: true); txtNome = AddInput(content, "Nome", 200, y, 450, inputH); y += rowH; txtCPF = AddInput(content, "CPF", 20, y, 160, inputH); DocumentoHelper.Registrar(txtCPF); txtCI = AddInput(content, "RG / CI", 190, y, 160, inputH); txtCTPS = AddInput(content, "CTPS", 360, y, 140, inputH); txtCNH = AddInput(content, "CNH", 510, y, 160, inputH); txtCatCNH = AddInput(content, "Cat. CNH", 680, y, 90, inputH); y += rowH; txtECivil = AddInput(content, "Estado Civil", 20, y, 160, inputH); txtRegime = AddInput(content, "Regime", 190, y, 160, inputH); // ── 2. FILIAÇÃO ─────────────────────────────────────────────────── y += rowH + secGap; content.Controls.Add(CreateSectionHeader("FILIAÇÃO", y)); y += secH + 4; txtPai = AddInput(content, "Nome do Pai", 20, y, 400, inputH); txtMae = AddInput(content, "Nome da Mãe", 430, y, 400, inputH); // ── 3. ENDEREÇO ───────────────────────────────────────────── y += rowH + secGap; content.Controls.Add(CreateSectionHeader("ENDEREÇO", y)); y += secH + 4; // LINHA ÚNICA txtcep = AddInput(content, "CEP", 20, y, 80, inputH); txtcep.Leave += (s, e) => { string cep = txtcep.Text.Trim().Replace("-", ""); if (cep.Length != 8) return; if (TLL.VerifyCep.verificaCEP(cep)) { txtEndereco.Text = TLL.VerifyCep.endereco; txtBairro.Text = TLL.VerifyCep.bairro; txtCidade.Text = TLL.VerifyCep.cidade; txtUF.Text = TLL.VerifyCep.estado; // Formata o CEP com hífen txtcep.Text = $"{cep[..5]}-{cep[5..]}"; } else { NT_MessageBox.Show("CEP não encontrado.", "CEP", MessageBoxButtons.OK, MessageBoxIcon.Warning); } };//cep txtEndereco = AddInput(content, "Logradouro", 110, y, 260, inputH); txtEndNumero = AddInput(content, "Nº", 380, y, 70, inputH); txtBairro = AddInput(content, "Bairro", 460, y, 150, inputH); txtCidade = AddInput(content, "Cidade", 620, y, 150, inputH); txtUF = AddInput(content, "UF", 780, y, 60, inputH); // ── 4. DADOS BANCÁRIOS ──────────────────────────────────────────── y += rowH + secGap; content.Controls.Add(CreateSectionHeader("DADOS BANCÁRIOS", y)); y += secH + 4; //txtBanco = AddInput(content, "Banco", 20, y, 280, inputH); cbBanco = AddComboBox(content, "Banco", 20, y, 200, inputH); txtAgencia = AddInput(content, "Agência", 310, y, 160, inputH); txtConta = AddInput(content, "Conta", 480, y, 160, inputH); // ── 5. CONTATO ──────────────────────────────────────────────────── y += rowH + secGap; content.Controls.Add(CreateSectionHeader("CONTATO", y)); y += secH + 4; txtTelefone = AddInput(content, "Telefone", 20, y, 200, inputH); // ── 6. ACESSO AO SISTEMA ────────────────────────────────────────── y += rowH + secGap; content.Controls.Add(CreateSectionHeader("ACESSO AO SISTEMA", y)); y += secH + 4; txtPass = AddInput(content, "Senha", 20, y, 200, inputH); txtPass.PasswordChar = '*'; y += rowH; chkMasterUser = CreateCheckBox("Master User", 20, y); chkVendedor = CreateCheckBox("Vendedor", 160, y); chkTecnico = CreateCheckBox("Técnico", 290, y); chkOutros = CreateCheckBox("Outros", 420, y); chkContador = CreateCheckBox("Contador", 560, y); chkDemitido = CreateCheckBox("Demitido", 690, y); content.Controls.AddRange(new Control[] { chkMasterUser, chkVendedor, chkTecnico, chkOutros, chkContador, chkDemitido }); // ── 7. OUTROS ───────────────────────────────────────────────────── y += 35 + secGap; content.Controls.Add(CreateSectionHeader("OUTROS", y)); y += secH + 4; // Label da foto var lblFoto = new Label { Text = "Caminho da Foto (FPATH)", Location = new Point(20, y), Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), ForeColor = TextDark, AutoSize = true }; content.Controls.Add(lblFoto); // Campo de texto da foto (menor para dar espaço ao botão lupa) txtFPath = new RoundTextBox { Location = new Point(20, y + 16), Size = new Size(560, inputH), Radius = 4, BorderColor = BorderColor, FocusColor = AccentBlue, BackColor = Color.White }; content.Controls.Add(txtFPath); // Botão lupa 🔍 var btnFoto = new Button { Text = "🔍", Location = new Point(588, y + 16), Size = new Size(36, inputH), FlatStyle = FlatStyle.Flat, BackColor = Color.FromArgb(37, 99, 235), ForeColor = Color.White, Font = new Font("Segoe UI", 11f), Cursor = Cursors.Hand, TabStop = false }; btnFoto.FlatAppearance.BorderSize = 0; btnFoto.Click += (s, e) => BtnFoto_Click(); content.Controls.Add(btnFoto); y += rowH; txtObserv = AddInput(content, "Observações", 20, y, 920, inputH); txtObserv.Multiline = true; txtObserv.Height = 60; // ── 8. DATAS ────────────────────────────────────────────────────── y += 70 + secGap; content.Controls.Add(CreateSectionHeader("DATAS", y)); y += secH + 4; txtDataAdm = AddInput(content, "Data de Admissão", 20, y, 175, inputH); txtDataDem = AddInput(content, "Data de Demissão", 205, y, 175, inputH); txtAniver = AddInput(content, "Aniversário", 390, y, 175, inputH); y += rowH; content.Height = y + 10; //SetCampos(false); SetCamposAtulizado(false); } // ── FOTO: LUPA ──────────────────────────────────────────────────────── private void BtnFoto_Click() { using var dlg = new FotoOrigemDialog(); if (dlg.ShowDialog() != DialogResult.OK) return; string? caminhoSalvo = dlg.UsarWebcam ? CapturarDaWebcam() : SelecionarDoComputador(); if (!string.IsNullOrEmpty(caminhoSalvo)) txtFPath.Text = caminhoSalvo; } private string? SelecionarDoComputador() { using var ofd = new OpenFileDialog { Title = "Selecionar Foto do Funcionário", Filter = "Imagens|*.jpg;*.jpeg;*.png;*.bmp|Todos os arquivos|*.*" }; if (ofd.ShowDialog() != DialogResult.OK) return null; return SalvarFoto(ofd.FileName); } private string? CapturarDaWebcam() { using var webcamForm = new WebcamCaptureForm(); if (webcamForm.ShowDialog() != DialogResult.OK) return null; if (webcamForm.ImagemCapturada == null) return null; string temp = Path.Combine(Path.GetTempPath(), $"webcam_{Guid.NewGuid()}.jpg"); webcamForm.ImagemCapturada.Save(temp, ImageFormat.Jpeg); return SalvarFoto(temp); } private string SalvarFoto(string origem) { const string pasta = @"C:\Levelcode\LevelOS\Uploads\Images\Funcionarios"; Directory.CreateDirectory(pasta); // Nome: NomeFuncionario_yyyyMMdd_HHmmss.jpg string nomeBase = string.IsNullOrWhiteSpace(txtNome.Text) ? "Funcionario" : txtNome.Text.Trim().Replace(" ", "_"); string nomeArq = $"{nomeBase}_{DateTime.Now:yyyyMMdd_HHmmss}.jpg"; string destino = Path.Combine(pasta, nomeArq); File.Copy(origem, destino, overwrite: true); return destino; } // ── CAMPOS ──────────────────────────────────────────────────────────── private RoundTextBox[] TodosOsCampos() => new[] { txtCodigo, txtNome, txtCPF, txtCI, txtCTPS, txtCNH, txtCatCNH, txtECivil, txtRegime, txtPai, txtMae, txtcep,txtEndereco,txtEndNumero, txtBairro, txtCidade, txtUF, /*txtBanco,*/ txtAgencia, txtConta, txtTelefone, txtPass, txtFPath, txtObserv, txtDataAdm, txtDataDem, txtAniver }; private CheckBox[] TodosOsChecks() => new[] { chkMasterUser, chkVendedor, chkTecnico, chkDemitido, chkContador, chkOutros }; private void SetCampos(bool enabled) { foreach (var campo in TodosOsCampos()) { campo.Enabled = enabled; campo.BackColor = enabled ? Color.White : Color.FromArgb(241, 245, 249); } foreach (var chk in TodosOsChecks()) chk.Enabled = enabled; } // ── EVENTOS ─────────────────────────────────────────────────────────── private void BtnNovo_Click() { foreach (var campo in TodosOsCampos()) campo.Text = string.Empty; foreach (var chk in TodosOsChecks()) chk.Checked = false; //SetCampos(true); SetCamposAtulizado(true); } private void BtnAlterar_Click() { if (string.IsNullOrWhiteSpace(txtId.Text)) { NT_MessageBox.Show( "Nenhum registro selecionado para alterar.", "Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } //SetCampos(true); SetCamposAtulizado(true); txtId.Enabled = false; txtId.BackColor = Color.FromArgb(241, 245, 249); } private void BtnExcluir_Click() { } private void BtnLocalizar_Click() { // Abre tela/diálogo de busca e preenche os campos } private void BtnSalvar_Click() { var bll = new BLLFuncionarios(_cx); if (string.IsNullOrWhiteSpace(txtNome.Text) || string.IsNullOrWhiteSpace(txtCPF.Text)) { NT_MessageBox.Show("Preencha ao menos Nome e CPF.", "Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } bool isNew = string.IsNullOrWhiteSpace(txtId.Text); var funcionario = new ModeloFuncionarios { ID_FUNCIONARIO = isNew ? 0 : int.Parse(txtId.Text), CODIGO = txtCodigo.Text, NOME = txtNome.Text, PAI = txtPai.Text, MAE = txtMae.Text, CPF = txtCPF.Text, CI = txtCI.Text, CTPS = txtCTPS.Text, CNH = txtCNH.Text, CAT_CNH = txtCatCNH.Text, ECIVIL = txtECivil.Text, REGIME = txtRegime.Text, CEP = txtcep.Text, ENDERECO = txtEndereco.Text, ENDNUMERO = txtEndNumero.Text, BAIRRO = txtBairro.Text, CIDADE = txtCidade.Text, UF = txtUF.Text, // 🔥 BANCO vindo do ComboBox BANCO = cbBanco.SelectedValue?.ToString(), AGENCIA = txtAgencia.Text, CONTA = txtConta.Text, TELEFONE = txtTelefone.Text, PASS = txtPass.Text, // 🔥 BOOL correto MASTERUSER = chkMasterUser.Checked, VENDEDOR = chkVendedor.Checked, TECNICO = chkTecnico.Checked, DEMITIDO = chkDemitido.Checked, FTECNICO = chkContador.Checked ? "1" : null, FVENDEDOR = chkOutros.Checked ? "1" : null, FPATH = txtFPath.Text, OBSERV = txtObserv.Text, // 🔥 DATAS DATA_ADM = ConverterData(txtDataAdm.Text), DATA_DEM = ConverterData(txtDataDem.Text), ANIVER = ConverterData(txtAniver.Text) }; bool sucesso = isNew ? bll.Inserir(funcionario) : bll.Alterar(funcionario); if (!sucesso) { NT_MessageBox.Show("Erro ao salvar funcionário.", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } SetCampos(false); NT_MessageBox.Show("Funcionário salvo com sucesso!", "Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information); } private void BtnFichaFuncionario_Click() { var bll = new BLLFuncionarios(_cx); var funcionario = bll.CarregarPorCodigo("100"); if (funcionario == null) { MessageBox.Show("Funcionário não encontrado."); return; } var resultado = TLL.FichaFuncionarioPDF.GerarEAbrir(funcionario); if (!resultado.Sucesso) MessageBox.Show(resultado.Mensagem, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error); } private void BtnCancelar_Click() { foreach (var campo in TodosOsCampos()) campo.Text = string.Empty; foreach (var chk in TodosOsChecks()) chk.Checked = false; //SetCampos(false); SetCamposAtulizado(false); //this.cbBanco.Enabled = false; } // ── HELPERS ─────────────────────────────────────────────────────────── private Panel CreateSectionHeader(string title, int y) { var pnl = new Panel { Location = new Point(20, y), Width = 1000, Height = 26 }; var lbl = new Label { Text = title, Font = new Font("Segoe UI", 8.5f, FontStyle.Bold), ForeColor = AccentBlue, AutoSize = true, Location = new Point(0, 0) }; var line = new Panel { BackColor = BorderColor, Height = 1, Width = 980, Location = new Point(0, 20) }; pnl.Controls.Add(lbl); pnl.Controls.Add(line); return pnl; } private RoundTextBox AddInput(Control parent, string label, int x, int y, int width, int height, bool readOnly = false) { var lbl = new Label { Text = label, Location = new Point(x, y), Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), ForeColor = readOnly ? Color.Gray : TextDark, AutoSize = true }; var txt = new RoundTextBox { Location = new Point(x, y + 16), Size = new Size(width, height), Radius = 4, BorderColor = readOnly ? Color.FromArgb(203, 213, 225) : BorderColor, FocusColor = AccentBlue, ReadOnly = readOnly, BackColor = readOnly ? Color.FromArgb(241, 245, 249) : Color.White }; parent.Controls.Add(lbl); parent.Controls.Add(txt); return txt; } private RoundComboBox AddComboBox(Control parent, string label, int x, int y, int width, int height) { var lbl = new Label { Text = label, Location = new Point(x, y), Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), ForeColor = TextDark, AutoSize = true }; var cb = new RoundComboBox { Location = new Point(x, y + 16), Size = new Size(width, height), Radius = 4, BorderColor = BorderColor, FocusColor = AccentBlue, BackColor = Color.White }; parent.Controls.Add(lbl); parent.Controls.Add(cb); return cb; } private CheckBox CreateCheckBox(string text, int x, int y) => new CheckBox { Text = text, Location = new Point(x, y), Font = new Font("Segoe UI", 8.5f, FontStyle.Bold), ForeColor = TextDark, AutoSize = true }; private RoundButton CreateToolbarButton(string text, Color color) => new RoundButton { Text = text, Size = new Size(95, 32), BackColor = color, ForeColor = Color.White, Font = new Font("Segoe UI Semibold", 8.5f), Margin = new Padding(0, 0, 6, 0), Cursor = Cursors.Hand }; } // ══════════════════════════════════════════════════════════════════════════ // DIALOG: Escolher origem da foto (Computador ou Webcam) // ══════════════════════════════════════════════════════════════════════════ public class FotoOrigemDialog : Form { public bool UsarWebcam { get; private set; } public FotoOrigemDialog() { Text = "Selecionar Foto"; Size = new Size(340, 160); StartPosition = FormStartPosition.CenterParent; FormBorderStyle = FormBorderStyle.FixedDialog; MaximizeBox = false; MinimizeBox = false; BackColor = Color.White; var lbl = new Label { Text = "Como deseja adicionar a foto?", Font = new Font("Segoe UI", 9.5f), Location = new Point(20, 18), AutoSize = true }; var btnComputador = new Button { Text = "📁 Do Computador", Location = new Point(20, 55), Size = new Size(140, 38), FlatStyle = FlatStyle.Flat, BackColor = Color.FromArgb(37, 99, 235), ForeColor = Color.White, Font = new Font("Segoe UI", 9f), Cursor = Cursors.Hand }; btnComputador.FlatAppearance.BorderSize = 0; btnComputador.Click += (s, e) => { UsarWebcam = false; DialogResult = DialogResult.OK; Close(); }; var btnWebcam = new Button { Text = "📷 Webcam", Location = new Point(172, 55), Size = new Size(140, 38), FlatStyle = FlatStyle.Flat, BackColor = Color.FromArgb(16, 185, 129), ForeColor = Color.White, Font = new Font("Segoe UI", 9f), Cursor = Cursors.Hand }; btnWebcam.FlatAppearance.BorderSize = 0; btnWebcam.Click += (s, e) => { UsarWebcam = true; DialogResult = DialogResult.OK; Close(); }; Controls.AddRange(new Control[] { lbl, btnComputador, btnWebcam }); } } // ══════════════════════════════════════════════════════════════════════════ // FORM: Captura pela Webcam usando AForge // ══════════════════════════════════════════════════════════════════════════ public class WebcamCaptureForm : Form { public Bitmap? ImagemCapturada { get; private set; } private PictureBox picPreview = null!; private VideoCaptureDevice? _camera; private Bitmap? _frameAtual; public WebcamCaptureForm() { Text = "Capturar Foto pela Webcam"; Size = new Size(680, 560); StartPosition = FormStartPosition.CenterParent; FormBorderStyle = FormBorderStyle.FixedDialog; MaximizeBox = false; BackColor = Color.FromArgb(15, 23, 42); picPreview = new PictureBox { Location = new Point(20, 20), Size = new Size(628, 440), SizeMode = PictureBoxSizeMode.Zoom, BackColor = Color.Black }; Controls.Add(picPreview); var btnCapturar = new Button { Text = "📷 Capturar", Location = new Point(20, 475), Size = new Size(200, 38), FlatStyle = FlatStyle.Flat, BackColor = Color.FromArgb(37, 99, 235), ForeColor = Color.White, Font = new Font("Segoe UI", 9.5f), Cursor = Cursors.Hand }; btnCapturar.FlatAppearance.BorderSize = 0; btnCapturar.Click += BtnCapturar_Click; Controls.Add(btnCapturar); var btnCancelar = new Button { Text = "Cancelar", Location = new Point(234, 475), Size = new Size(120, 38), FlatStyle = FlatStyle.Flat, BackColor = Color.FromArgb(100, 116, 139), ForeColor = Color.White, Font = new Font("Segoe UI", 9.5f), Cursor = Cursors.Hand }; btnCancelar.FlatAppearance.BorderSize = 0; btnCancelar.Click += (s, e) => { PararCamera(); DialogResult = DialogResult.Cancel; Close(); }; Controls.Add(btnCancelar); FormClosing += (s, e) => PararCamera(); IniciarCamera(); } private void IniciarCamera() { var cameras = new FilterInfoCollection(FilterCategory.VideoInputDevice); if (cameras.Count == 0) { MessageBox.Show("Nenhuma webcam encontrada.", "Webcam", MessageBoxButtons.OK, MessageBoxIcon.Warning); DialogResult = DialogResult.Cancel; Close(); return; } _camera = new VideoCaptureDevice(cameras[0].MonikerString); _camera.NewFrame += Camera_NewFrame; _camera.Start(); } private void Camera_NewFrame(object sender, NewFrameEventArgs e) { _frameAtual?.Dispose(); _frameAtual = (Bitmap)e.Frame.Clone(); picPreview.Invoke((MethodInvoker)(() => { picPreview.Image?.Dispose(); picPreview.Image = (Bitmap)_frameAtual.Clone(); })); } private void BtnCapturar_Click(object? sender, EventArgs e) { if (_frameAtual == null) { MessageBox.Show("Aguarde a câmera inicializar.", "Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } ImagemCapturada = (Bitmap)_frameAtual.Clone(); PararCamera(); DialogResult = DialogResult.OK; Close(); } private void PararCamera() { if (_camera != null && _camera.IsRunning) { _camera.SignalToStop(); _camera.WaitForStop(); } } } }