Índice. Delphi. Editorial. Dicas Delphi .NET. Desafio The CLub. Legenda. Introdução a Porta Paralela - PDF
Índice. Delphi. Editorial. Dicas Delphi .NET. Desafio The CLub. Legenda. Introdução a Porta Paralela
Download "Índice. Delphi. Editorial. Dicas Delphi .NET. Desafio The CLub. Legenda. Introdução a Porta Paralela"
Alícia Benevides César
3 Índice Editorial Neste mês apresentaremos o artigo Diretivas de Compilação Parte I do consultor Luiz Alexandre, neste artigo é abordado um assunto ainda obscuro para a maioria dos programadores, mas com grande potencial para auxiliar o programador. Alexandre lista e esclarece neste artigo as principais diretivas com alguns exemplos, e mostra que recursos e possibilidades são enormes usando as diretivas de compilação do Delphi. Victory Fernandes está de volta apresentando Juliana Andrade Carvalho e Rafael Araújo, onde juntos escrevem o artigo Introdução a Porta Paralela Escrevendo bits via Delphi, neste artigo é abordado à automatização de processos utilizando como principal forma de comunicação a porta paralela. 04 Delphi Introdução a Porta Paralela 05 Utilizando as API s do windows para melhorar a aplicação 12 Diretivas de compilação - Parte I 18.NET A nova fase da WEB com Silverlight Legenda Iniciante Intermediário Avançado 23 Dicas Delphi Corrigindo erro na distribuições desenvolvidas em 2009 com SQL Server Obter o nome do usuário e da empresa informado durante a instalação do Windows Criar cores personalizadas (sistema RGB) Gerar uma tabela no Word através do Delphi Obter o valor de uma variável de ambiente Aumentar um Edit em tempo de execução 28 Desafio The CLub Teste seus conhecimentos. 30 maio
4 Bem-vindo Neste mês apresentaremos o artigo Diretivas de Compilação Parte I do consultor Luiz Alexandre, neste artigo é abordado um assunto ainda obscuro para a maioria dos programadores, mas com grande potencial para auxiliar o programador. Alexandre lista e esclarece neste artigo as principais diretivas com alguns exemplos, e mostra que recursos e possibilidades são enormes usando as diretivas de compilação do Delphi. Victory Fernandes está de volta apresentando Juliana Andrade Carvalho e Rafael Araújo, onde juntos escrevem o artigo Introdução a Porta Paralela Escrevendo bits via Delphi, neste artigo é abordado à automatização de processos utilizando como principal forma de comunicação a porta paralela. Neste assunto que vai muito além da programação software, teremos conhecimentos técnicos sobre a tecnologia de acesso a hardwares até mesmo conceitos de eletrônica digital, artigo este bastante interessante que vale muito a pena sua leitura. Para os programadores não tão iniciantes, mas que precisam aprimorar suas técnicas de programação, Antonio Spitaleri Neto vem com o artigo Utilizando as API s do Windows para melhorar a aplicação. Neste artigo ele mostra recursos do sistema operacional simples de serem implementados na sua aplicação, mas que pode trazer grandes funcionalidades para a aplicação, funcionalidades estas que dificilmente iria ser possível de ser implementada usando apenas os recursos do Delphi. A nova Fase da web com Silverlight é o artigo para.net de Luiz Alexandre, onde ele apresenta a tecnologia SilverLight da Microsoft para desenvolvimento web. Usando as palavras do autor essa tecnologia é capaz de trabalhar com um conceito novo de recursos visuais, como os de som e vídeo, animações, além da praticidade, usabilidade, agilidade e intuitividade de navegação. Desejo a todos uma boa leitura e espero que se divirtam com seus novos códigos. Av. Profº Celso Ferreira da Silva, 190 Jd. Europa - Avaré - SP - CEP Informações: (14) Suporte: (14) Internet Cadastro: Suporte: Informações: Skype Cadastro: theclub_cadastro Skype Suporte: theclub_linha1 theclub_linha2 Copyright The Club Megazine 2008 Diretor Técnico Marcos César Silva Diagramação e Arte Vitor M. Rodrigues Revisão Marcos César Silva Colunistas Antonio Spitaleri Neto Fabiano Belmonte Luís Alexandre de Oliveira Marco Antonio Armando Marcos César Silva Victory Fernandes Vitor M. Rodrigues Impressão e acabamento: GRIL - Gráfica e Editora Rua São Paulo, nº 447 Cep: Taquarituba-SP Tel. (14) Reprodução A utilização, reprodução, apropriação, armazenamento em banco de dados, sob qualquer forma ou meio, de textos, fotos e outras criações intelectuais em cada publicação da revista The Club Megazine são terminantemente proibidos sem autorização escrita dos titulares dos direitos autorais. Um abraço a todos. Marcos César Silva - Editor Chefe Delphi é marca registrada da Borland International, as demais marcas citadas são registradas pelos seus respectivos proprietários. 04 maio 2009
5 Delphi Introdução a Porta Paralela Escrevendo bits via Delphi A exigência dos consumidores faz com que os processos automatizados estejam cada vez mais presentes no cotidiano, o que faz a automação de processos, algo de grande valor no mercado. Tal automatização pode ser baseada em diversos tipos de dispositivos controladores, tais como: Micro-Controladores, Controladores Lógicos Programáveis CLP, computadores PC dentre outros. A visão mais simplista deste processo envolve sempre algum tipo de dispositivo micro-processado que faz uso de portas de entradas e saídas para comunicação com o meio externo. Neste contexto, propostas simples como acender uma lâmpada a partir do clique do mouse, envolvem soluções de software onde o processo de desenvolvimento extrapola a confecção de telas e interface com bancos de dados, exigindo um maior conhecimento acerca de tecnologias de acesso a hardware, bases numéricas, conceitos de eletrônica digital, dentre outras. Com o objetivo de iniciar o leitor nestas tecnologias e prover conceitos básicos relacionados a automação de processos a partir de computadores PC, será abordado nesta série de artigos a mais simples dessas soluções: a porta paralela. No decorrer desta primeira parte, falaremos sobre uma breve introdução do dispositivo e à saída de dados. A porta paralela como base do ensino da automação Os conceitos técnicos apresentados neste artigo são base de uma metodologia mais ampla proposta, desenvolvida e aplicada nos cursos de Engenharia Mecatrônica e Mecânica da Universidade Salvador UNIFACS, premiada com a Menção Honrosa do Prêmio Top Educacional Professor Mário Palmério 2008, promovido pela Associação Brasileira de Mantenedoras de Ensino Superior ABMES, conforme descrito em Araujo (2008). Com o intuito de incentivar a aplicação prática de conceitos teóricos abordados em sala, tornando o curso lúdico e desafiador para o estudante, de forma a aumentar seu interesse e reduzir os índices de evasão, foi implantada a estrutura de um programa interdisciplinar de práticas semestrais aplicadas de forma gradual, orientada e continuada, devidamente adequadas às grades curriculares dos cursos citados. Este programa, codinome ARHTE, prevê que desde o primeiro semestre o aluno realize atividades de desenvolvimento de projetos automatizados, inicialmente integrados com o computador via porta paralela, interagindo de forma empreendedora com o mercado, aumentando a abrangência de seus conhecimentos e culminando ao final do curso com o desenvolvimento de aplicações profissionais e inovadoras. As possibilidades de projetos são vastas e os exemplos de sucesso já desenvolvidos são inúmeros, no entanto alguns merecem destaque pelo seu reconhecimento prévio. Dois projetos desenvolvidos por estudantes da UNIFACS ficaram entre os vencedores do Concurso Idéias Inovadoras de 2008, realizado pela Fundação de Amparo à Pesquisa do Estado da Bahia (FAPESB) e Secretaria de Ciência, Tecnologia e Inovação do Estado (SECTI). Na categoria Graduando, conquistou o primeiro lugar e premiação de R$3.000,00, o projeto Sensor de Presença Veicular (SPV), desenvolvido por alunos de Engenharia Mecatrônica e Engenharia Mecânica. Na categoria Inventor Livre, o terceiro lugar e premiação de R$5.000,00, foi para o projeto de uma balança para botijão de GLP, de um estudante de Engenharia Mecatrônica. Ainda houve a participação no concurso de um terceiro grupo formado por estudantes de Engenharia Mecatrônica e Engenharia Elétrica, o grupo ficou entre os finalistas da categoria Graduando, com o projeto Dotbus, um sistema de automação de transporte público envolvendo acessibilidade, que permite aos passageiros selecionar o veículo desejado em um painel eletrônico instalado no ponto de ônibus. O que há em comum nesses projetos? Todos começaram a partir de uma simples escrita e leitura de dados da porta paralela do PC como forma de interagir e comunicar com o mundo externo, permitindo que o software controle e automatize processos. Para maiores informações sobre o programa ARHTE bem como acesso completo aos vídeos e detalhamentos dos projetos, acesse unifacs.br ou ainda os portais acadêmicos de alguns professores da universidade: victory/solucoes.html, do professor Victory Fernandes e do professor maio
6 Rafael Araújo. Tipos de comunicação No âmbito das comunicações de dados através de canais de entrada e saída, existem dois modos de comunicação básicos: comunicação serial e a comunicação paralela. A comunicação serial, como o próprio nome indica, envia os dados em série. Os dados são enviados através de um único canal de comunicação, por onde as informações passam bit-a-bit. Na comunicação paralela há mais de um canal de comunicação e dados podem ser enviados simultaneamente nos diversos canais. Na Figura 1 é possível visualizar, através de um gráfico de conjuntos, a diferença entre tais tipos de comunicação. Figura 1: Comunicação Serial e Comunicação Paralela. Fonte: Veja na Figura 1. Conforme Tocci (2007), a informação é transmitida em formato binário e, geralmente, é representada por tensões na saída de um circuito transmissor que está conectado à entrada de um circuito receptor. Para transmitir o texto oi de um computador para uma impressora, conectada à porta paralela LPT1, serão enviados de uma só vez, pelos 8 canais de dados da porta paralela, os 8 bits referentes à representação da letra o na tabela ASCII ( ). Em seguida são enviados os 8 bits restantes referentes à representação da letra i na tabela ASCII ( ). Um total de 16 bits enviados em 2 momentos ou tempos de comunicação. Para a mesma aplicação desta vez utilizando o canal de dados serial, portas COM ou USB, faz-se necessário que os 16 bits sejam enviados um a um através do único canal de comunicação existente. A porta paralela Fisicamente falando, a porta paralela se apresenta diretamente conectada à placa mãe do computador como um conector de 25 pinos, DB25, mostrado na Figura 2. Devido ao fato de estar diretamente acoplada à placa mãe, surge um grande perigo do uso indevido da porta, para o qual o leitor deve estar sempre atento, de forma a evitar danos. jpg Figura 3: Porta paralela e seus endereços de memória. Fonte: (editada) Figura 2: Conector Macho DB25. Fonte: Todos os aspectos da porta paralela do computador pessoal são padronizados pela norma IEEE 1248, incluindo conectores, pinagem, níveis de tensão etc. A porta paralela possui 5 canais de entrada (pinos 10 a 13, 15) e 12 de saída de dados (pinos 1 a 9, 14, 16 e 17). Além desses canais de entrada e saída, existem mais 8 canais para aterramento (pinos 18 a 25). Assim totalizam-se 25 canais apresentados, fisicamente, por pinos (macho) e encaixes (fêmea). Os canais de entrada e saída são divididos em endereços de memória, identificados por números na base hexadecimal, e codinomes (portas), como pode ser visto na Figura 3. Veja a Figura 3 06 maio 2009
7 Nas portas de Dados e de Controle concentram-se os 12 canais de saída de dados. Já na porta de Status, temos os 5 canais de entrada. Neste artigo são abordados os canais de saída, utilizados para escrever dados ou enviar informações para o meio externo. Os canais de entrada serão abordados na próxima edição. As informações em um computador são interpretadas em níveis lógicos digitais ou, popularmente, os zeros e uns. Esses níveis lógicos são pulsos com magnitude de corrente e de diferença de potencial (ddp). No caso da porta paralela, são padronizados respeitando o padrão TTL (Transistor- Transistor-Logic) da eletrônica com 5 VDC (Volts Corrente Contínua) para representar bits com valor 1 (um), e 0 VDC para representar bits com valor 0 (zero). As correntes geradas por um sinal da porta paralela são suficientes apenas para acionar LED s, que são cargas que consomem correntes da ordem de miliampéres. Dessa forma, caso se queira controlar dispositivos mais robustos, é necessário o uso de circuitos auxiliares que serão abordados em seguida. Acesso à porta paralela e o uso inpout.dll Recentemente desenvolver um software para enviar bits para os dispositivos de entrada e saída do computador tornou-se um pouco mais complicado, devido ao bloqueio do acesso direto aos componentes de hardware dos computadores promovido pelos sistemas operacionais mais novos, a exemplo do Windows NT, XP e Vista. procedure outportb(endporta: Integer; Valor:BYTE); stdcall; external inpout32.dll name Out32 ; Os parâmetros recebidos pela função outportb são, respectivamente, o endereço da porta para o qual a informação deve ser enviada e a informação a ser enviada propriamente dita. Como se pode verificar, o valor EndPorta é um valor do tipo Integer. Uma variável desse tipo pode receber valores em diversas bases numéricas, assim é possível o envio do valor da porta em qualquer base numérica. Vejamos um exemplo. Suponhamos que desejamos acessar a porta de controle da porta paralela cujo endereço é 37A16. Assim, utilizando o Delphi, podemos atribuir tal valor de duas formas equivalentes, passando o número na sua representação Decimal ou Hexadecimal, conforme mostrado a seguir. EndPorta := 890; EndPorta := $37A; Assim como o parâmetro EndPorta, o parâmetro Valor também pode receber a informação em qualquer base numérica, tendo como padrão a base decimal. O código apresentado a seguir executa a chamada à função de envio de dados, transmitindo para os pinos de Dados da porta paralela o número 1010 na base decimal, cuja representação equivalente na base binária representada com 8 bits é Outoportb($378, 10); Para identificar quais pinos da porta paralela serão ativados e desativados após a execução deste comando, é preciso analisar a representação binária dos valores enviados. Cada algarismo do número binário representa um pino da porta paralela, como pode ser visto na Figura 4. Veja a Figura 4. Assim, para a porta de Dados, o algarismo mais significativo representa o pino 9 e o menos significativo o pino 2. Um dos dispositivos de hardware bloqueados pelos sistemas operacionais, por motivos de segurança, foi a porta paralela. Como forma de abstrair a complexidade de acesso à porta paralela em tais sistemas operacionais e simplificar o acesso a tais dispositivos é possível utilizar uma Dynamic Link Library (dll) disponível gratuitamente na internet: a inpout32.dll. Na linguagem Delphi, em poucas linhas é possível disponibilizar as funções escritas na dll para a sua aplicação. A seguir é apresentado o código de declaração da função de escrita na porta paralela contida na dll: Figura 4: relação entre casas binárias e pinos da porta paralela. Fonte: (editada) maio
8 Neste exemplo, após a transmissão do valor 1010 para a porta de dados, os pinos 5 e 3 da porta paralela ficariam ativados com nível lógico alto de 5VDC e os demais desativados, com nível lógico baixo 0 VDC. Escrevendo na porta paralela Para exemplificar o processo de escrita na porta paralela de forma abrangente e simples, este artigo propõe o seguinte módulo de escrita na porta paralela, apresentado na Figura 5. Figura 5: Laiute do programa de envio de bits pela porta paralela. Fonte: Elaboração própria. No RadioGroup é feita a escolha do endereço da porta para a qual o usuário deseja mandar a informação. A depender de qual opção esteja marcada, um valor será atribuído ao parâmetro EndPorta da função OutPortB. No EditBox, o usuário digita o valor numérico inteiro que deseja enviar para a porta paralela. Como já foi visto, a função outportb pode receber o valor a ser enviado em qualquer base numérica. Então, com o objetivo de tornar a interface com o usuário mais amigável, o valor será digitado na base decimal. Esse valor digitado será atribuído ao parâmetro Valor da função OutPortB. Ao clicar no botão Enviar!, a função outportb será chamada com os parâmetros atribuidos pelo usuário. A seguir temos a rotina atribuída ao evento de OnClick do botão Enviar: procedure TForm1.Button1Click(Sender: TObject); var porta, valor: integer; try if radiogroup1.itemindex = 0 then Label2.Caption := InttoByteSTR(strtoint(edit1.Text), 8); porta := $378; valor := strtoint(edit1.text); end else if Radiogroup1.ItemIndex = 1 then Label3.Caption := InttoByteSTR(strtoint(edit1.Text), 8); porta := $37A; valor := strtoint(edit1.text); end else showmessage( Escolha para qual porta deseja mandar um valor antes de ligar o programa! ); exit; outportb(porta, valor); except on E: EConvertError do Showmessage( Esse texto não corresponde a um valor inteiro válido. Digite novo valor! ); Código 1 Veja o Código 1. Para que possamos então visualizar quais bits estão ligados ou desligados, precisamos implementar uma função de conversão decimal-binário. Uma maneira rápida e prática de realizar tal conversão é fazer sucessivas divisões por dois (base do sistema binário) do número decimal a que se deseja representar em binário. Para maiores detalhes desse método leia a apostila sobre conversões de bases numéricas do sistema EAD do ICEA (Instituto de Controle do Espaço Aéreo) na seguinte url: Assim fica fácil construir uma rotina que realize essa conversão. Seria ela: 08 maio 2009
9 Veja o Código 2. Aplicações de controle via Porta Paralela Uma das aplicações mais simples de controle de dispositivos via porta paralela, é acender e apagar um LED (Light-emitting diode). Como foi discutido anteriormente, as correntes e as tensões disponibilizadas pela porta paralela são de baixa magnitude. Como o led é um dispositivo que não demanda elevadas correntes, este pode ser controlado diretamente pela porta paralela, sem o auxilio de amplificadores de sinal. Utiliza-se apenas um resistor da ordem de 470ohm para garantir que a corrente trabalhe na faixa de tolerância do led, algo em torno de 10 a 20 ma. Assim, com o aplicativo proposto anteriormente, é possível controlar o acionamento de um led, através de um circuito bastante simples mostrado na Figura 6, a seguir. function InttoByteSTR(Value, Tam: integer): String; var x: integer; temp: string; temp := ; setlength(result, 8); while (value >= 1 ) do temp := temp + inttostr(value mod 2); value := value div 2; if length(temp) > Tam then ON_OFF; {rotina que trata de proprieties dos panels, radiogroups e editboxes} showmessage(numero tem mais que a quantidade de bits estipulada ); end else for x:= 1 to 8 do if (length(temp) < x) then result[9 - x] := 0 else result[9 - x] := temp[x]; Código 2 Figura 6: Circuito de acionamento de LED via porta paralela. Fonte: Elaboração própria. Um exemplo de testes de funcionamento do circuito proposto na Figura 6 pode ser visto no vídeo postado no YouTube de cursos ministrados na UNIFACS, disponível no link: Existem dispositivos que necessitam de uma corrente e/ou tensão mais elevadas. Para que seus estados de ligado e desligado sejam comutados, bem como pode ser necessário comutar tensões alternadas para o caso de acionamento de lâmpadas e diversos outros dispositivos, para esses casos, utilizam-se transistores, drivers de potência e relés. Para exemplificar o caso descrito anteriormente, mostraremos um circuito de comutação, através de um relé controlado pela porta paralela, de uma tensão alternada em uma lâmpada. O relé é um dispositivo composto por uma bobina e uma chave de três contatos, como pode ser visto na Figura 7. Veja a Figura 7. Ao induzir uma corrente na bobina, um campo magnético é gerado, forçando o acionamento da chave. Devido às questões da estrutura física do relé, a corrente que possibilita o acionamento da chave é de magnitude elevada, não sendo compatível com a corrente disponibilizada pela porta paralela. Então é possível utilizar um circuito integrado (CI) que funcionará como um gatilho, amplificando o sinal original, este CI é o ULN2003 ou ULN2803. Dessa forma o circuito descrito apresenta-se como na Figura 8. Veja a Figura 8. Ao enviar um bit de valor 1 (um) para o pino 2 da porta paralela, o mesmo será ativado, fazendo com que o ULN libere uma tensão de 12VDC para acionamento do relé, que por sua vez fechará o circuito da lâmpada com a rede elétrica de 110 ou 220VAC, permitindo desta forma que você ligue e desligue uma lâmpada a partir do clique do mouse. Agora você já sabe como controlar uma lâmpada através do seu software! O acionamento de sistema digitais baseados em transistores e relés é o princípio básico de qualquer processo de automação! maio
10 Conclusão Neste artigo apresentamos os conceitos básicos relacionados à automação de processos a partir de computadores PC, utilizando acionamento de bits da porta paralela para controle de dispositivos externos através de aplicativos desenvolvidos em Delphi. A aplicação desta metodologia no ensino da automação tem demonstrado excelentes resultados. Na experiência da UNIFACS, há a indicação de que os alunos ingressam em semestres posteriores amadurecidos, com interesses profissionais, resultado das pesquisas e aplicação de conteúdos de eletrônica, programação, mecânica, materiais e automação realizados previamente. Os professores relatam que as aulas formais tornaram-se mais interessantes e dinâmicas, pois a responsabilidade de trazer conteúdos do mercado de trabalho deixa de ser atribuição exclusiva do professor da disciplina, que passa a compartilhar essa responsabilidade com o aluno. Os resultados obtidos indicam uma modificação nas abordagens didáticas e comportamentais de discentes e docentes nos cursos de engenharia. Associado aos conteúdos técnicos, a proposta tem se mostrado eficaz na formação do engenheiro para o século XXI, com o processo de ensino-aprendizagem prazeroso, efetivo e de qualidade. No próximo artigo daremos continuidade no estudo dos recursos da porta paralela, abordando a leitura de informações a partir de sensores acoplados à mesma, tornando possível que seu software adquira percepção do ambiente. Referências TOCCI, Ronal J.. Sistemas Digitais Principios e Aplicações Editora Pearson. 10a Edição. São Paulo - SP. ARAUJO, Rafael; Fleming, Paulo Victor; Amorin, Targino; Fernandes, Victory; Marques Ederval. Ensino Interdisciplinar nas Engenharia Mecânica e Mecatrônica. Prêmio Top Educacional Professor Mário Palmério Salvador BA. MESSIAS, Antonio Rogério. Rogercom: O maior conteúdo brasileiro sobre porta paralela. Disponível em: <http://www.rogercom.com/>. ARAÚJO, Rafael Gonçalves Bezerra de. Rafael Araújo: ENGENHARIA. Disponível em: <http://www. harpia.eng.br/>. FERNANDES, Victory Santos. Victory Fernandes: Engenharia e Software. Disponível em: <http:// Figura 7: Estrutura do relé. Fonte: Figura 8: Circuito para acionar lâmpada. Fonte: Elaboração própria. Sobre os autores Juliana Andrade Carvalho é graduanda em Engenharia Mecatrônica pela UNIFACS e estagiária da TKS. Pode ser contatada em Rafael Araujo é Coordenador do Curso de Engenharia Mecatrônica da UNIFACS, Engenheiro com Mestrado em Regulação da Indústria de Energia. Pode ser contatado em ou através do site Victory Fernandes é Professor do Departamento de Engenharia da UNIFACS, Engenheiro Mestrando em Redes de Computadores, e desenvolvedor sócio da TKS Software - Soluções de Automação e Softwares Dedicados. Pode ser contatado em ou através dos sites br 10 maio 2009
12 Utilizando as API s do windows para melhorar a aplicação Todo aplicativo que é executado sobre a plataforma Windows, tenha sido ele desenvolvido em Delphi ou qualquer outra linguagem, precisa seguir um conjunto de regras para funcionar corretamente. Esse conjunto de regras é conhecido por API(Application Program Interface), e consiste numa série de classes que controlam o comportamento dos aplicativos Win32. O Delphi utiliza as API s a todo instante, porém de forma transparente ao programador, ou seja, quem programa em Delphi não tem a necessidade de realizar nenhuma chamada direta à API quando está programando. O Delphi se encarrega de efetuar as chamadas necessárias à API para realizar as mais diversas funções como minimizar e maximizar uma janela, alterar a cor ou imagem de fundo de um formulário, etc. Quem programa em Delphi, mesmo os experientes, na maioria das vezes digamos que vai pelo rumo em se tratando de APIs, ou seja, utiliza as API s porém não diretamente, apenas através do encapsulamento oferecido pelas classes da VCL do Delphi. No Delphi, grande parte das funções que trabalham com as API s estão localizadas na unit Windows, veja esse pequeno trecho dessa unit que é bem extensa: function DeleteFiber; external kernel32 name DeleteFiber ; function DeleteFile; external kernel32 name DeleteFileA ; function DeleteFileA; external kernel32 name DeleteFileA ; function DeleteFileW; external kernel32 name DeleteFileW ; function DeviceIoControl; external kernel32 name DeviceIoControl ; function DisableThreadLibraryCalls; external kernel32 name DisableThreadLibraryCalls ; function DisconnectNamedPipe; external kernel32 name DisconnectNamedPipe ; function DosDateTimeToFileTime; external kernel32 name DosDateTimeToFileTime ; function DuplicateHandle; external kernel32 name DuplicateHandle ; function EncryptFile; external kernel32 name EncryptFile ; function EncryptFileA; external kernel32 name EncryptFileA ; function EncryptFileW; external kernel32 name EncryptFileW ; Código 1 12 maio 2009
13 Repare que as funções utilizam a diretiva external que indica que elas não estão Em alguma unit do Delphi e sim em uma DLL, no caso a dll kernel32 que se encontra no diretório C:\Windows\ System32. Não é impescindível ao programador Delphi saber trabalhar com as API s, porém o bom uso delas pode melhorar significativamente a aplicação. Nesse artigo estarei mostrando alguns exemplos de como a API do Windows pode ser usada para incrementar seus aplicativos. Mãos à obra! Radio Group 1 Radio Group 2 Button 1 Tabela 1 Objeto Propriedades Caption: Resolução da tela Itens: 640 x 480, 800 x 600, 1024 x 768 Caption: Cores Itens: 16 cores, 256 cores, cores Caption: Aplicar Alterações. Alterando a resolução da tela Geralmente, desenvolvemos nossos aplicativos para serem executados em uma determinada resolução de vídeo (por exemplo, 800x600) e quando o usuário executa o aplicativo em uma resolução diferente as janelas ficam mal posicionadas, o que convenhamos não é interessante em termos visuais e acaba por desvalorizar o software. Nesse caso, podemos utilizar a API do Windows para oferecer ao usuário final a opção de mudar a resolução das telas do aplicativo de acordo com a resolução de vídeo do monitor que ele esteja utilizando. Dessa forma o problema com o mal posicionamento de telas é resolvido. O Delphi possui a classe TScreen que poderia ser utilizada nesse caso, essa classe contém métodos que podem ser utilizados para, entre outras coisas alterar a resolução da tela do computador. Nesse exemplo porém estaremos utilizando duas funções da API: EnumDisplaySettings, que é responsável por retornar os valores de resolução de vídeo correntes e ChangeDisplaySettings que se encarrega de mudar a resolução de vídeo.além dessas funções, estaremos utilizando a estrutura DevMode, que armazena dados sobre a resolução de vídeo. Mais informações sobre essas funções podem ser obtidas através do help do Delphi, na seção Windows Setup API Programmers Reference. Vamos ao exemplo. Crie uma nova aplicação em Delphi e inclua os seguintes componentes: Veja a tabela 1. A tela de seu aplicativo deverá ficar com a seguinte aparência: Veja a imagem 1. No evento Onclick do Button1 faça: Imagem 1 procedure TForm1.Button1Click(Sender: TObject); var sdispmode:devmode;//declaração da estrutura devmode EnumDisplaySettings(nil,0,sdispmode);//armazenamos os dados de resolução // tela na variável sdispmode case RadioGroup1.ItemIndex of // aqui alteramos os valores de largura // e altura da tela de acordo com a // escolha do usuário 0: sdispmode.dmpelswidth:=640; sdispmode.dmpelsheight:=480; 1: sdispmode.dmpelswidth:=800; sdispmode.dmpelsheight:=600; 2: sdispmode.dmpelswidth:=1024; sdispmode.dmpelsheight:=768; Código 2 maio
14 case RadioGroup2.ItemIndex of // aqui ajustamos o número de bits de cores por //pixel através da propriedade bitsperpel da // estrutura devmode representada pela variável sdispmode 0: sdispmode.dmbitsperpel:=4; // 16 cores 1: sdispmode.dmbitsperpel:=8;// 256 cores 2: sdispmode.dmbitsperpel:=16; // cores // agora especificamos quais campos da estrutura devmode foram alterados sdispmode.dmfields:=dm_bitsperpel+dm_pelswidth+dm_ PELSHEIGHT; // a seguir aplicamos as alterações e verificamos o valor de retorno // que é representado pela constante DISP_CHANGE_ SUCCESSFUL // se o retorno da função ChangeDisplaySettings for igual a essa // constante é porque as alterações foram executadas com sucesso if (ChangeDisplaySettings(sdispmode,0)= DISP_CHANGE_ SUCCESSFUL)then ShowMessage( Alterada a resolução ) else ShowMessage( Resolução não Suportada ); Código 2 Criando Formulários diretamente via Código Em alguns casos, na programação Delphi, acabamos por ter que criar formulários para a execução de pequenas tarefas e na soma esses vários formulários acabam por tornar a aplicação mais pesada. aplicação no Delphi e localize a unit do programa, ou seja, o arquivo dpr onde a aplicação é inicializada. Nessa unit coloque o seguinte código: Nesse exemplo, estarei mostrando que é possível criar janelas em Delphi através de chamadas diretas à API, ao estilo da programação em C++. É claro que devido a complexidade do código não seria viável a criação de vários forms de uma grande aplicação devido a baixa produtividade. Esse exemplo fica limitado a criação de forms para tarefas pequenas da aplicação como, por exemplo, o login de usuários. Vamos ao código do exemplo. Inicie uma nova 14 maio 2009
15 program testwindow; uses Windows,Messages; var WinClass: TWndClassA; Inst, Handle, Button1, Label1, Edit1: Integer; Msg: TMsg; hfont: Integer; { Verifica se a senha digitada é theclub e mostra uma mensagem } procedure CheckPassword; var Textlength: Integer; Text: PChar; TextLength := GetWindowTextLength(Edit1); if TextLength = 7 then GetMem(Text, TextLength + 1); GetWindowText(Edit1, Text, TextLength + 1); if Text = theclub then MessageBoxA(Handle, A senha está correta., Verifica a senha, MB_OK); FreeMem(Text, TextLength + 1); Exit; MessageBoxA(Handle, Senha incorreta., Verifica senha, MB_OK); { Função WindowProc alternativa } function WindowProc(hWnd, umsg, wparam, lparam: Integer): Integer; stdcall; Result := DefWindowProc(hWnd, umsg, wparam, lparam); { Ve se tem mensagens } if (lparam = Button1) and (umsg = WM_COMMAND) then CheckPassword; if umsg = WM_DESTROY then Halt; { ** Registra um classe de janela alternativa ** } Inst := hinstance; with WinClass do style := CS_CLASSDC or CS_PARENTDC; lpfnwndproc hinstance := Inst; hbrbackground := color_btnface + 1; lpszclassname := AG_TESTWINDOW ; hcursor := LoadCursor(0, IDC_ARROW); { with } RegisterClass(WinClass); { ** Cria a janela principal ** } Código 3 maio
16 Handle := CreateWindowEx(WS_EX_WINDOWEDGE, AG_ TESTWINDOW, Amigreen TestWindow 1.00, WS_VISIBLE or WS_SIZEBOX or WS_CAPTION or WS_SYSMENU, 363, 278, 305, 65, 0, 0, Inst, nil); { ** Cria um botao ** } Button1 := CreateWindow( Button, OK, WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or BS_TEXT, 216, 8, 75, 25, handle, 0, Inst, nil); { ** Cria um label estatico ** } Label1 := Createwindow( Static,, WS_VISIBLE or WS_ CHILD or SS_LEFT, 8, 12, 76, 13, Handle, 0, Inst, nil); { ** Cria um Edit ** } Edit1 := CreateWindowEx(WS_EX_CLIENTEDGE, Edit,, WS_CHILD or WS_VISIBLE or WS_BORDER or ES_PASSWORD, 88, 8, 121, 21, Handle, 0, Inst, nil); { ** Cria a fonte padrao ** } hfont := CreateFont(-11, 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_ QUALITY, DEFAULT_PITCH or FF_DONTCARE, MS Sans Serif ); { Muda a fonte } if hfont <> 0 then SendMessage(Button1, WM_SETFONT, hfont, 0); SendMessage(Label1, WM_SETFONT, hfont, 0); SendMessage(Edit1, WM_SETFONT, hfont, 0); { Muda o texto do label } SetWindowText(Label1, Informe a senha: ); { Poe o focu no Edit } SetFocus(Edit1); Através de chamadas a API é possível, até de forma um tanto simples, fazer essa verificação utilizando para tanto apenas uma função da API, getversionex, é essa função que utilizaremos no exemplo a seguir. O primeiro passo é declarar uma variável do tipo tosversioninfo, é essa variável que será passada como parâmetro para a função getversionex para que essa função retorne corretamente a versão do Windows que está rodando na máquina. Com a variável declarada, precisamos dimensioná-la, isso é feito através do seguinte comando: Var version:tosversioninfo; version.dwosversioninfosize :=sizeof(version); Código 4 Com a variável devidamente dimensionada, podemos chamar a função getversionex e passar essa variável como parâmetro da mesma: GetVersionEx(version); Código 5 Agora podemos acessar os valores da variável que nos permitirão conferir a versão do Windows através da comparação desses valores com a seguinte tabela: Veja a tabela 2 UpdateWindow(Handle); { ** Loop de Mensagens ** } while(getmessage(msg, Handle, 0, 0)) do TranslateMessage(msg); DispatchMessage(msg); { with } end. Código 3 Essa tabela está disponível no site da Microsoft no link: Vamos agora criar a função.segue o código da mesma: Como pode ser verificado, o código é extenso e se torna um tanto complexo devido às chamadas diretas à API que são realizadas. Apesar disso pode ser muito útil para reduzir o tamanho em memória da aplicação. Verificando qual versão do Windows está sendo executada. Em algumas situações, pode ser útil que o aplicativo faça uma verificação de qual versão do Windows está sendo executada na máquina no qual ele está rodando. Principalmente nos casos em que o aplicativo executa funções cuja chamada pode ser diferente dependendo da versão do sistema operacional. 16 maio 2009
17 95 98 ME NT 3,51 NT XP PlatformID Major Version Minor Version Tabela 2 function TForm1.getversion: string; version.dwosversioninfosize:=sizeof(version); GetVersionEx(version); Result:= ; with Version do case dwplatformid of 1: case dwminorversion of 0: Result:= Windows 95 ; 10: Result:= Windows 98 ; 90: Result:= Windows Me ; 2: case dwmajorversion of 3: Result:= Windows NT 3.51 ; 4: Result:= Windows NT 4.0 ; 5: case dwminorversion of 0: Result:= Windows 2000 ; 1: Result:= Windows XP ; if (Result= ) then Result:= Sistema operacional desconhecido. ; No exemplo usaremos a função no evento onclick de um Button, como segue: procedure TForm1.Button1Click(Sender: TObject); var winversion:string; winversion:=getversion; ShowMessage( Você está usando +winversion); var falador:olevariant; falador:=createoleobject( SAPI.spvoice ); falador.speak(edit1.text,0); Código 6 Código 7 Verifique que apesar de estarmos utilizando API é relativamente fácil verificar qual versão do Windows estamos rodando. E pode ser bastante útil essa verificação. Fazendo o Delphi falar SAPI(Speech Application Program Interface) é uma API que permite aos desenvolvedores trabalhar de forma mais tranqüila com reconhecimento de voz e simulação de efeitos sonoros.no exemplo a seguir, utilizaremos essa API para construir um aplicativo simples em Delphi que irá ler um texto digitado pelo usuário e transformá-lo em som. Inicie uma nova aplicação no Delphi e adicione uma Edit e um Button. No evento on click do Button criado faça: Veja o Código 7. No código, criamos um objeto no padrão OLE(object linking and embeding) que é um padrão para integração de aplicações. Esse objeto se encarrega de fazer a leitura do que o usuário digita e transforma em áudio que será exibido via placa de som. Conclusão Embora não seja necessário ser um conhecedor de API s, observamos que ter certo conhecimento em API s pode facilitar a vida do programador, permitindo incluir recursos no sistema, onde apenas usando Delphi seria quase impossível. Sobre o autor Antonio Spitaleri Neto Consultor Técnico The club maio
18 DIRETIVAS DE COMPILAÇÃO Parte I Neste artigo irei abordar um assunto que é um mistério para grande maioria dos programadores e vem de encontro as necessidades de alguns sócios. Quando você compila o seu projeto, o Delphi esta realizando um processo de tradução do código que você escreveu para uma linguagem que seu computador possa entender. As diretivas são usadas para controlar as características do compilador Delphi. As diretivas podem ser inseridas diretamente no código fonte utilizando a sintaxe de comentário( não podemos confundir diretivas com comentário), ou também podem ser colacadas no arquivo de configuração DCC32.CFG. do seu programa e também gerar versões de demonstração. Quando você usa as diretivas de compilação o Delphi verifica se ela esta definida e obedece as regras que você impôs pelo uso da diretiva, visto que as diretivas são avaliadas antes da compilação do seu código. Você pode então, através das diretivas de compilação controlar, o código que será compilado. Lista das Diretivas $A Define o tipo de alinhamento de campos do tipo Record. Também podem ser fornecidas na linha de comando do compilador DCC32.exe. A caixa de diálogo Project Options Compiler contém muitas opções equivalentes as diretivas, contudo, as diretivas inseridas diretamente no código fonte sempre se sobrepõem às diretivas na linha de comando e às opções do projeto (Project Options Compiler). A tecla ctrl + OO pressionadas no editor de código inserem as definições correntes das diretivas ativas no início do arquivo fonte.(figura 2) significado Os campos em tipos Record declarados sem o modifi- serão alinhados Não serão alinhados Opção {$A+} cador packed {$A-} Exemplo Figura 1. Todas as diretivas de compilação são iniciadas pelo caractere $. As diretivas podem ser colocadas em qualquer parte do programa. Você pode usar as diretivas de compilação para selecionar trechos particulares de código que serão executados enquanto outros trechos serão ignorados pelo compilador. Pode também alterar valores definidos de alguns elementos type // default : $A+ // sem pacote TSemPacoteON = Record name1 : string[4]; floater : single; name2 : char; int : Integer; // packed record TPacote = Packed Record name1 : string[4]; floater : single; name2 : char; int : Integer; // Set alignment off {$A-} // Sem pacote com {$A-} TSemPacoteOff= Record 18 maio 2009
19 name1 : string[4]; floater : single; name2 : char; int : Integer; var Form1: TForm1; alignedrec : TSemPacoteOn; packedrec : TPacote; unpackedrec : TSemPacoteOff; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); ShowMessage( tamanho registro alinhado sem pacote com {$A+} = +IntToStr(Size Of(alignedRec))); ShowMessage( tamanho com pacote(packed record)= +IntToStr(SizeOf(packedRec))); ShowMessage( tamanho sem pacote com {$A-} = +IntToStr(SizeOf(unPackedRec)) ); end. $APPTYPE Controla se o compilador deve gerar uma aplicação GUI ou uma ou uma aplicação console console que pode ser executada a partir da linha de comando. Corresponde ao comando Project Options Linker exe and DLL options Generate console application do menu principal do Delphi. {$APPTYPE GUI} OU {APPTYPE CONSOLE} Exemplo program Project1; {$AppType CONSOLE} uses SysUtils; var name : string; WriteLn( Entre com seu nome ); ReadLn(name); WriteLn( Seu nome e +name); WriteLn( ); WriteLn( Pressione enter para sair ); ReadLn(name); end. $assertions o mesmo que {$C+ -} $B Define o modelo de geração de código para os operadores booleanos and e or. O mesmo que {$booleval on off} {$B+} Todas as expressões booleanas são avaliadas até o final, mesmo que o resultado da expressão inteira seja avaliado. {$B-} A avaliação é finalizada tão logo que o resultado da expressão inteira torne-se evidente, mesmo antes que a expressão inteira seja avaliada. Exemplo var FullString, EmptyString : string; FullString := alexandre ; EmptyString := ; {$B-} // verifica o 4º caractere if (Length(FullString) >= 4) and (FullString[4] = x ) then ShowMessage( O 4th caractere é x ) else ShowMessage( O 4th caractere não é x ); if (Length(EmptyString) >= 4) and (EmptyString[4] = x ) then ShowMessage( O 4th caractere é x ) else ShowMessage( O 4th caractere não é x ); {$B+} // verifica o 4º caractere if (Length(FullString) >= 4) and (FullString[4] = x ) then ShowMessage( O 4th caractere é x ) else ShowMessage( O 4th caractere não é x ); maio
20 try if (Length(EmptyString) >= 4) and (EmptyString[4] = x ) then ShowMessage( O 4 th caractere é x ) else ShowMessage( O 4th caractere não é x ); except on E : EAccessViolation do ShowMessage(E.Message); $BOOLEVAL O mesmo que {$B+ -} {$BOOLEVAL ON} OU {$BOOLEVAL OFF} $C Controla a geração de código objeto para asserções( procedure Assert) no programa fonte. O mesmo que {$ASSERTIONS ON OFF} Assertions são validações sobre os fundamentos da lógica de um programa. A verificação de um assertion é a validação de que uma condição necessária para o algoritimo funcionar, algo que você supõe ser verdadeiro, é realmente válido durante a execução do programa. Em Delphi, a sintaxe de um Assertion é a seguinte: Assert(Condition: Boolean; [Message: string]); Isso quer dizer que Assert é um procedimento que aceita uma condição, e opcionalmente uma mensagem de erro. É usado como uma prática defensiva de codificação para garantir o estado do seu programa, pegando falhas antes que aconteçam. Se a condição passada para o assert for avaliada como falso, será gerada uma exceção com a mensagem informada (ou assertion failure, se não for passada nenhuma), e o mais interessante, por uma mágica de compilador a mensagem também inclui o nome do arquivo e a linha onde a falha ocorreu. Project/Options, Compiler, Debug Information, Assertions. Exemplo Simularemos um caso em que um cliente possui um saldo inicial de 200 Reais e ele poderá fazer depósitos e retiradas. A pré-condição para efetivarmos o depósito é de que o valor depositado seja maior que 0, e a pós-condição é que o saldo após o depósito seja maior que o saldo anterior à operação, simples mas bastante lógico não? Para a retirada teremos como pré-condição que o valor a ser retirado não seja maior que o saldo, e como pós-condição, que o saldo final seja maior que 0. Comece declarando duas variáveis globais do tipo Currency, uma chamada valor e outra chamada saldo inicializada com o valor de 200: var valor: Currency; saldo: Currency = 200; No evento OnClick do botão btretirar digite o código a seguir: procedure TForm1.btRetirarClick(Sender: TObject); valor:= StrToCurr(edtValor.Text); Assert(saldo > valor, Tentativa de retirada inválida ); saldo:= saldo - valor; Assert(saldo >= 0, O saldo estava negativo ); ShowMessage( Saldo atual: + CurrToStr(saldo)); Começamos capturando o valor digitado no edtvalor na variável valor, na linha a seguir, inferimos a nossa pré-condição, saldo deve ser maior que valor para que a retirada possa ser feita, caso essa condição não seja atendida (o chamador não cumpriu sua parte do contrato), um erro de asserção será lançado. A execução do código subseqüente é então abortada e a retirada nunca é concretizada. Isso foi um erro de asserção. Caso conseguíssemos chegar à penúltima linha deste código (Assert(saldo >= 0, O saldo estava negativo );) ai sim teria ocorrido uma verdadeira exceção, já que pelas regras impostas o saldo nunca conseguiria ser menor que 0, portanto, em algum momento o software teria falhado em impor estas regras. Assertions não são feitas para validação de entrada de dados ou de resultados de funções, mas sim de pressupostos que deveriam sempre ser verdadeiros, e se não forem, indicam existe uma bug em alguma parte do seu programa. Por esse motivo, é prática comum desabilitar a validação de assertions no executável final produzido para distribuição, o que pode ser feito através de Vamos agora programar o click do botão btdepositar: 20 maio 2009