Mostrar mensagens com a etiqueta WinForm. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta WinForm. Mostrar todas as mensagens

terça-feira, 16 de abril de 2024

Aprenda a Evitar Memory Leaks no .NET com Dispose e Blocos Using



Os memory leaks são como fantasmas assombrando os desenvolvedores de software. Eles podem se esconder silenciosamente em nossos códigos, consumindo recursos preciosos e prejudicando o desempenho do aplicativo. No ambiente .NET, a gestão de memória é parcialmente automatizada pelo coletor de lixo (garbage collector), mas mesmo assim, é responsabilidade do desenvolvedor garantir a liberação adequada de recursos não gerenciados. Felizmente, o .NET oferece algumas ferramentas poderosas para lidar com isso, como o método Dispose() e os blocos using.

O Que São Memory Leaks?

Um memory leak ocorre quando um programa aloca memória dinamicamente repetidamente, mas não libera essa memória quando não é mais necessária. Isso pode acontecer por várias razões, mas é especialmente comum quando trabalhamos com recursos não gerenciados, como arquivos, conexões de banco de dados e objetos COM.

A Importância do Método Dispose()

O método Dispose() é uma parte fundamental do padrão de design "Dispose pattern" no .NET. Ele é usado para liberar explicitamente os recursos não gerenciados usados por um objeto. Ao implementar a interface IDisposable e chamar o método Dispose(), os desenvolvedores podem garantir que os recursos sejam liberados assim que não forem mais necessários.

Usando Blocos Using para Garantir a Liberação de Recursos

Os blocos using no C# fornecem uma maneira conveniente de garantir que os objetos que implementam IDisposable sejam liberados corretamente, mesmo se ocorrerem exceções no código. Um bloco using garante que o método Dispose() seja chamado automaticamente quando o escopo do bloco é concluído.

 

Exemplo Prático

Vamos examinar um trecho de código e explorar como podemos melhorá-lo para garantir uma gestão mais robusta de recursos no ambiente .NET.



No código acima, estamos lidando com uma operação de leitura de dados de um banco SQLite e exibindo-os em um DataGridView. Pode ser que vocês já estejas  familiarizado com códificação parecida. No entanto, há alguns problemas de gestão de recursos que precisamos resolver:

1. Gestão de Conexão com o Banco de Dados

O objeto SQLiteConnection precisa ser aberto e fechado corretamente para evitar vazamentos de recursos. Vamos usar um bloco using para garantir que a conexão seja fechada automaticamente quando não for mais necessária.



2. Limpeza de Recursos em Caso de Exceção

Se ocorrer uma exceção durante a execução do código dentro do bloco using, precisamos garantir que os recursos sejam liberados corretamente. Vamos mover a definição do objeto DataTable para dentro do bloco using e usar o método Dispose() para liberar o leitor e o comando em caso de exceção.



Conclusão

Lidar com memory leaks no .NET é crucial para manter a estabilidade e o desempenho dos aplicativos. Utilizar corretamente o método Dispose() e os blocos using é uma prática recomendada para garantir a liberação adequada de recursos não gerenciados. Ao melhorar a gestão de recursos em nosso código, garantimos que ele seja mais robusto, eficiente e menos propenso a problemas como memory leaks. Utilizando blocos using para objetos que implementam IDisposable, lidamos adequadamente com a liberação de recursos. Ao seguir essas práticas, podemos criar aplicativos mais estáveis e de alta qualidade no ambiente .NET. Adotar essas práticas desde o início do desenvolvimento, os desenvolvedores podem evitar muitas dores de cabeça no futuro e garantir uma experiência de usuário mais suave.

  

sexta-feira, 31 de agosto de 2018

Como exportar Crystal Report para PDF e Excel (código completo)

Vamos aprender, de forma rápida, como exportar um relatório de Crystal Report para os formatos PDF e Excel. Como exemplo vou pegar o projecto que fizemos no post anterior. Clica aqui para ver.

Adicione os botões "Exportar PDF" e "Exportar Excel" no formulário para exportar o relatório.



