terça-feira, 21 de setembro de 2010

DragDrop de arquivos em C#

Não pretendia fazer outro post tão cedo, mas lembrei disso e achei que poderia ser interessante.

Estive trabalhando em um software que envia um arquivo pela porta serial.
A princípio o arquivo deveria ser procurado entre as pastas do computador através de uma janela do Explorer e ao clicar em "Abrir" na janela de navegação o caminho do arquivo era copiado para uma TextBox na minha janela principal.
Eu decidi adicionar uma opção em que se possa arrastar e soltar o arquivo na janela e então recuperar o caminho para manipular o arquivo como desejado. Fiz isso utilizando os eventos de DragDrop já disponíveis em C#.

No caso estou trabalhando dentro da classe da minha janela principal, chamada Form1.cs e tenho uma TextBox chamada nomeArquivo.

A primeira coisa a fazer é modificar a propriedade AllowDrop da Form1 para true. Isso pode ser feito no modo Design.

A parte do código é bem simples.
É possivel recuperar o caminho do arquivo desejado na forma de um vetor de strings de forma muito simples. Se você soltar um grupo de arquivos você ficará com o caminho de cada arquivo em uma posição do vetor.

Exemplo: Eu usei o evento DragEnter para definir o efeito e DragDrop para recuperar o caminho do arquivo.

{
.
.
.
    private void Form1_DragEnter(object sender, DragEventArgs e)
    {
        if(e.Data.GetDataPresent(DataFormats.FileDrop))
            e.Effect = DragDropEffects.Copy;
    }

    private void Form1_DragDrop(object sender, DragEventArgs e)
    {

        string[] arquivos = (string[])e.Data.GetData(DataFormats.FileDrop);
        nomeArquivo.Text = arquivos.Last();
    }
.
.
.
}


No caso eu não tenho como carregar mais de um arquivo ao mesmo tempo, então eu decidi optar por pegar sempre o último arquivo do vetor (se colocar apenas um arquivo, ele é carregado; se forem vários, pega só o último do vetor). Mas só fiz isso porque realmente não me interessa, nessse caso, trabalhar com mais de um arquivo.

Até mais.

sexta-feira, 17 de setembro de 2010

Problema com threads e porta serial em C#

Faz um tempão que não posto aqui, mas hoje também não poderei me deter muito aqui. O fato de eu não ter postado nada aqui ultimamente não quer dizer que eu esteja parado. O problema é que algumas vezes começo a trabalhar em mais de um software ao mesmo e começa a ficar difícil filtrar e decidir o que pode ser interessante postar aqui e o que só é relevante lá dentro do software mesmo.
Mas essa semana me deparei com algo muito incômodo. Eu já fiz um outro post falando um pouco sobre comunicação serial com C#, então não vou entrar em detalhes agora, embora eu não tenha explorado todos os recursos da classe SerialPort naquele post. Mas o fato aqui é outro: usar uma thread para receber os dados de uma porta serial.
Mas o que é uma thread?
Thread é um trecho de código-fonte que deve ser executado determinado número de vezes (ou o tempo inteiro) em paralelo ao código do programa. Na prática esses processos não são paralelos, o que acontece na verdade é uma alternância entre o código principal e o código da thread.
Eu, particularmente, prefiro não usar threads se houver uma forma de não usá-las, mas às vezes não há escapatória.

Meu caso:
Estive refazendo um código de programa desenvolvido em VB 6.0 que o Visual Studio converteu parcialmente para VB.NET. O software usava um componente de comunicação serial obsoleto (conhecido como MSComm) o qual substitui por um objeto da classe SerialPort do namespace System.IO.Ports, com as devidas alterações no código-fonte, claro. Mas não foi sobre isso que vim escrever.
Feito isso decidi reescrever o código em C# (para fins de conhecimento geral, pois isso me ajudou a conhecer um pouco do VB.NET, que até então não tinha tido contato) e depois implementar um terminal de comunicação serial no software. Basicamente um terminal para enviar comandos via porta serial e escrever as linhas recebidas como resposta na tela.
O problema de fazer isso é que é necessário ficar "monitorando" a porta serial, ficar constantemente lendo a entrada de dados. Para fazer isso pode-se criar uma thread que fique executando um código que leia a porta serial e escreva o que foi lido num TextBox, por exemplo. Mas não vou entrar no detalhe da criação de uma thread.
A outra forma de fazer isso é usar o evento DataReceived existente na classe SerialPort e é a forma que demonstrarei. Esse evento já funciona como uma thread então os mesmos problemas que eu tive com thread eu encontrei ao lidar com esse evento.