Para o botão "Exportar PDF" coloque o seguinte código:


private void btnExportToPDF_Click(object sender, EventArgs e)
{
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Filter = "Arquivo PDF|*.pdf";
            string nomeArquivo="";
            if(dialog.ShowDialog()== DialogResult.OK)
            {
                nomeArquivo = dialog.FileName;
            cr.ExportToDisk(ExportFormatType.PortableDocFormat, nomeArquivo);
            }
            
}

Para o botão "Exportar Excel" coloque o seguinte código:

private void btnExportToExcel_Click(object sender, EventArgs e)
{
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Filter = "Arquivo Excel|*.xls";
            string nomeArquivo = "";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                nomeArquivo = dialog.FileName;
            cr.ExportToDisk(ExportFormatType.Excel, nomeArquivo);
            }

}

Como podemos ver, para os dois botões, colocamos um SaveFileDialog para o utilizador poder escolher a pasta e o nome do arquivo.



Executa o programa e testa cada botão. Espero te ajudado.

Código completo deste projecto.


public partial class FormPaises : Form
    {
        public FormPaises()
        {
            InitializeComponent();
        }
        Reports.ReportPaises2 cr = new Reports.ReportPaises2();

        private List<Pais> GetListaPaises()
        {
            List<Pais> Paises = new List<Pais>
            {
                new Pais(1, "Angola"),
                new Pais(2, "Brasil"),
                new Pais(3, "Portugal"),
                new Pais(6, "Moçambique"),
                new Pais(7, "Cabo-Verde"),
                new Pais(8, "Namibia")
            };

            return Paises;
        }

        private void FormPaises_Load(object sender, EventArgs e)
        {
            crystalReportViewer1.ReportSource = cr;

            cr.SetDataSource(GetListaPaises());

        }

        private void btnExportToPDF_Click(object sender, EventArgs e)
        {
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Filter = "Arquivo PDF|*.pdf";
            string nomeArquivo="";
            if(dialog.ShowDialog()== DialogResult.OK)
            {
                nomeArquivo = dialog.FileName;
            cr.ExportToDisk(ExportFormatType.PortableDocFormat, nomeArquivo);
            }
         

        }

        private void btnExportToExcel_Click(object sender, EventArgs e)
        {
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Filter = "Arquivo Excel|*.xls";
            string nomeArquivo = "";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                nomeArquivo = dialog.FileName;
            cr.ExportToDisk(ExportFormatType.Excel, nomeArquivo);
            }


        }
    }

Como criar um relatório CrystalReport sem banco de dados


A um tempo tive problemas com as conexões do crystal report. Quando passava a aplicação para outros computadores tinha que trocar também a conexão, porem muitas vezes esquecia de fazer esse processo e ficava horas e horas para descobrir onde estava o problema. Por isso optei por usar os crystal report sem conexão directa a base de dados.

O que vamos ver é pequeno exemplo de como criar um relatório de Lista de Países com o Crystal Reports a partir de uma lista de objectos sem ter uma banco de dados.


Passo 1

Certifique-se de ter Crystal Report para o Visual Studio instalado.

Passo 2

Cria um novo projecto WinForm. Neste exemplo criei um projecto com nome TesteCrystalSemDB. A seguir, cria uma classe País como o seguinte:

public class Pais
    {
        public Pais(int codigo,string nome)
        {
            this.Codigo = codigo;
            this.NomePais = nome;
        }
        public int Codigo { get; set; }
        public string NomePais { get; set; }
    }

Passo 3


Adicione um novo formulário com o nome FormPaises, e adicione o seguinte método:

        private List<Pais> GetListaPaises()
        {
            List<Pais> Paises = new List<Pais>
            {
                new Pais(1, "Angola"),
                new Pais(2, "Brasil"),
                new Pais(3, "Portugal"),
                new Pais(6, "Moçambique"),
                new Pais(7, "Cabo-Verde"),
                new Pais(8, "Namibia")
            };

            return Paises;
        }

Passo 4

Adicione um DataSet. Nomeia-o por DataSet1 como na figura abaixo:



Dentro da DataSet adicione uma DataTable com o nome de Pais, e cria as colunas com os mesmos nome dos atributos da classe Pais. ( Esse é o maior segredo ;). Confirma na figura acima.

Passo 5


Adicione ao projecto um Crystal Report e nomeio-o por ReportPaises2, clique em Add.

 Aparecerá uma caixa como a que se segui, as  opeções criar um nome documento de crystal report, escolha a segunda, Relatório em Branco e clica OK.

Passo 6

Restamos definir a fonte de dados ou DataSet no nosso Crystal Report. Para isso, vai em Fiel Explorer dê um clique direito na Database Fiel para selecionar o opção Database Expert conforme a figura abaixo mostra:


No assistente, expande Dados de Projecto > Conjuntos de Dados ADO.NET > TesteCrystalSemDB.DataSet1e seleccione a DataTable Pais.


 Modele a aparência do relatório, e adicione os campos que deseja ao relatório, confirme na figura:

Passo 7


Volte para o formulário FormPaises, vai à ToolBox, escolha o CrystalReportViewer, coloque-o ao formulário e nomeia-o por crystalReportViewer1.

Selecione este novo componente e (1) no seu canto superior direito dê um clique para ver a lista de propriedades, (2) clique em "Escolher um Crystal Report, (3) Selecione o relatorio que criamos "ReportPaises2", (4) clique em OK.
 No evento Load do formulário cole o seguinte código:

private void FormPaises_Load(object sender, EventArgs e)
{
            Reports.ReportPaises2 cr = new Reports.ReportPaises2();
            crystalReportViewer1.ReportSource = cr;

            cr.SetDataSource(GetListaPaises());

}

Pronto, o relatório está feito, basta pressionar F5 para testar.


Bonus

A propriedade SetDataSource do CrystalReport pode receber qualquer colecção de dados. Por isso aproveita essa propriedade colocar a tua fonte da dados. Como eu disse no inicio deste post, não acho viável os dados serem dependentes da conexão do Crystal Report.

sexta-feira, 27 de julho de 2018

Como definir a resolução do monitor com o C#

Tive dificuldade em definir uma resolução de tela dinâmica quando estava fazendo um aplicativo. Eu presumo que a maioria de nós tenha acontecido conosco ou tenha enfrentado esses tempos em algum lugar ao longo de nosso ciclo de vida de engenharia. Porque, como todos sabemos, a resolução da tela do usuário pode não ser a mesma da tela do ambiente de desenvolvimento.

Neste post vou entregar o que eu encontrei como uma solução para o desafio discutido.
Então vamos ver:


  • Como obter a resolução do monitor do usuário.
  • Como alterar a resolução do monitor do usuário para produto compatível
  • Como proteger a resolução do monitor do usuário.

Como obter a resolução do monitor do usuário


O acesso à tela do usuário está sendo facilitado pela classe Screen, que é fornecida junto com a estrutura .NET. E pode acessar a resolução da tela do usuário atual por meio de uma propriedade Screen.PrimaryScreen que é estática disponível na classe Screen:

public static Screen PrimaryScreen {get;}

A propriedade acima mencionada é somente leitura e retorna um tipo  Screen. E a lógica abaixo mostra como usar o tipo Screen para acessar a resolução da tela do usuário:

Screen screen = Screen.PrimaryScreen;
int S_width=screen.Bounds.Width;

int S_height=screen.Bounds.Height;



Como alterar a resolução do monitor do usuário para produto compatível


Antes de seguir em direção ao nosso próximo objetivo, deixe-me falar sobre a parte não gerenciada dessa implementação. Ao contrário das linguagens tradicionais, a estrutura .NET mantém uma etapa distinta enquanto aproveita o código gerenciado e não gerenciado. Pessoalmente, quando escrevi este artigo, nunca encontrei nenhum código gerenciado que faça esse tratamento de resolução. E isso é o que me fez pensar em explorar algumas APIs do Win32.

Como o escopo deste artigo está limitado ao código gerenciado, não discutirei nada sobre código não gerenciado. Mas, apesar disso, podemos usar o atributo DllImport para ler a definição de código não gerenciado em seu ambiente gerenciado. Neste caso, estaremos usando a API User32.dll, que facilita a resolução dinâmica e possui duas funções relacionadas à alteração da resolução da tela.


  • EnumDisplaySettings
  • ChangeDisplaySettings


class User32
{
        [DllImport("user32.dll")]
        public static extern int EnumDisplaySettings (string deviceName, int modeNum, ref DEVMODE devMode );         
        [DllImport("user32.dll")]
        public static extern int ChangeDisplaySettings(
              ref DEVMODE devMode, int flags); 

        public const int ENUM_CURRENT_SETTINGS = -1;
        public const int CDS_UPDATEREGISTRY = 0x01;
        public const int CDS_TEST = 0x02;
        public const int DISP_CHANGE_SUCCESSFUL = 0;
        public const int DISP_CHANGE_RESTART = 1;
        public const int DISP_CHANGE_FAILED = -1;
}


Como sabemos, o [DllImport("user32.dll")] é um trabalho explícito antes de injetar uma implementação não gerenciada em nosso ambiente gerenciado.


public static extern int EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode);

DEVMODE é uma estrutura explicada na documentação da plataforma, bem como incluída no Visual Studio .NET. A estrutura é definida em C#, por isso não se preocupar!


[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE 
{
        [MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)] 
          public string dmDeviceName;
        public short  dmSpecVersion;
        public short  dmDriverVersion;
        ... 
}

Você pode dar uma olhada no código-fonte clicando aqui e aplicar essa lógica a qualquer evento desejado.


Esteja ciente de que, os tipos têm o tamanho certo e que as seqüências de comprimento fixo são apropriadamente definida. Neste caso, WORD mapeia para short, DWORD para int e short permanece como short.

DEVMODE dm = new DEVMODE();
dm.dmDeviceName = new String(new char[32]);
dm.dmFormName = new String(new char[32]);
dm.dmSize = (short)Marshal.SizeOf (dm); 

if (0 !=User32.EnumDisplaySettings(null,User32.ENUM_CURRENT_SETTINGS,ref dm))
{

Neste ponto, a estrutura DEVMODE será decorado com as configurações padrão e pode modificá-la em qualquer instância.

dm.dmPelsWidth = iWidth;
dm.dmPelsHeight = iHeight; 
int iRet = User32.ChangeDisplaySettings(ref dm, User32.CDS_UPDATEREGISTRY);


O bloco de código fechado faz isso um pouco diferente de lidar com várias condições de erro. Gostaria de incentivá-lo a olhar para o arquivo fonte completo e ver o que ele faz. Isso é tudo que existe para isso.


Como proteger a resolução de tela do usuário

Finalmente, antes de continuarmos, é nossa responsabilidade salvaguardar a resolução de tela padrão de um usuário. Para fazer isso, você pode ter que usar alguns membros ou classes estáticas para manter a resolução da tela do usuário e retê-la quando concluir a execução.


Bonus - O código-fonte completo


Fim de conversa, para ver o código-fonte de graça clica aqui.
Espero ter ajudado. Força!

quarta-feira, 30 de maio de 2018

Como arraste e solte uma imagem de uma pasta para picturebox com C#


Vamos aprendemos como arraste e solte uma imagem de uma pasta para picturebox no WinForms.
Passo 1: crie um novo aplicativo do Windows em C#. 
Passo 2: Tome o controle picturebox e coloque-o no formulário abaixo.


Passo 3:  defina a propriedade AllowDrop do formulário como True.
Passo 4: Colocar mais quatro namespace.
using System.Drawing;
using System.IO;
using
 System.Threading;
using
 System.Diagnostics;

Passo 5:Escreva o código a seguir.


using System;
using System.Collections.Generic;
using
 System.ComponentModel;
using
 System.Data;
using
 System.Drawing;
using
 System.Linq;
using
 System.Text;
using
 System.Windows.Forms;
using
 System.IO;
using
 System.Threading;
using
 System.Diagnostics;

namespace WindowsFormsApplication1
{
    
public partial class Form1 : Form
    {

        protected bool validData;
        string path;
        
protected Image image;
        
protected Thread getImageThread        public Form1()
        {

            InitializeComponent();

        }

        private void Form1_DragEnter(object sender, DragEventArgs e)
        {
            
string filename;
            validData = GetFilename(
out filename, e);
            
if (validData)
            {

                path = filename;

                getImageThread = 
new Thread(new ThreadStart(LoadImage));
                getImageThread.Start();

                e.Effect = DragDropEffects.Copy;

            }

            
else
                e.Effect = DragDropEffects.None;

        }

        
private bool GetFilename(out string filename, DragEventArgs e) 

        {
            
bool ret = false;
            filename = 
String.Empty;
            
if ((e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy)
            {
                
Array data = ((IDataObject)e.Data).GetData("FileDrop") as Array;
                
if (data != null)
                {

                    
if ((data.Length == 1) && (data.GetValue(0) is String))
                    {

                        filename = ((
string[])data)[0];
                        
string ext = Path.GetExtension(filename).ToLower();
                        
if ((ext == ".jpg") || (ext == ".png") || (ext == ".bmp"))
                       {

                            ret = 
true;
                        }

                    }

                }

            }

            
return ret;
        }

        private void Form1_DragDrop(object sender, DragEventArgs e)
        {
            
if (validData)
            {

                
while (getImageThread.IsAlive)
                {

                    Application.DoEvents();

                    
Thread.Sleep(0);
                }

                pictureBox1.Image = image;

            }

        }

        protected void LoadImage()
        {
            image = 
new Bitmap(path);
        }

    }

}


Etapa 6: Executar o aplicativo, F5.
Etapa 7: Arraste o arquivo de imagem no formulário.


quarta-feira, 16 de maio de 2018

Como usar o ColorDialog no C#

ColorDialog
Um controle ColorDialog é usado para selecionar uma cor das cores disponíveis e também definir cores personalizadas. Uma caixa de diálogo de cores típica se parece com a Figura 1, onde você pode ver que há uma lista de cores sólidas básicas e que há uma opção para criar cores personalizadas.
ColorDialogImg1.jpg
figura 1
Criando um ColorDialog
Podemos criar um controle ColorDialog usando um designer de formulários no tempo de design ou usando a classe ColorDialog no código em tempo de execução (também conhecido como dinamicamente). Ao contrário de outros controles do Windows Forms, um ColorDialog não tem e não precisa de propriedades visuais como os outros. O único objetivo do ColorDialog é exibir cores disponíveis, criar cores personalizadas e selecionar uma cor dessas cores. Quando uma cor é selecionada, precisamos dessa cor em nosso código para que possamos aplicá-la em outros controles.
Novamente, você pode criar um ColorDialog em tempo de design, mas é mais fácil criar um ColorDialog em tempo de execução.
Tempo de design
Para criar um controle ColorDialog em tempo de design, basta arrastar e soltar um controle ColorDialog da caixa de ferramentas para um formulário no Visual Studio. Depois de arrastar e soltar um ColorDialog em um formulário, o ColorDialog se parece com a Figura 2.
ColorDialogImg2.jpg
Figura 2
Adicionando um ColorDialog a um formulário adiciona seguindo duas linhas de código.

private System.Windows.Forms. ColorDialog colorDialog1;
this .colorDialog1 = new System.Windows.Forms. ColorDialog ();
Tempo de execução
Criar um controle ColorDialog em tempo de execução é apenas um trabalho de criar uma instância da classe ColorDialog, definir suas propriedades e adicionar a classe ColorDialog aos controles de formulário.
O primeiro passo para criar um ColorDialog dinâmico é criar uma instância da classe ColorDialog. O trecho de código a seguir cria um objeto de controle ColorDialog.
ColorDialog colorDlg = new ColorDialog ();

O método ShowDialog do ColorDialog exibe o ColorDialog. O trecho de código a seguir define as propriedades cor de plano de fundo, cor de primeiro plano, Texto, Nome e Fonte de um ColorDialog.
colorDlg.ShowDialog ();

Uma vez que o método ShowDialog é chamado, você pode escolher cores na caixa de diálogo.

Definindo as propriedades do ColorDialog
Depois de colocar um controle ColorDialog em um formulário, a próxima etapa é definir propriedades.
A maneira mais fácil de definir propriedades é a partir da janela Propriedades. Você pode abrir a janela Propriedades pressionando F4 ou clique com o botão direito em um controle e selecione o item de menu Propriedades. A janela Propriedades se parece com a Figura 3.
ColorDialogImg3.jpg
Figura 3
AllowFullOpen
Se você observar a Figura 1, verá um botão chamado Definir cores personalizadas no ColorDialog. Clicar neste botão abre a área do editor de cores personalizadas, onde você pode definir as cores definindo valores de cores RGB (entre 0 e 255) e também pode selecionar uma cor na área de cores, como você pode ver na Figura 4.
ColorDialogImg4.jpg
Figura 4
A propriedade AllowFullOpen garante que a opção Definir cor personalizada esteja ativada em um ColorDialog. Se você deseja desabilitar esta opção, você pode definir a propriedade AllowFullOpencomo false e seu ColorDialog será semelhante à Figura 5.
ColorDialogImg5.jpg
Figura 5
 
O trecho de código a seguir define a propriedade AllowFullOpen como false.
colorDlg.AllowFullOpen = false ;
Cor, AnyColor e SolidColorOnly
A propriedade Color é usada para obter e definir a cor selecionada pelo usuário em um ColorDialog.
AnyColor é usado para obter e definir se um ColorDialog exibe todas as cores disponíveis no conjunto de cores básicas.
SolidColorOnly é usado para obter e definir se um ColorDialog restringe os usuários a selecionar somente cores sólidas.
O fragmento de código a seguir define essas propriedades.
colorDlg.AnyColor = true ;
colorDlg.SolidColorOnly = false ;
colorDlg.Color = Cor . Vermelho ;
Usando ColorDialog em Aplicativos
Agora vamos criar um aplicativo que use um ColorDialog para definir cores de vários controles. O aplicativo do Windows Forms é semelhante à Figura 6.
ColorDialogImg6.jpg
Figura 6
Na Figura 6, temos alguns controles do Windows Forms e clicar nos botões Foreground Color e Background Color permitirá que o usuário selecione uma cor e defina essa cor como cores de primeiro e segundo plano dos controles. Depois de selecionar as cores de primeiro plano e de fundo, o formulário se parece com a Figura 7.
ColorDialogImg7.jpg
Figura 7
O trecho de código a seguir é o código para os botões Foreground Color e Background Color, clique em manipuladores de eventos.
Vazio privado ForegroundButton_Click ( remetente do objeto , EventArgs e)
{
    ColorDialog colorDlg = new ColorDialog ();
    colorDlg.AllowFullOpen = false ;
    colorDlg.AnyColor = true ;
    colorDlg.SolidColorOnly = false ;
    colorDlg.Color = Cor . Vermelho ;
                    
    if (colorDlg.ShowDialog () == DialogResult .OK)
    {
        textBox1.ForeColor = colorDlg.Color;
        listBox1.ForeColor = colorDlg.Color;
        button3.ForeColor = colorDlg.Color;
    }
}

private void BackgroundButton_Click ( remetente do objeto , EventArgs e)
{
    ColorDialog colorDlg = new ColorDialog ();
    if (colorDlg.ShowDialog () == DialogResult .OK)
    {
        textBox1.BackColor = colorDlg.Color;
        listBox1.BackColor = colorDlg.Color;
        button3.BackColor = colorDlg.Color;
    }
}

Resumo 
Um controle ColorDialog permite que os usuários iniciem o Diálogo de Cor do Windows e permitam que eles selecionem uma cor sólida ou criem uma cor personalizada a partir das cores disponíveis. Neste artigo, discutimos como usar um diálogo de cores do Windows e definir suas propriedades em um aplicativo do Windows Forms.

Pesquisar neste blogue

Com tecnologia do Blogger.

Páginas