segunda-feira, 28 de dezembro de 2009

Conversor de medidas Wii Fit

Se você possui um Wii e um Wii Fit em casa e precisou calibrar o sistema com as suas medidas você já se deparou com as unidades de medida americanas, que são diferentes.

Se já usou qualquer produto americano ou precisou viajar para os EUA reparou que os americanos usam libras para peso, que equivalem a 453 gramas, e usam pés e polegadas para medida de distância (ou comprimento, altura, etc), sendo que cada polegada tem 2.54 centímetros e que 12 polegadas são um pé.

Fiz um pequeno script em javascript para fazer essas conversões e espero que seja útil tanto para quem for jogar wii quanto para quem quer aprender javascript, como colocar um script n blog etc.


Não sei porque cargas d'água o código js só funcionou em TODOS os browsers, exceto no mozilla Firefox. Testei no chrome, Opera, Safari e IE(ca)8. O mais estranho é que funcionou no Firefox FORA DO BLOGSPOT, NUMA PÁGINA EM BRANCO, mas dentro do blogspot não funcionou, e olha que eu uso scripts malucos no blogspot.... enfim, o fonte do html/javascript segue abaixo, então você pode copiar, colar e fazer sua própria pagininha. Se quiser abrir no blog mesmo use o chrome, mas NUNCA use um IE, Jamais! ;)


Have Fun ;)




Metros para Pés e polegadas (coloque ponto para separar os centímetros)

Converter


Quilos para Libras (coloque ponto para separar as gramas)

Converter



O código - fonte segue abaixo

<script type='text/javascript'> function MetrosToPolegadas(metros) { cm = metros * 100; polegadastotais = cm / 2.54; pes = polegadastotais / 12; polegadas = polegadastotais % 12; result = metros + " Metros são: <br>" + Math.round(polegadastotais) + " Polegadas ou <br>" + Math.round(pes) + " pés e " + Math.round(polegadas) + " Polegadas "; document.getElementById("resultado1").innerHTML = result; } function QuilogramasToLibras(quilos) { libras = (quilos * 1000)/453; result = quilos + " quilos são: <br>" + Math.round(libras) + " Libras"; document.getElementById('resultado2').innerHTML = result; } </script> <p> <span><strong>Metros para Pés e polegadas (coloque ponto para separar os centímetros)</strong></span><br> <input id='txtMetros' value='0' /> <a href="#" onclick="MetrosToPolegadas(txtMetros.value);">Converter</a> <br/> <span id='resultado1'></span> </p> <p> <span><strong>Quilos para Libras (coloque ponto para separar as gramas)</strong></span><br> <input id='txtQuilos' value='0' /> <a href="#" onclick="QuilogramasToLibras(txtQuilos.value);">Converter</a> <br/> <span id='resultado2'></span> </p>

sexta-feira, 18 de dezembro de 2009

Artigo sobre RTTI na Clube Delphi 113

Saiu mais um artigo meu na Revista Clube Delphi.

Trata-se de um artigo sobre a RTTI. Para quem não sabe, RTTI é o mecanismo de reflexão e Introspecção do Delphi.

Esse artigo vai mais além do que eu já publiquei sobre object inspector, e além de te ajudar a criar um object inspector ele servirá de semente para a criação de um framework de persistência e até mesmo de um framework de MVC.

Reflexão é um dos meus assuntos favoritos em todas as linguagens, sabe porquê? Preguiça de ficar fazendo alterações bestas nos programas. Você tem o poder para deixar que o usuário faça certas alterações, como cores, layout, ordem de chamada de métodos e eventos e até cálculos simples.

Pretendo escrever mais artigos, públicos e privados, sobre RTTI, Reflexão e Interfaces, também em C# e Prism.

Quem tiver alguma dúvida sobre algum desses assuntos pode me perguntar no meu formspring

Até +

Google Translator

Novo componente do google traz a api do google translator para o seu site. Vou incorporar esse componente no blog e recomendar os meus posts pros estrangeiros ;)

Modo de usar:






ronaldo, brilha muito no corinthians







sexta-feira, 11 de dezembro de 2009

Artigo sobre interfaces na Clube Delphi 112

Puxa vida! faz tempo que eu não posto nada nos meus blogs! Novembro inteiro sem postar, que feio!



É tanto projeto, tanto compromisso que o tempo fica bem curto mesmo. Além disso ferramentas como facebook e twitter são maravilhosas para integração de pessoas e informações,
para se fazer jabá e para se manter atualizado. Mas são um terror para a produtividade. Nos tomam muito tempo e causam muita distração.
Imagina quem tem déficit de atenção então, é ainda pior.



Também são tantas as novas tecnologias que surgem a cada dia que é impossível acompanhar o mercado ou o progresso da informática. É impossível até se manter informado sobre
as mudanças. Quando eu estava planejando estudar Java caiu o C# de pára-quedas na minha vida. Quando planejei estudar Ruby atacaram o PHP no meu colo, quando estava ficando
razoável em POO apareceu essa tal de programação funcional, a nova febre do momento. Fora as novas tecnologias do google, como o app engine, que são muito atraentes.



Com certeza tive que adiar meus estudos e projetos, e estão todos parados, ou andando beeem devagar de mãos dadas, numa série de threads que compartilham 1/100 do tempo para cada um.
Bem dizia o meu pai que quem quer fazer tudo acaba não fazendo nada.

É tanta tecnologia que qualquer um ficaria louco, eu já fiquei. Mas sabe de uma coisa? Eu AMO isso.



Mas eu ainda consegui tirar um tempinho para meus projetos pessoais e para escrever artigos e talz. Principalmente sobre Delphi, que é a minha linguagem materna.



Quem lembra dos meus posts sobre interfaces?

Pois é, fazendo um jabá aqui, esse artigo, que eu também postei no meu space na devmedia, é complementar
a um artigo meu que foi publicado na Revista Clube Delphi 112.



É o meu primeiro (de muitos, espero) artigo publicado numa revista e eu estou muito feliz \o/ \o/ por isso. Mas eu não poderia deixar de agradecer várias pessoas que me apoiaram e/ou tiveram
a paciência de me ensinar.

Em especial gostaria de agradecer ao meu amigo Marcos Barreto, o cara do Infra que, há muito tempo atrás e talvez ele nem se lembre, desperdiçou pelo menos umas três horas da vida dele para me ensinar sobre interfaces,
a base do conhecimento que me ajudou e motivou a compartilhar com vocês esses artigos.



Por falar nisso, esse fim de semana estarei testando algumas funcionalidades do google wave e sua integração com blogs. Talvez eu inicie uma conversa pública sobre Delphi no meu blog. É só aguardar.


Por falar nisso, quem precisa de convites para o Google Wave? Me contate e eu mando.



Espero que tenha sido útil, agradável e didático, não importa a linguagem em que você programa.

Sucesso!

sexta-feira, 30 de outubro de 2009

Segurança dos bancos na Internet

Tudo bem que esse blog é sobre programação e outras dicas mas....

Quero deixar claro e tornar público meu repúdio à decisão judicial favorável ao banco ITAÚ e meu total repúdio e aversão à atitude tomada pelo referido banco.
Sou correntista do ITAÚ, mas a partir de hoje, se puder, deixo todo meu dinheiro no BRADESCO.
O pior: como o ITAÚ mancha sua reputação por míseros R$4000,00. Só de taxas já deve ter faturado isso de mim só esse ano.
O ITAÚ pode e DEVE ser processado, pelo cliente, por DANOS MORAIS E MATERIAIS se continuar com essa atitude.

Como acompanhamos o caso postado pelo IDG Now, a sentença, que antes era favorável ao cliente, foi mudada por um certo magistrado (parcial, vendido, subornado) estando agora favorável ao banco.
Foi feita alguma perícia (EU MESMO PODERIA FAZE-LA) com o computador do cliente para se provar que o mesmo estava inseguro. Mesmo se estivesse, é a culpa EXCLUSIVAMENTE do cliente ou o banco tem sua parcela de culpa?
Eu me pergunto se o BANCO avisou o cliente, por todos os meios de comunicação: carta, e-mail, aviso no site, propaganda na televisão etc... dos riscos que o cliente pode estar correndo.

Como sabemos, o cliente pode ser culpado por estar com um antivirus desatualizado ou falho, por baixar e executar programas duvidosos, por ser leigo em TI e não ser um especialista de segurança. Mas ele é obrigado a tal?
Se todos nós fossemos especialistas em segurança, não seria melhor irmos armados ao banco, quando formos pessoalmente? Senão o banco poderia se isentar de nos devolver o dinheiro se fossemos assaltados dentro do banco, o que ocorre com frequencia.
Como sabemos também, o código de defesa do consumidor isenta a empresa de ressarcir o cliente SE E SOMENTE a culpa for EXCLUSIVA do cliente. Será que o ITAÚ não tem nem uma parcelinha de culpa?

Na minha humilde opinião, de profissional da área:

1) O banco não tem como averiguar se o computador do cliente está seguro ou não, então ele tem a obrigação de prover a segurança
2) O usuario pode estar usando Mac OS ou linux, e o banco não tem como saber
3) Não importa se o sistema operacional ou outro sistema qualquer do usuário é pirata ou não, isso é entre o usuário e a empresa fabricante do sistema. A empresa fabricante do sistema que deve processar o usuário por estar usando sistema pirata, mas não cabe ao banco julgar isso.
4) O banco deveria ter todas as suas operações "sandboxed"
5) O banco deve prover a segurança de seus usuários, de pelo menos uma das maneiras abaixo:
5.1) Na alemanha os bancos desenvolveram programas e protocolos proprios para acesso aos serviços da banco, que não usam browsers.
5.2) o site do Itaú não é seguro (HTTPS) desde a primeira página
5.3) a empresa https://xerobank.com/ criou um browser próprio, baseado no mozilla mas com plugins de segurança e cache e proxy internacional
5.4) o BRADESCO tem um plugin activeX que identifica virus, trojans e keyloggers no computador do cliente
5.5) Jogos online, como Gunbound e CABAL, simplesmente não iniciam, e não permitem login, se o usuario tiver em seu computador um virus ou keylogger. Isso para crackers não roubarem a conta do usuário, o que acarreta pequenas perdas materiais e alguma dor de cabeça.
5.6) Como pode alguns games, que são uma diversão, terem um sistema de segurança mais sofisticado que o ITAÚ?
5.7) O yahoo criou, para evitar phishing, um sistema de selo visual um pouco mais seguro do que os sistemas que conhecemos e mais seguro que qualquer banco
5.8) Eu mesmo já criei coisa mais segura em sites que eu fiz.
5.9) Por que o Itaú não dá aquele chaveiro-token randômico para os clientes pessoa física igual alguns bancos dão para as pessoas jurídicas.
5.10) Já vi sistemas "half-mouth", que não são de nenhum banco, implementar biometria, e-cpf e outros. Por que não o ITAÚ, o banco que eu acreditava ser o maior e mais seguro?

Como sabíamos, o cliente não foi vitima de phishing, nem de keylogger, mas deum sofisticado virus que GERA AUTOMATICAMENTE o fishing quando ele entra no site do banco.
E o pior, o virus era dividido em duas partes, uma o usuário baixa e executa. (admito que essa parte é culpa do usuário). Mas a outra parte é ativado por um programa de segurança.
Se o usuário tivesse entrado numa página falsa do banco é uma coisa, mas o usuário entrou numa página verdadeira do banco, e o virus cria a página de phishing detectando o exato momento em que o usuario entra na página original, a partir dessa.

O banco não pode alegar que o computador do usuario estava inseguro, e nem que a culpa é EXCLUSIVA do usuario. Vale ressaltar que o código de defesa do consumidor só isenta a empresa se a culpa for EXCLUSIVA do cliente.

Outra coisa, de nada adianta o usuário atualizar o antivirus todo santo dia, se um virus novo simplesmente é inventado antes da ultima atualização, e até a próxima não terá vacina contra ele. Hoje mesmo atualizei meu Avira, que eu considero o melhor dos gratuitos, e ele identificou um virus que estava lá desde ontem, mas que ontem não havia sido identificado.


Bom, se fosse meu cliente, eu não gostaria de perde-lo. Além disso, está aumentando o número de usuários de serviços da internet de meia-idade ou idosos. Quem poderia culpar esses simpáticos senhores ou senhoras de não conhecerem muito de tecnologia, uma estranha tecnologia que não existia quando eram crianças? De não terem a malícia de
conhecer estratégias de segurança porque, um pouco ingenuamente, não sabem que o mundo à sua volta está muito mais perdido, desonesto e agressivo do que a 20 anos atrás?
Quem poderia culpar meu pai de ser logrado pelo site do banco, quando senhores que levam a senha anotada na meia são enganados pelos próprios funcionários do banco?

Mesmo se o problema fosse total imperícia do cliente, o banco deveria ressarci-lo. O banco pode rastrear o dinheiro através do número de série das notas. E se o banco não tiver essa informação, então o banco é notavelmente inseguro.
O banco TEM DE PROVER toda a segurança extra necessária e ponto. Para quem tomou o partido do banco, achando que sabe muito de informática, e penalizou o cliente, eu pergunto: E se fosse você? Um dia será. Você confia tanto assim no seu
sistema M$ original, seu norton antivirus, seu "soft" firewall meia - boca e nos seus milhões de antispywares, que tem seus componentes fabricados "como as salsichas"? Acho melhor você parar de usar o internet banking e só ir pessoalmente no banco.
Todas, absolutamente TODAS essas empresas de Sistema Operacional (windows), antivirus, antimalware etc fazem você concordar com um contrato que diz, garrafalmente, que eles se isentam de qualquer perda, dano, ou lucros cessantes causados por qualquer
mal funcionamento ou não-funcionamento dos seus produtos.

Um problema comum dos antivirus são os falsos positivos que nos fazem perder a confiança neles. Se você é um programador provavelmente deve ter em suas pastas uma série de dll's, biblitecas compiladas, executaveis entre outros que são erroneamente identificadas como virus porque podem ser usadas para tal. Até mesmo o CD que vem junto com o famoso livro de C++ do Deitel contem um arquivo que vive caindo em falsos positivos.


Como um colega já disse, o ITAÚ é corruptor e comprador de juizes. Uma rápida navegada no ITAÚ mostra que grande parte das páginas é HTML puro, sem qualquer tipo de validação dinâmica e que em sua maioria não são SSL, como o banco mentiu em julgamento.
A página sobre SEGURANÇA e PRIVACIDADE, é uma letra miúda, no rodapé da página, que NÃO É HTTPS (SSL).

A decisão (comprada) do desembargador cria um precedente, uma jurisprudência, que fará no futuro que todo processo semelhante a este resulte favoravelmente ao banco. O ITAÚ é mestre nesse tipo de coisa. Se for sempre favoravel ao banco, todos nós perdemos. Se for favorável ao cliente, o banco pode perder muito dinheiro, se não investir em segurança e tiver que arcar com osprejuizos.
Se a cada instância maior que se apelar a decisão for favorável ao banco, quando chegar ao supremo tribunal federal, aí, meu amigo, o banco sempre terá razão.
Imagina se fosse você: roubam todo o seu dinheiro no dia em que você recebe. Vai passar fome o mes inteiro? Nem um advogado você conseguirá pagar.

Os links com as notícias, vejam os comentários:

http://idgnow.uol.com.br/seguranca/2009/10/26/tribunal-muda-sentenca-e-isenta-itau-por-vazamento-de-senha-em-computador-de-cliente
http://idgnow.uol.com.br/seguranca/2009/10/29/banco-pode-ficar-livre-de-indenizacao-se-provar-que-culpa-por-fraude-na-web-e-exclusiva-do-consumidor-diz-procon/
http://idgnow.uol.com.br/seguranca/2009/10/30/cuidado-com-o-novo-virus-que-rouba-senhas-bancarias

terça-feira, 8 de setembro de 2009

Por que Delphi?




Antes de ser um texto apaixonado de um fanboy qualquer de uma tecnologia qualquer, isso é um texto explicativo do básico do básico sobre
linguagens de programação e compiladores.




Muitas pessoas confundem erroneamente uma linguagem de programação com o seu compilador e com a IDE em que se programa, caso houver uma. Muitas pessoas também confundem
o fato de uma linguagem ser "compilada" ou "interpretada" por um outro sistema como uma limitação da linguagem em si.




O que deve ficar claro para qualquer programador, iniciante ou experiente, é que a linguagem é a parte mais abstrata e flexível do ato de programar em si.




Uma linguagem de programação, assim como a linguagem natural nativa de um povo ou civilização qualquer, não passa de um conjunto de simbolos, grupos de simbolos, palavras
e regras gramaticais para interligação e relacionamento entre esses simbolos.




Mais do que isso, uma linguagem, seja nas artes, nas exatas ou em qualquer campo do conhecimento, é uma maneira de expressar idéias, conceitos, padrões e transmitir informações.
Portanto, uma linguagem de programação é uma maneira de um programador, seja ele humano ou não, transmitir informações e/ou dados a um outro programador, humano ou não, ou a um computador.




Quando eu digo "programador, humano ou não" me refiro ao fato de que o programador pode ser também um sistema ou programa de computador, que simplesmente
traduzem um texto ou programa num nível mais alto e menos específico para um nível mais baixo e mais específico de linguagem.




Sim, programas podem gerar programas, que por sua vez podem gerar programas, e assim por diante. Por exemplo você pode usar um compilador de C para compilar o código fonte do interpretador de PHP ou Python, e depois criar um programa em PHP ou Python para que ele possa ser "rodado".




Isto posto, qualquer pessoa ou empresa pode criar qualquer tipo de linguagem de programação. Ela terá utilidade somente abstrata (ou didática) a menos que uma pessoa ou empresa crie um compilador ou interpretador para essa linguagem.




As possibilidades de uma linguagem podem ser nulas ou infinitas, tudo depende do compilador. Qualquer linguagem pode ser usada para criar sistemas operacionais, rotinas de boot, páginas web, drivers de dispositivo e sistemas comerciais, industriais ou games, bastando que exista um compilador para isso.




Por exemplo a linguagem Pascal. Ela já passou por diversas evoluções e modificações, existem diversos "filhos" dela, como Oxygene, object pascal etc..., mas em essência ela continua a mesma.
Existem vários compiladores de pascal, desde o Turbo Pascal Compiler, passando pelo compilador do Delphi, o Free Pascal Compiler e outros, para outros sistemas operacionais e fins.
A linguagem C também possui o GCC open-source, o compilador C da microsoft, o compilador C da Borland/Embarcadero e assim por diante.




Onde quero chegar com isso?

Programadores inexperientes têm a tendência de culpar uma linguagem pelo que se pode ou não produzir com ela. Por exemplo, dizem que com C você pode criar programas em baixo nível, como Sistemas Operacionais e Drivers de Dispositivo, enquanto que em Pascal você não pode fazer isso.

Eu costumo dizer que simplesmente EU, pessoalmente, AINDA não consegui encontrar um compilador de pascal ou qualquer uma de suas derivadas que me permita compilar um driver de dispositivo.

Repare que a culpa não é da linguagem e sim do compilador. Poderia ser o contrário. Se existisse um compilador capaz de compilar drivers de dispositivo em Pascal mas não em C, as pessoas iriam usar Pascal para criar driver de dispositivo e afirmar exatamente o crontrário: que "não dá" para escrever drivers de dispositivo em C.




Com tantas linguagens e tecnologias, amplas ou específicas, conhecidas ou não, que pipocam todo dia, é até um pecado culpar a linguagem pelo que ela pode ou não produzir.

Por exemplo, suponhamos que não existisse nenhum poeta na frança, seria correto dizer que é impossível fazer poesia em Francês? Ou se não existisse nenhum músico na Itália, seria correto dizer que não se pode fazer música em Italiano?




A verdade é que, da mesma forma que existem compiladores com certas capacidades para uma linguagem, poderiam existir compiladores com essa mesma capacidade para qualquer outra.




Eu digo compiladores porque para uma linguagem gerar um executável nativo de um sistema, arquitetura ou processador, ou seja, para gerar um arquivo binário do seu estado mais puro, que nada mais é do que um conjunto de instruções para um determinado processador, uma linguagem precisa de um compilador.




No caso dos interpretadores, eles nada mais são do que programas que leem trechos ou linhas de código, as interpretam e executam, ou as compilam para um formato binário em memória, sob demanda, em tempo de execução e fazem o que tem que fazer.




Os iniciantes insistem em dizer, por exemplo, que C, C++ e Pascal são compilados enquanto que Java, Python, PHP e C# são interpretados.




Eu insisto em dizer que uma linguagem pode ser compilada ou interpretada a medida que exista um compilador ou interpretador para ela. Como programador eu sei que nada impede ninguém de criar um
interpretador para C++, ou uma máquina virtual para Pascal.

Da mesma forma, uma empresa qualquer poderia criar um compilador de Java, que transformasse um codigo fonte Java em um binário puro e nativo de uma determinada arquitetura. Da mesma forma poderiam ser criados compiladores de Python ou PHP, que fizesse, inclusive, drivers de dispositivo em PHP.

Eu já vi, por exemplo, Basic rodar compilado e interpretado. COBOL compilado e interpretado, e assim por diante.




As possibilidades sempre foram infinitas, é só usar a imaginação.

A única coisa que me impede de criar agora um compilador ou interpretador de Portugol agora é o tempo e a dificuldade envolvida.




Muitas pessoas ainda dizem que a melhor linguagem de todas é o Assembly, porque todos os compiladores um dia foram escritos em Assembly, portanto Assembly é a mãe de todos os compiladores e de todas as linguagens.




Vão engano.

Pense no seguinte: Ao criar o primeiro martelo da humanidade, alguém usou uma pedra para fixar o cabo de madeira no martelo propriamente dito, certo?

E ao criar o segundo martelo? Será que não foi mais fácil e inteligente usar o primeiro martelo para montar o segundo?

Assim também é com as linguagens de programação. Da mesma forma como no passado foi usado Assembly para criar o primeiro compilador de C, hoje usa-se muito o C para se criar Assemblers, das mais diversas plataformas.

Se você duvida, faça uma rápida busca no Google e confira o Nasm, um assembler GNU, open-source muito usado e difundido no universo GNU. Baixe os fontes dele, ele é totalmente escrito em C.

Ele poderia ser escrito em pascal, por exemplo. E a única coisa que impediu que ele fosse escrito em assembly foi a praticidade.




Mais uma vez eu repito: qualquer linguagem pode escrever absolutamente qualquer programa, e qualquer programa pode ser escrito em qualquer linguagem. Tudo depende, em primeira instância, do conhecimento e criatividade do programador, e em segunda instância do compilador.

Compiladores e Assemblers também são programas, onde existe uma entrada (um arquivo de código fonte), existe um processamento, e existe uma saída (um arquivo binário, executável, um programa ou parte dele, uma dll etc). Por isso compiladores e assemblers podem ser escritos também em qualquer linguagem.




As pessoas também confundem a linguagem com a IDE. Por exemplo muitos dizem: "eu gosto mais de delphi, porque é fortemente tipado" se referindo à linguagem, quando deveriam dizer "eu gosto mais de object pascal".

Ou dizem : "eu gosto mais de C#, porque nele você cria web sites muito intuitivamente" referindo - se a IDE visual studio, quando na verdade deveriam dizer que gostam de Visual Studio.




Uma IDE, ou Integrated Development Environment (ambiente de desenvolvimento integrado) nada mais é do que um conjunto de softwares que atuam como uma grande caixa de
ferramentas para programadores. Uma IDE contém um editor de código fonte, geralmente com iluminação e destaque de sintaxe, pré validação de sintaxe, recursos para auto-completar código etc...

Uma IDE é uma ferramenta que ajuda e torna mais prático a criação ou formulação de um arquivo de código fonte, bem como o agrupamento de vários desses arquivos em um projeto.

A IDE pode conter geradores de codigos, wizzards, templates, integração com bancos de dados ou leitores / visualizadores / editores de bancos de dados, ou UML. Integração com sistemas de versionamento de código, componentes, snippets, ferramentas de desenho de páginas e formulários e, o mais importante:

Toda a IDE possui uma integração com um compilador. A IDE é uma espécie de "Word" para código fonte. Mas depois do código fonte salvo, a IDE "chama" ou executa um compilador,
que pode ou não vir junto com ela, mandando que o compilador compile o arquivo de código salvo por ela, gerando assim um programa executável.

Muitas IDE's também acompanham um vasto conjunto de bibliotecas de funções e classes, bem como exemplos e snippets, para facilitar o processo de codificação.

Além disso uma função interessante das IDE's é o help, sensível a contexto, tanto da própria IDE e suas ferramentas, como da linguagem para a qual ela foi desenvolvida.




Uma ide não precisa ser específica para apenas uma linguagem, muito menos para um único compilador. Um exemplo disso é o próprio visual studio, que serve para se
escrever código em C#, C++ ou VB, e também possui integração com compiladores dessas três linguagens. Você pode instalar para o Visual Studio, na forma de plugin, uma nova linguagem
e um novo compilador, como no caso da linguagem Oxygene, evolução do object pascal, e o Delphi Prism.

Outras IDE's assim são o Eclipse e o NetBeans, onde você pode instalar novas linguagens e configurar um ou mais compiladores para cada linguagem. Por exemplo eu configurei meu NetBeans para usar tanto o GCC como o Borland C++ para compilar a linguagem C. Eu posso escolher qual usar.




As vezes, aliás, quase sempre, uma empresa adiciona um novo comando ou sintaxe a uma linguagem, criando assim uma nova vertente ou dialeto dela, para criar um recurso especial ou atender uma necessidade específica num novo compilador que está criando.

Isso é muito normal e não é um problema, visto que grande parte da linguagem continua a mesma. Além disso existem padrões, e se você nivelar por baixo verá que
se um código fonte em uma determinada linguagem for escrito visando a intersecção ou o mínimo dos recursos de todos os seus compiladores então você garante
a portabilidade desse código entre os seus vários compiladores, sistemas, plataformas etc.

Isso eleva exponencialmente o número de plataformas, sistemas, bibliotecas e suas combinações nas quais podemos trabalhar.




Linguagens de programação podem ser um assunto tão infinito quanto literatura, poesia ou matemática, por isso eu escolhi algumas dentre as quais gostaria de trabalhar.




Como linguagem eu escolhi o Pascal e Object Pascal devido não somente à facilidade de aprendizado, mas à facilidade de ensino. É uma linguagem robusta, flexível,
fortemente tipada e nem por isso limitada, muito similar ao Portugol, elegante, onde eu posso fazer minha programação tanto sob o paradigma estruturado como sob o
paradigma orientado a objetos. Muitos professores de universidades consideram, ou pelo menos deveriam considerar, pascal como uma boa opção de linguagem ao se ensinar programação.

Eu não teria a prepotência ou a arrogância de discordar de Niklaus Wirth.




Como IDE para trabalhar com Object Pascal eu escolhi o Delphi e sua contraparte Open-Source Lazarus, pela facilidade de se criar formularios e Interfaces com o usuário ricas,
repletas de controles, eventos e interatividade com os usuários, além da facilidade de acesso a diversos bancos de dados, facilidade de deploy, uma certa medida de portabilidade entre outras questões.

Todo compilador e/ou IDE vem junto com uma biblioteca ou conjunto de bibliotecas de classes e funções, com fontes ou simplesmente pré-compiladas, em uma ou mais linguagens.

Essas bibliotecas, as vezes publicas e com contribuições da comunidade, as vezes privadas, contam com um alto gral de robustez, devido ao amplo número de contribuições e correções a que se submeteram, número de usuários e tempo de uso.

No caso do Delphi não podia ser diferente, com as bibliotecas RTL, VCL (de componentes visuais) e a JCL e JVCL do projeto JEDI, fornecem um leque gigante de ferramentas para desenvolvimento, deploy, design etc...

E o lazarus, com sua LCL não fica devendo em nada nesse quesito.




O Delphi pode não ser mais barato que os concorrentes proprietários similares, mas existem versões gratuitas do Delphi, por exemplo o Turbo Explorer Delphi 2006, que como unica limitação impede que você instale pacotes e componentes de terceiros,
limitação esta que pode ser facilmente contornada instanciando - se os componentes em runtime. Versões mais antigas do Delphi, como o 3 e o 4 també já foram distribuídas gratuitamente, e não deixam a desejar se o assunto for ensino e aprendizado de programação.

Como alternativa ao desenvolvimento profissional, com baixo custo, temos o Lazarus, que é o "Delphi" do Free Pascal, livre de todas as formas como um software arte deve ser.




Outra característica marcante do Delphi é o desenvolvimento multi camadas usando sockets, COM e COM+, DataSnap entre outras tecnologias, e a rapidez em desenvolver um sistema nesses moldes.




Os programadores inexperientes tem a mania de "Malhar" ou "Humilhar" uma determinada linguagem e enaltecer outras, ou idolatrar uma linguagem em detrimento de outras, mas o bom programador, o experiente,
procura pelo menos conhecer o básico e os objetivos ou vantagens de todas elas.

Como eu disse todas as linguagens podem servir para todas as coisas e atender a todas as necessidades dependendo do conhecimento, experiência e criatividade do programador.




Existem por aí muitas dicas de como se tornar um bom programador. Eu dou a minha dica aqui, sobre como se tornar um bom programador:


  • Conhecimento de inglês, desejável inglês fluente

  • Conhecimento de matemática, pelo menos para não passar vergonha

  • Apreço pela leitura, vontade de ler, gosto por ler, desejável leitura dinâmica

  • Deve aprender a PROGRAMAR, e não aprender uma linguagem de programação.





Inglês é óbvio o porquê de aprender e eu não vou entrar no assunto. Leitura dinâmica deveria ser ensinada na escola, na primeira ou segunda série, logo depois de se ensinar o indivíduo a ler. No máximo deveria ser matéria do ensino médio.

Porquê? Simples, por causa da velocidade e sazonalidade com que livros de tecnologia, principalmente programação, são escritos. São escritos em um ano e tornam-se obsoletos no ano seguinte.

A leitura simplesmente intelectualiza o indivíduo, não importa qual é a área.




Acho que todo programador deveria saber muito sobre a linguagem que mais GOSTA, o suficiente sobre uma linguagem interpretada qualquer: (Java, Perl, Python, PHP, Ruby...), o suficiente sobre a linguagem que mais TRABALHA, e o básico de C.

C é uma grande linguagem. É a única linguagem que todos respeitam, ninguem xinga, ninguém malha e ela é respeitada por todos, até pelos que não a utilizam no seu dia a dia ou simplesmente não a conhecem a fundo.




Qualquer programador tem que saber C, não simplesmente porque ela é uma grande linguagem, mas porque foram escritos grandes compiladores para ela.




Batendo novamente na tecla de linguagens compiladas (quando existe um compilador para elas) e linguagens interpretadas (quando existe apenas um interpretador para elas), todos nós sabemos a diferença entre as duas:

As linguagens compiladas geram um programa mais rápido (o compilador gera), enquanto a maioria das linguagens interpretadas geram programas fáceis de se fazer ou dar manutenção, com recursos de reflexão e metaprogramação.

Linguagens compiladas geram executaveis nativos, menores, mais rápidos, embora sejam mais complicadas. Linguagens interpretadas são mais fáceis e flexíveis, tornando-as mais produtivas, embora sejam mais lentas e pesadas.

Linguagens compiladas precisam ser recompiladas em outros sistemas operacionais, se for possível, enquanto que linguagens interpretadas são portáveis direto para outros sistemas operacionais contanto que tenham o runtime, máquina virtual, interpretador ou conjunto
de frameworks correto e adequado ao programa, e VOCÊ tenha paciência de levar tudo isso pra cá e pra lá.

Todas as linguagens servem para fazer programas, porém,
linguagens compiladas fazem drivers de dispositivos e programas em modo kernel enquanto linguagens interpretadas tem uma certa facilidade para se fazer scripts e páginas da web.

O Delphi é compilado, ou melhor, uma ferramenta para se compilar object pascal, embora o compilador não tenha todos os recursos de um compilador C. Eu nunca vi um programa em modo kernel feito em Delphi... EU nunca vi, você pode ter visto.

Mesmo assim o Delphi possui todas as facilidades e flexibilidades de uma linguagem Interpretada, OO, dinâmica como Java ou Ruby. Além de ser produtiva e gerar executáveis rápidos.




Não, tudo isso acima é besteira e ao mesmo tempo não é, COMO EU JÁ DISSE: Não adianta bater na tecla de linguagens interpretadas Vs. Linguagens compiladas porque, como eu já disse novamente, todos já sabemos a diferença.




Java? Eu curto, acho legal, respeito os fanáticos (sim linguagem de programação, para alguns, é como religião, existem fanáticos), mas eu não curto a JVM em si. Não acho legal ser obrigado a ter 1GB de ram pra rodar um hello world com
todos os recursos da JVM que eu não vou usar. Não acho legal precisar de uma supermáquina pra rodar o TD-REDF, validador e transmissor de nota fiscal paulista do governo, que é capaz de transformar em uma carroça o mesmo computador que roda O SEU SISTEMA COM RAPIDEZ E LEVEZA.

A medida que eu for precisando de Java no meu trabalho eu vou usando, porque não, afinal ele está no topo da literatura, no apogeu do uso, no ápice das contribuições da comunidade, literalmente bombando.

Daqui pra frente o que vier pode ser decadência....




Existem, claro, outras implementações da JVM, para outras plataformas, assim como existem para .Net etc... Acredito ainda que parte do peso e performance de aplicativos feitos em Java se devam a problemas de design e projeto por parte de seus idealizadores, e não culpa da JVM em si.




Nem sempre, ou quase nunca, o problema é da linguagem, compilador, interpretador, vm, computador....




Tem programador que faz caca em Delphi e culpa o Delphi, faz caca em Java e culpa o Java, faz caca em Assembly e culpa o Assembly, simplesmente faz caca e não assume.

Assim como um BOM PROGRAMADOR programa bem em qualquer linguagem, um PROGRAMADOR MEDÍOCRE FAZ MEDIOCRIDADE EM QUALQUER LINGUAGEM.




Programadores medíocres são aqueles que sabem uma linguagem apenas, mas não sabem programar de verdade.

Eles vivem se perguntando: "o que será do futuro?", "O que será do mercado?" , "A linguagem x está falindo?" , "Compensa aprender y?", "o que vai ser do meu emprego/carreira se a linguagem z morrer?", "A empresa a comprou a b, que vai ser de mim?", "a linguagem K está morrendo, morrerei junto?" ....





Eu digo aqui, com todas as letras, o que será do futuro e do mercado:

DANE-SE O FUTURO E O MERCADO!

Eu faço meu próprio futuro, eu faço meu próprio mercado.




Eu gosto de Delphi, gosto de C#, C e outras linguagens. Vou continuar a usar todas as que eu gostar, tanto pessoalmente como profissionalmente de acordo com minhas necessidades ou vontades.

É assim que funciona.

Nenhuma linguagem desaparece, elas evoluem como a ortografia do nosso bom e velho português.

Sim, fábricas de compiladores podem, um dia, desaparecer, assim como poetas e romancistas morrem, mas não levam a linguagem junto para o túmulo.

E os bons de verdade, meu amigo, são e serão sempre IMORTAIS...



sexta-feira, 4 de setembro de 2009

O dilema do envio de e-mail


Hoje em dia um sistema enviar um e-mail automático é não só comum como uma necessidade. Sistemas enviam e-mails automáticos para usuarios que se cadastram num sistema, enviam login e senha para quem esqueceu, enviam as ofertas da semana e uma infinidade de eventos que acontecem em sistemas online.
Mas não são apenas os sistemas web como e-commerce ou sites de rede social, mas ERP's, CRM, SCM e HRM também enviam e-mails. Pipelines de produção avisam gerentes quando uma variável atingiu um valor crítico ou exige atenção. Por exemplo, quando um determinado produto ou insumo no estoque atinge um determinado nivel, o responsável recebe um e-mail, e , as vezes, o fornecedor também recebe um e-mail com a proposta de compra.
Programas de monitoria de rede, de segurança etc enviam e-amils.
Enfim, as aplicações precisam enviar e-mails para os mais diversos fins. Cada linguagem tem a sua maneira e a sua peculiaridade. Mas o que é necessário para enviar um e-mail?
Pasmem, embora o spam seja uma prática muito feia, quem faz afirma que surte efeitos. Eu mesmo já conheci e comprei várias coisas legais através de spam. Mas foi pouca coisa. O resto eu configurei pra ir pro lixo mesmo. Aliás, o melhor anti-spam que eu conheço é o do gmail. Parabéns para o pessoal da Google.
O mínimo que você precisará é de um servidor de SMTP anônimo, no qual você não precise se autenticar para mandar um e-mail. Esses servidores aceitam que você envie e-mails apenas do host onde está o próprio servidor, ou de algum outro host do mesmo domínio. O IIS já vem com um servidor de smtp. A configuração do servidor de SMTP, bem como as configurações de relay fogem ao escopo desse artigo.
Vamos abordar aqui como mandar um e-mail através de um SMTP anônimo usando o .Net framework 1.1. Depois falaremos sobre como mandar e-mails através de servidores de SMTP autenticado e por último falaremos desses dois assuntos no .Net framework 2.0 ou superior.
Primeiro de tudo, seja em C# ou seja em VB.Net você vai precisar colocar isso no seu using:
using System.Web.Mail;
Depois digite o código da Listagem 1, abaixo, no evento que for disparar um e-mail, por exemplo o evento onclick de um botão, na página de fale conosco.
Listagem 1:

MailMessage message = new MailMessage();
try
{
 //crio o objeto MailMessage, que contem o conjunto de parametros de uma mensagem de e-mail

 //aqui eu configuro os parâmetros da mensagem em si
 message.From = "[[nome]]@[[domínio]]"; //e-mail do remetente, deve vir do web.config (mas pode ser  fixo se for uma unica pagina de fale conosco e você não tiver acesso ao web.config)
 message.To = "vitorrubio@gmail.com"; //e-mail do destinatário, deve vir de um textbox
 message.Subject = "teste 1"; //assunto, deve vir de um textbox, ou do web.config
 message.Body = "Isto é uma mensagem de teste."; //corpo da mensagem, deve vir de um textbox

 //aqui eu configuro os parametros do servidor de SMTP SEM AUTENTICAÇÃO
 SmtpMail.SmtpServer = "[[servidor]]"; //servidor de smtp, deve vir do web.config (mas pode ser  fixo se for uma unica pagina de fale conosco e você não tiver acesso ao web.config)
  
 SmtpMail.Send(message);

 Label1.Text = "e-mail enviado com sucesso!";
}
catch (Exception ex)
{
 Label1.Text = "Erro ao enviar e-mail " + ex.Message;

 //concatena todas as inner exceptions:

 //loop para concatenar todas as exceptions ao longo do caminho, porque a exception mais externa não é muito conclusiva
 while (ex.InnerException != null)
 {
  ex = ex.InnerException;
  Label1.Text += " --- Inner Exception --- " + ex.ToString();
 }
}
Repare bem que no catch eu coloco a mensagem de erro e o exception mais externo no label, mas eu crio um laço while para concatenar as mensagens de todos os exceptions mais internos. Faço o loop enquanto a minha exception corrente EX tiver um inner exception diferente de null. Essa é minha condição de parada. Depois eu substituo o proprio EX pelo inner exception dele mesmo, para que eu não entre num loop infinito.
Com todas essas excessões mostradas a mim eu posso saber o motivo exato de o e-mail não ter sido enviado. É necessário um inglês mínimo.
Agora se você estiver tentando mandar e-mail através de um servidor autenticado, como Terra ou Yahoo, assim você não vai conseguir. Terá de usar alguns artifícios e preencher alguns campos especiais que a Microsoft preparou no objeto message. Você confere isso na listagem 2.
Listagem 1:

MailMessage message = new MailMessage();
try
{
 //crio o objeto MailMessage, que contem o conjunto de parametros de uma mensagem de e-mail

 //aqui eu configuro os parâmetros da mensagem em si
 message.From = "[remetente]"; //e-mail do remetente, deve vir do web.config
 message.To = "vitor@rt.com.br"; //e-mail do destinatário, deve vir de um textbox
 message.Subject = "teste 1"; //assunto, deve vir de um textbox, ou do web.config
 message.Body = "Isto é uma mensagem de teste."; //corpo da mensagem, deve vir de um textbox

 //aqui eu configuro os parametros do servidor de SMTP. A autenticação você pode ver logo abaixo
 SmtpMail.SmtpServer = "[servidor de smtp]"; //servidor de smtp, deve vir do web.config


 /*
  * Mas, se você precisar de mandar um e-mail num servidor smtp com autenticação....
  * num servidor que não é seu.... aí você vai precisar dessa gambiarra da microsoft
 */


 //se você precisar enviar e-mail através de um servidor com autenticação, por exemplo terra ou yahoo, utilize esses parametros
 message.Fields["http://schemas.microsoft.com/cdo/configuration/smtsperver"] = "[servidor de smtp]"; //server
 message.Fields["http://schemas.microsoft.com/cdo/configuration/smtpserverport"] = 25;//porta, geralmente é a 25 quando não usa ssl
 message.Fields["http://schemas.microsoft.com/cdo/configuration/sendusing"] = 2;
 message.Fields["http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"] = 1; //marca se tem que autenticar
 message.Fields["http://schemas.microsoft.com/cdo/configuration/sendusername"] = "[seu login]"; //user
 message.Fields["http://schemas.microsoft.com/cdo/configuration/sendpassword"] = "[sua senha]"; //senha


 SmtpMail.Send(message);

 Label1.Text = "e-mail enviado com sucesso!";
}
catch (Exception ex)
{
 Label1.Text = "Erro ao enviar e-mail " + ex.Message;

 //concatena todas as inner exceptions:

 while (ex.InnerException != null)
 {
  ex = ex.InnerException;
  Label1.Text += " --- Inner Exception --- " + ex.ToString();
 }
} 
 


Observe aqui que
preenchemos alguns campos especiais do objeto Message. Você pode, inclusive, colocar todo o código numa única página .aspx sem precisar de um codebehind. Você não precisa nem de visual studio ou #develop para fazer essa página, qualquer bloco de notas resolve. Veja como fica no proximo snippet:



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

<html>
<head>
 <title>MandaEmailDireto</title>
 <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
 <meta name="CODE_LANGUAGE" Content="C#">
 <meta name=vs_defaultClientScript content="JavaScript">
 <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
</head>
<body >

 <form id="Form1" method="post" runat="server">
<P>
 <asp:Label id=Label1 runat="server">Label</asp:Label></P>
<P>

<asp:Button style="Z-INDEX: 0" id=Button1 runat="server" Text="Button"></asp:Button></P>
 <script language=C# runat=server>

public void Page_Load(object sender, System.EventArgs e)
{
Response.Write("Página Carregada!<br>");
}

override protected void OnInit(EventArgs e)
{
this.Button1.Click += new System.EventHandler(this.Button1_Click);
base.OnInit(e);
}

public void Button1_Click(object sender, System.EventArgs e)
{

System.Web.Mail.MailMessage message = new System.Web.Mail.MailMessage();
try
{
 //crio o objeto MailMessage, que contem o conjunto de parametros de uma mensagem de e-mail

 //aqui eu configuro os parâmetros da mensagem em si
 message.From = "[remetente]"; //e-mail do remetente, deve vir do web.config
 message.To = "[destinatario]"; //e-mail do destinatário, deve vir de um textbox
 message.Subject = "teste 1"; //assunto, deve vir de um textbox, ou do web.config
 message.Body = "Isto é uma mensagem de teste."; //corpo da mensagem, deve vir de um textbox

 //aqui eu configuro os parametros do servidor de SMTP SEM AUTENTICAÇÃO
 System.Web.Mail.SmtpMail.SmtpServer = "[servidor]"; //servidor de smtp, deve vir do web.config


 /*
  * Mas, se você precisar de mandar um e-mail num servidor smtp com autenticação....
  * num servidor que não é seu.... aí você vai precisar dessa gambiarra da microsoft
 */


 //se você precisar enviar e-mail através de um servidor com autenticação, por exemplo terra ou yahoo, utilize esses parametros
 message.Fields["http://schemas.microsoft.com/cdo/configuration/smtsperver"] = "[servidor]"; //server
 message.Fields["http://schemas.microsoft.com/cdo/configuration/smtpserverport"] = 25;//porta, geralmente é a 25 quando não usa ssl
 message.Fields["http://schemas.microsoft.com/cdo/configuration/sendusing"] = 2;
 message.Fields["http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"] = 1; //marca se tem que autenticar
 message.Fields["http://schemas.microsoft.com/cdo/configuration/sendusername"] = "[login]"; //user
 message.Fields["http://schemas.microsoft.com/cdo/configuration/sendpassword"] = "[senha]"; //senha


 System.Web.Mail.SmtpMail.Send(message);

 Label1.Text = "e-mail enviado com sucesso!";
}
catch (Exception ex)
{
 Label1.Text = "Erro ao enviar e-mail " + ex.Message;

 //concatena todas as inner exceptions:

 while (ex.InnerException != null)
 {
  ex = ex.InnerException;
  Label1.Text += " --- Inner Exception --- " + ex.ToString();
 }
}
} 
 </script>


  </form>

</body>
</html>
Atente que para esses casos de servidores de SMTP autenticados, e até mesmo para alguns casos de servidores de SMTP anônimos do seu próprio domínio, o servidor pode exigir que o domínio do remetente seja o mesmo domínio dele. Ou seja, para mandar um e-mail pelo SMTP do yahoo, o remetente precisa ser do yahoo (não que o yahoo seja assim, isso é só um exemplo).
Não precisamos preencher todos esses dados especiais na mensagem no .Net 2.0.
O que precisamos é instanciar um objeto SMTPClient e preencher corretamente os valores das propriedades.
Vamos ver como fazer no próximo snippet:
  protected void Button1_Click(object sender, EventArgs e)
{
SmtpClient smtpCliente = new SmtpClient();
MailMessage message = new MailMessage();
try
{
 //duas variáveis MailAddress para o remetente e destinatário
 MailAddress fromAdress = new MailAddress("***remetente***", "nome do remetente"); //remetente
 MailAddress toAdress = new MailAddress("***destinatario 1 ****", "nome"); //destinatario 1
 MailAddress toAdress2 = new MailAddress("**destinatario 2 ***", "nome"); //destinatario 2

 message.From = fromAdress;
 message.To.Add(toAdress); //adiciona o destinatario 1
 message.To.Add(toAdress2); //adiciona o destinatario 2
 message.Subject = "Teste";
 message.Body = "mensagem de teste.";

 //configuração do smtp
 smtpCliente.Host = "***servidor***";

 ////credenciais, ou seja, login e senha. Essa parte não precisa se o servidor web for o proprio servidor de e-mail anonimo, ou se o servidor de e-mail anonimo permitir relay a partir do ip que você estiver tentando mandar.
 smtpCliente.Credentials = new NetworkCredential("***login***", "***senha***");

 smtpCliente.Send(message);
 Label1.Text = "e-mail enviado com sucesso!";
}
catch (Exception ex)
{
 Label1.Text = "Erro ao enviar e-mail " + ex.Message;

 //concatena todas as inner exceptions:

 while (ex.InnerException != null)
 {
  ex = ex.InnerException;
  Label1.Text += " --- Inner Exception --- " + ex.ToString();
 }
}
}
Analogamente podemos fazer o envio de e-mail com o código C# direto na página asp.net, conforme o snippet abaixo:

<%@ Import Namespace="System.Net.Mail" %>
<%@ Import Namespace="System.Net" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title>Untitled Page</title>
</head>
<body>
 <form id="form1" runat="server">
 <div>

     <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
     <br />
     <br />
     <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
  
     <script language="C#" runat="server">
  
         protected void Page_Load(object sender, EventArgs e)
         {
             Response.Write("Página Carregada!");
         }
         protected void Button1_Click(object sender, EventArgs e)
         {
             SmtpClient smtpCliente = new SmtpClient();
             MailMessage message = new MailMessage();
             try
             {
                 //duas variáveis MailAddress para o remetente e destinatário
                 MailAddress fromAdress = new MailAddress("email do remetente", "nome do remetente"); //remetente
                 MailAddress toAdress = new MailAddress("destinatario 1", "nome"); //destinatario 1
                 MailAddress toAdress2 = new MailAddress("destinatario 2", "nome"); //destinatario 2

                 message.From = fromAdress;
                 message.To.Add(toAdress); //adiciona o destinatario 1
                 message.To.Add(toAdress2); //adiciona o destinatario 2
                 message.Subject = "Teste";
                 message.Body = "mensagem de teste.";

                 //configuração do smtp
                 smtpCliente.Host = "servidor";
              
                 //credenciais, ou seja, login e senha. Essa parte não precisa se o servidor web for o proprio servidor de e-mail anonimo, ou se o servidor de e-mail anonimo permitir relay a partir do ip que você estiver tentando mandar.
                 smtpCliente.Credentials = new NetworkCredential("login", "senha");

                 smtpCliente.Send(message);
                 Label1.Text = "e-mail enviado com sucesso!";
             }
             catch (Exception ex)
             {
                 Label1.Text = "Erro ao enviar e-mail:<br/> " + ex.Message;

                 //concatena todas as inner exceptions:

                 while (ex.InnerException != null)
                 {
                     ex = ex.InnerException;
                     Label1.Text += " --- Inner Exception --- " + ex.ToString();
                 }
             }
         }
     </script>

 </div>
 </form>
</body>
</html>
Onde quero chegar com tudo isso? Seguinte, para os web designers, que muitas vezes não são programadores e sabem apenas o básico, pode ser um desafio mandar um e-mail
pelo smtp do servidor, seja para um formulario de contato, fale conosco ou até mesmo cadastro. Por isso resolvi criar essa página como uma espécie de template
para que possa ser usada por webdesigners.
Abaixo você pode conferir todo o código desse template de envio de e-mail, com diversos camposde informações gerais, através de um script C# em uma página asp.net, com runat=server

<%@ Import Namespace="System.Net.Mail" %>
<%@ Import Namespace="System.Net" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title>Fale Conosco</title>
</head>
<body>
 <form id="form1" runat="server">
 <div>

     <asp:Label ID="lbMensagem" runat="server" ForeColor="#FF3300"></asp:Label>
     <br />
     <br />
     <asp:Label ID="Label2" runat="server" Text="Nome"></asp:Label>
     <br />
     <asp:TextBox ID="txtNome" runat="server"></asp:TextBox>
     <br />
     <asp:Label ID="Label3" runat="server" Text="E-Mail"></asp:Label>
     <br />
     <asp:TextBox ID="txtEmail" runat="server"></asp:TextBox>
     <br />
     <asp:Label ID="Label4" runat="server" Text="Assunto"></asp:Label>
     <br />
     <asp:TextBox ID="txtAssunto" runat="server"></asp:TextBox>
     <br />
     <br />
     <asp:CheckBox ID="cbFumante" runat="server" Text="Fumante" />
     <br />
     <asp:CheckBox ID="cbConducao" runat="server" Text="Condução própria" />
     <br />
     <asp:CheckBox ID="cbSolteiro" runat="server" Text="Solteiro" />
     <br />
     <asp:RadioButtonList ID="rgSexo" runat="server">
         <asp:ListItem Selected="True">Masculino</asp:ListItem>
         <asp:ListItem>Feminino</asp:ListItem>
     </asp:RadioButtonList>
     <br />
     <br />
     <br />
     <asp:Label ID="Label5" runat="server" Text="Corpo da Mensagem"></asp:Label>
     <br />
     <asp:TextBox ID="txtCorpo" runat="server" Height="138px" TextMode="MultiLine"
         Width="299px"></asp:TextBox>
     <br />
     <br />
     <asp:Button ID="btEnviar" runat="server" onclick="btEnviar_Click"
         Text="Enviar" />
  
     <script language="C#" runat="server">
  
         protected void Page_Load(object sender, EventArgs e)
         {
             //isso serve simplesmente para saber se o asp.net está funcionando e a página foi carregada corretamente. Depois de testado pode ser omitido.
             Response.Write("Página Carregada!");
         }
         protected void btEnviar_Click(object sender, EventArgs e)
         {
             SmtpClient smtpCliente = new SmtpClient();
             MailMessage message = new MailMessage();
             try
             {
                 //duas variáveis MailAddress para o remetente e destinatário
                 MailAddress fromAdress = new MailAddress(txtEmail.Text, txtNome.Text); //remetente (campos textbox do cliente)
                 MailAddress toAdress = new MailAddress("vitorrubio@gmail.com", "Vitor Rubio"); //destinatario  (quem recebe na empresa)

                 message.From = fromAdress;
                 message.To.Add(toAdress); //adiciona o destinatario
                 message.Subject = txtAssunto.Text;
              
                 //vamos compor o corpo com todas as informações dadas pelo usuário
                 //criamos uma string chamada corpao: (pode ser um stringbuilder, mas precisa de um import de system.text)
              
                 string corpao = "";
              
                 //vamos concatenando (grudando) todas as informações
                 //o operador += concatena as strings. corpao += "laranja" é o mesmo que dizer "corpao recebe o que já estava escrito lá grudado com "laranja"
                 //"\r\n pula uma linha, como se tivesse dado um enter ou escrito um <br> no html
              
                 corpao += "Nome: " + txtNome.Text + "\r\n";
                 corpao += "E-Mail: " + txtEmail.Text + "\r\n";
                 corpao += "Assunto: " + txtAssunto.Text + "\r\n";
              
                 //pulamos mais uma linha
                 corpao += "\r\n";
              
                 //começamos a colocar as outras informações, sobre sexo etc. Essas informações não são strings (palavras ou cadeias de caracteres)
                 //mas são booleanas (lógica), com excessão de sexo que dá para pegar o valor selecionado e transformar em string
                 //entenda string como uma cadeia, ou sequencia, de caracteres, como palavras e frases.
              
                 //aqui concatenamos a palavra "Fumante: " e usamos o operador ternário para perguntar: A caixinha está clicada? Se sim então grude a palavra "sim", se não "não"
                 corpao += "Fumante: " + ((cbFumante.Checked)?"Sim":"Não") + "\r\n";
                 corpao += "Conducao Própria: " + ((cbConducao.Checked)?"Sim":"Não") + "\r\n";
                 corpao += "Solteiro: " + ((cbSolteiro.Checked)?"Sim":"Não") + "\r\n";
              
                 //agora o sexo, que não é nem checkbox nem textbox, mas é um radiogroup
                 corpao += "Sexo: " + rgSexo.SelectedValue.ToString() + "\r\n";
              
                 //pula duas linhas e poe a mensagem:
                 corpao +=  "\r\n\r\n";
                 corpao += txtCorpo.Text + "\r\n";
              
                 //e o body da mensagem é o corpão:
                 message.Body = corpao;
              
                 //facinho facinho!

                 //configuração do smtp
                 smtpCliente.Host = "localhost"; //use  o host fornecido pelo serviço de hospedagem, se precisar armazene no web.config
              
                 //credenciais, ou seja, login e senha. Essa parte não precisa se o servidor web for o proprio servidor de e-mail anonimo, ou se o servidor de e-mail anonimo permitir relay a partir do ip que você estiver tentando mandar.
                 //nesse caso, se usarmos o serviço de SMTP do proprio serviço de hosting/hospedagem/colocation provavelmente será um SMTP anônimo. Consulte seu fornecedor de serviços para tirar as dúvidas.
                 //smtpCliente.Credentials = new NetworkCredential("login", "senha");

                 smtpCliente.Send(message);
              
                 //colocamos, através do dream weaver, expression ou visual studio um label e demos o nome de lbMensagem
                 //usaremos a propriedade text do lbMensagem para avisar o usuario do sucesso ou fracasso do envio do e-mail
              
                 lbMensagem.Text = "e-mail enviado com sucesso!";
             }
             catch (Exception ex)
             {
                 //se der erro, veremos onde
                 lbMensagem.Text = "Erro ao enviar e-mail:<br/> " + ex.Message;

                 //concatena todas as inner exceptions:

                 while (ex.InnerException != null)
                 {
                     ex = ex.InnerException;
                     lbMensagem.Text += " --- Inner Exception --- " + ex.ToString();
                 }
             }
         }
     </script>

 </div>
 </form>
</body>
</html>

Aqui neste arquivo zipado temos vários exemplos do envio de e-mail através do C#
Os exemplos EnviaEmail_1.1 e EnviaEmailDireto_1.1 mostram como enviar e-mail através do .net framework 1.1 com e sem code behind. Ou seja, o "Direto" aqui significa que o código C# está direto na página, para ser compilado e executado em runtime, no server.
Os exemplos EnviaEmail_2.0 e EnviaEmailDireto_2.0 são análogos, mas para .net framework 2.0 ou superior.
Como dito anteriormente, para mandar e-mails a partir do próprio servidor de smtp ele deve estar configurado corretamente, com relay e tudo o mais, e o
destinatário tem que aceitar emails provindos do seu IP. Este Site pode te ajudar a configurar o SMTP.
Esses livros são apenas 3 de milhares que podem te ajudar a iniciar uma carreira de programador C# / Asp.net

http://www.livrariasaraiva.com.br/produto/produto.dll/detalhe?pro_id=130808&ID=C95552527D909041024070050

https://www.verticebooks.com.br/index.php?sub=produto&id=16172

http://www.livrariasaraiva.com.br/produto/produto.dll/detalhe?pro_id=944045&ID=C95552527D909041024070050
Espero que tenha sido util a todos.

have fun ;)



sexta-feira, 28 de agosto de 2009

Criando um Port Scanner em Delphi


Um port scanner é um programa que serve para procurar por portas TCP/IP abertas em um ou mais computadores da rede.
É possível criar um port scanner em delphi facilmente com poucas linhas de código.
Criei um port scanner multithread apenas para demonstrar como threads podem ser usadas no dia a dia.
Vale a pena conferir, no meu space da dev media.
http://www.devmedia.com.br/articles/viewcomp.asp?comp=14097



você pode fazer o download direto dele aqui no meu drop box

Esta é apenas a primeira versão. Faremos sucessivas melhorias até ele se tornar uma ferramenta que possa ser usada por algum administrador de redes.

sexta-feira, 21 de agosto de 2009

Transformando imagem em HTML

Recentemente minha esposa perguntou como transformar imagens em html, para postar imagens em blogs e talz.

Uma rápida pesquisa no google levou a conclusão de que a maioria deles não faz muito bem o que se presta a fazer. Talvez uma busca mais aprofundada me levasse a um belo programinha open-source, mas eu desisti de procurar.

A principio eu disse simplesmente que não dá, tem que colocar a imagem em algum lugar na web, um fotolog, drop box ou coisa parecida, e depois adicionar uma tag img que faça referência a ela.

Mas como todo programador adora desafios, ta aí, resultado de 5 min de código e do nosso .net framework.

Em breve eu posto o código fonte :) mas só se comentarem!

A imagem: Infelizmente não poderá ser postada aqui no blogspot porque todos os pixeis ficam em cima de um só. Parece que aqui não funciona direito o "position".

quinta-feira, 6 de agosto de 2009

Criando uma galeria de imagens em javascript




Isso é tanto um tutorial como uma bibliotequinha de galeria open source. Acho que todos já precisaram fazer uma galeria de imagens para um site, fosse apenas institucional, fosse e-commerce.

Existem 1001 maneiras de se fazer uma galeria dessas. Eu criei uma simples, sem usar muitos recursos do DOM. Criei onze exemplos, de "A" a "K" que mostram como fazer uma galeria de imagens. O primeiro exemplo mostra como fazer da maneira mais simples possível, e a complexidade vai aumentando conforme você vai chegando no exemplo K.

Todos os exemplos estão comentados detalhadamente. É bom abrir os exemplos apenas de dois em dois para comparar as diferenças entre eles. Você pode usar o winmerge :)

É importante ressaltar que para alguns esses exemplos podem parecer fracos, mas eles foram desenvolvidos visando quem é totalmente leigo em javascript.

Primeiro de tudo você precisa ter uma área com as imagens pequenas, que ao serem clicadas aparecerão em uma imagem maior. Na verdade todas as nossas imagens serão grandes, mas serão achatadas nas img pequenas. Para a criação de Thumbnails reais, deve-se usar script server-side como PHP ou asp.net.

Você pode baixar todos os exemplos no meu Sky Drive, ou no meu Drop Box.

Exemplo A:







<html>

 <head>

    <script>


     //funciona em todos os browsers

     //o que esta função faz: ela espera que você passe um numero inteiro positivo no lugar de xxx (seu unico argumento ou parametro)

     //usando document.getElementById('imagemzona') ele obtem o objeto da imagem maior e altera o seu src concatenando 3 partes:

     // 1) o caminho e primeira parte do nome

     // 2) a parte variavel (no caso o xxx)

     // 3) a extensao, que no caso é gif.

  

    

            function CarregaImagenzao(xxx)

            {

                document.getElementById('imagemzona').src = 'img/ronaldoimge'+xxx+'.gif';

            }

        

   </script>

  </head>

   <!-- é necessario, alem de dar um id para as imagens, definir seu evento onclick, chamando CarregaImagenzao(<passando aqui o umero da imagem>) -->

     <img src='img/001.gif' id='imge1' width=50 height=50 onclick='CarregaImagenzao(1);'/>

     <img src='img/002.gif' id='imge2' width=50 height=50 onclick='CarregaImagenzao(2);'/>

     <img src='img/003.gif' id='imge3' width=50 height=50 onclick='CarregaImagenzao(3);'/>
     <img  src='img/001.gif' id='imagemzona' width=300 height=300/>
     <br>
     <br>
     <pre>
            é necessario, alem de dar um id para as imagens, definir seu evento onclick, chamando CarregaImagenzao(&lt;&lt;passando aqui o umero da imagem&gt;&gt;) 
            //funciona em todos os browsers

            //o que esta função faz: ela espera que você passe um numero inteiro positivo no lugar de xxx (seu unico argumento ou parametro)

            //usando document.getElementById('imagemzona') ele obtem o objeto da imagem maior e altera o seu src concatenando 3 partes:

            // 1) o caminho e primeira parte do nome

            // 2) a parte variavel (no caso o xxx)

            // 3) a extensao, que no caso é gif.

    </pre>
 </body>
</html>
      






Os proprios arquivos HTML contém um tutorialzinho, como este:

é necessario, alem de dar um id para as imagens, definir seu evento onclick, chamando CarregaImagenzao(<<passando aqui o umero da imagem>>)

//funciona em todos os browsers

//o que esta função faz: ela espera que você passe um numero inteiro positivo no lugar de xxx (seu unico argumento ou parametro)

//usando document.getElementById('imagemzona') ele obtem o objeto da imagem maior e altera o seu src Concatenando 3 partes:

// 1) o caminho e primeira parte do nome

// 2) a parte variavel (no caso o xxx)

// 3) a extensao, que no caso é gif.

Por isso não irei detalhar cada um dos arquivos, apenas o último, porque é uma biblioteca de geração de galeria completa.

A última galeria é um arquivo .js. Para usá-la é simples, basta entender como funciona a estrutura da página de galeria:

Eu tenho duas pastas de imagens, a pasta "IMG" e a pasta "Outras". Na pasta img ficarão as imagens da galeria, e na outras ficarão as outras imagens do site que não terão evento, nem ampliação nem nada. Na página html há um img com o id='imagemzona' e a classe = 'imggrande', uma div com o id='divgaleria' que será o lugar onde ficarão os thumbnais.

Tem também um arquivo css simples com as classes 'imgpequena' e 'imggrande', e o arquivo .js referido que faz a coisa toda acontecer. Na minha página html eu referencio/importo/chamo esses 2 arquivos.

Para funcionar você tem que basicamente colocar as imagens na pasta img e o "Inicializa();" ou o "InicializaTempo();"no evento onload.

Ainda não está 100%, faltam umas coisas, como por exemplo identificar o browser do cara, se é IE ou FF e qual a versão, mas já serve. Abra os exemplos desde o A até o K e veja os comentários das funções e as páginas HTML de teste.

Nas três ultimas versões existem alguns parâmetros/variáveis para setar no javascript, e a ultima de todas, a versão "K" é a mais completa de todas. A Versão "K" reune as fuincionalidades de carga automática de imagens da versão H com a carga "manual" através de tags html das versões anteriores. Abaixo você confere a lista de parâmetros da versão K:

var CARREGA_IMG_AUTOMATICA = true; //sete este parâmetro, que ativa temporizador para true para, alem das imagens estáticas ele carregar as dinâmicas.

var QTDE_MAXIMA_IMAGENS = 20; //quantidade maxima de imagens da galeria

var Extencoes = new Array(".gif",".jpg",".png", ".bmp"); //extensões ou sufixos validos

var IMAGENS = "img/"; //diretorio de imagens

var ID_GALERIA = "divgaleria"; //id da div que vai conter os thumbnais da galeria

var ID_IMAGEMGRANDE = "imagemzona"; //id da imagem grande a ser demonstrada

var CLASSE_IMAGEMPEQUENA = "imgPequena"; //classe da imagem pequena

var CARACTER_ESQUERDA = "0"; //caracter a ser preenchido a esquerda no nome das imagens usando padleft

var TAMANHO_NOME = 3; //tamanho do nome da imagem sem caminho e sem extencao: exemplo 005.jpg o tamanho é 3

var DEBUG_MODE = false; //setar para true quando quiser visualizar as mensagens de erro

Experimente usar essa galeria em conjunto com asp, asp.net, php ou qualquer linguagem dinâmicaserver-side. Assim, até mesmo as imagens estaticas podem ser dinamicas via código html dinamico gerado do lado do servidor. Sendo a variavel QTDE_MAXIMA_IMAGENS menor e a variavel CARREGA_IMG_AUTOMATICA = false o site carrega bem mais rapido pois o loop de imagens a ser carregado é menor, ou no caso de CARREGA_IMG_AUTOMATICA = false ele nem chega a ser repetido indefinidamente pelo temporizador. Você também pode implementar a carga de todas as imagens pequenase grandes em divs invisíveis que vão aparecendo e desaparecendo via javascript, conforme a thumbnail que o usuário clica. Existem milhares de possibilidades/combinações diferentes.



Para um próximo release implementaremos a navegação com as setas do teclado e a identificação do browser do usuário.

É isso aí, espero que seja útil para designers que não tem familiaridade com o javascript.








Console.Writeline(@"Have Fun \(^^)/");

terça-feira, 28 de julho de 2009

Integer overflow no delphi 7

Dica sobre diferenças entre a sintaxe do delphi 2009 e do delphi 7 para se trabalhar com numeros negativos.

Isso soluciona o problema do integer overflow

http://www.devmedia.com.br/articles/viewcomp.asp?comp=13695

terça-feira, 21 de julho de 2009

Até que ponto os softwares modernos necessitam de hardware?

Isso é apenas uma coisinha boba, mas fundamenta meu argumento:
Sempre achei que os softwares modernos estão ficando cada vez mais exagerados no que eles exigem de hardware, e acredito que é porque estão ficando cada vez mais mal-feitos.

Acredito que programadores sem um conhecimento técnico muito grande, iniciantes ou medianos podem tornar um programa mais lento e exigente a medida que ele faz mal uso do processador e da memória.
Para exemplificar isso criei um cenário onde poderíamos codificar um programinha.
Se eu tenho uma função que subtrai um valor de um determinado montante, mas o resultado não pode ser negativo, porque essa função alimentará uma outra que aceita como entrada apenas números naturais não negativos. Caso o valor seja maior que o montante a função deve retornar zero.
Imagine uma operadora de celular pré-pago. Ela deve cortar a ligação do usuário quando os créditos chegam a zero, e impedir que faça novas ligações, mas jamais permitir que os créditos do cliente fiquem negativos. Mesmo que o cliente tenha suponhamos 50 centavos e a ligação que ele fará custe 55, mesmo que a operadora resolva deixar o usuário completar a ligação, arredondando para menos e arcando com o onus de 5 centavos, o cliente nunca deverá ficar com saldo negativo (pode até não ser assim, mas estamos impondo isso como premissa).
Se o cliente tem um saldo de 50 e é debitado 55, o saldo deve ser 0. Todo saldo negativo deve ser 0.
Consideraremos apenas a função de débito, mas ela não deve nem ser executada caso o cliente não disponha realmente dos meios para pagar o serviço. Por exemplo se numa verificação de saldo descobre-se que o cliente tem 20 centavos e a ligação é 50, simplesmente ele não fará a ligação.
O mesmo vale para sites onde o conteudo visualizado é pré-pago através de créditos. Imagine que o cliente compra 50 creditos, usa um, se arrepende e pede o dinheiro de volta. Você deve extornar o dinheiro do cliente e zerar o seu saldo de créditos, debitando 50 (o que ele comprou) dos 49 (o que ele tem), porém sem deixa-lo com saldo negativo -1. Ele não irá gostar de, caso um dia compre créditos de novo, comprar 50 e visualizar 49, como se 1 tivesse sumido.
Veja as várias formas de se fazer isso:



//desperdiçando memória com variáveis desnecessárias:
function debita1(montante,num: integer): integer;
var temp: integer;
begin
 temp := montante-num;
 if temp < 0 then
  result := 0
 else
  result := temp;
end;

//desperdiçando processamento
function debita2(montante,num: integer): integer;
begin
 if montante-num < 0 then
  result := 0
 else
  result := montante-num;
end;

//usando um if
function debita3(montante,num: integer): integer;
begin
 if num > montante then
  result := 0
 else
  result := montante-num;
end;

//uma maneira matemática e elegante, arregaçando o processador
function debita4(montante,num: integer): integer;
begin
 result := (montante-num + trunc(sqrt(sqr(montante-num)))) div 2;
end;


//método "me acho o bom mas sou um mané"
function debita5(montante,num: integer): integer;
asm
  sub eax, edx
  jns @@final
  and eax, 0
  @@final:
end;




A função debita1 claramente está usando uma variável temporária desnecessária, uma vez que em certas condições o cálculo não será efetuado,


a função debita2 economiza memoria em relação a debita1, mas executa o cálculo duas vezes, uma no if.

a função debita3 seria a mais performática e correta.

a função debita4 parece bonita, usa a matemática, com raiz quadrada do quadrado de um número, para tirar modulo, a formula ((m-d)+|m-d|)/2, não tem nenhum if, mas é a pior de todas. ela usa os operadores sqr e sqrt, uma vez cada um, que são operadores para se trabalhar com ponto flutuante. O todo desta função, inclusive as funções sqrt e sqr, acabam gerando mais instruções de máquina do que as precedentes.

A função debita5 foi o resultado de várias tentativas de fazer uma função mais performática que a debita3 em assembly. Não consegui. Mesmo para um loop de cem bilhões de vezes as funções debita3 e debita5 têm performances semelhantes.

Se alguem tiver uma sugestão de uma função mais performática que a debita5 eu agradeço!

Lógico que nem sempre é assim. As vezes uma função com operações matemáticas é mais rápida do que um complexo labirinto de if's.
Num outro exemplo, se seus números de ponto flutuante não tem mais de 2 casas depois da vírgula, pode-se evitar se trabalhar com números decimais, que são mais lentos, e multiplicar todas as parcelas por 100, dividindo-as por 100 depois. Isso num loop muito grande economizaria bastante tempo do processador.
Parece besteira minha, mas cada ano que passa os softwares estão ficando mais exigentes em termos de hardware, para fazer as tarefas cada vez mais triviais. Um messenger moderno, que tem a função apenas de chat com outros messengers, não funciona num 486 ou pentium 100 por exemplo.
A maioria das linguagens gerenciadas exige que você tenha 1 gb de memória para executar um hello world.
Acredito que grande parte desse desperdício pode ser atribuido a desatenção dos programadores, e uma parte menor a burrice mesmo.

Só que considerando software cada vez mais exigente. Hardware cada vez mais exigindo energia (uma simples placa pci express off board te obriga a ter uma fonte de 450 watts reais no mínimo), cada vez mais computadores velhos sendo jogados no lixo, com seus chips de silício, que é um veneno para a natureza, não deveríamos nós tentar o máximo possível fazer um código "econômico"?

Eu tenho tentado, logico, à medida que meus conhecimentos permitirem.

segunda-feira, 6 de julho de 2009

não consegue instalar o ie7 de jeito nenhum?

Como desenvolvedor web preciso instalar no meu computador vários browsers, varias versões do firefox e do IE.

Recentemente tive um problema para instalar o IE7 e IE8.

Simplesmente dava a mensagem dizendo que o programa não foi/não pôde ser instalado e interrompia a instalação, criando na área de trabalho um link para o suporte microsoft.

Alguma coisa errada com meu registro. Não corri muito atrás para saber profundamente o que era, afinal só o registro do windows é assunto para um livro.

Simplesmente fucei na net e achei uns comandos.

Se você já disse: "não consigo instalar o IE7 de jeito nenhum" ou "não consigo instalar o IE8 de jeito nenhum", esses comandos podem te ajudar:

no iniciar --> executar digite o comando abaixo:
secedit /configure /cfg %windir%\repair\secsetup.inf /db secsetup.sdb /verbose

se não der certo, procure por essa chave de registro no regedit, de um clique de direita e na opções permissões, de permissão a si mesmo ou ao usuário que está tentando instalar o ie7 ou ie8.

HKCR\Interface\{34A715A0-6587-11D0-924A-0020AFC7AC4D}

Agora algumas dicas para browsers.
para testar com todas as versões do IE ao mesmo tempo:
MultipleIE - http://tredosoft.com/Multiple_IE - instala varias versões do ie na sua máquina
IETester - http://www.my-debugbar.com/wiki/IETester/HomePage - cria uma aba para cada versão do ie.

Para testar com todas as versões de firefox use as versões portable novas e antigas:
3.5 - http://sourceforge.net/projects/portableapps/files/Mozilla%20Firefox,%20Portable%20Ed./FirefoxPortable_3.5_English.paf.exe
3.0 - http://sourceforge.net/projects/portableapps/files/Mozilla%20Firefox,%20Portable%20Ed./FirefoxPortable_3.0.11_English.paf.exe
2.0 - https://sourceforge.net/projects/portableapps/files/Mozilla%20Firefox,%20Portable%20Ed./Firefox_Portable_2.0.0.14_de.paf.exe
1.5 - http://sourceforge.net/projects/portablefirefox/files/Mozilla%20Firefox,%20Portable%20Ed./Firefox_Portable_1.5.0.10_en-us.paf.exe
1.0 - http://sourceforge.net/projects/portablefirefox/files/Mozilla%20Firefox,%20Portable%20Ed./Firefox_Portable_1.0.8_en-us.exe

Para mais informações procure no sourceforge.


Falando de sourceforge, ele está de cara nova, e muito bonito.
www.sourceforge.net

experimente os browsers chrome, muito rapido: http://www.google.com/chrome
e o kmeleon, um browser baseado no firefox muito levinho: http://kmeleon.sourceforge.net/

té +

segunda-feira, 29 de junho de 2009

Softwares Open Source que merecem um donativo

Eu gosto de software open-source. Mais ainda se for software open-source para windows.
(Aguardando xingamentos e profanidades ...)
Calma, pessoal, não me xinguem ainda. Eu amo o linux, apenas ainda não me sinto produtivo o suficiente com ele. Alem disso só posso usar o linux em casa, no trabalho é o velho windão.
Existem muitas maneiras de se manter um software open-source:

  • - Totalmente através de colaborações voluntárias de hobbistas: nesse caso o software é totalmente mantido por pessoas e não por organizações.
  • - Mantido por uma organização sem fins licrativos, ong, instituição ou ong
  • - Mantido por uma empresa, como opção aberta e de baixo custo de um outro produto proprietário.
  • - Mantido por uma empresa que vive de serviços.
  • - Mantido por uma empresa que USA o software, então precisa redistribuí-lo
  • - Também por empresa, quando a empresa patrocina ou apoia de alguma maneira.
  • - Mantido por um consórcio, grupo ou coisa do gênero de empresas que entram em acordo para convencionar padrões, modelos, compatibilidades etc.
  • - Qualquer misto das opções acima.

Muitos desses softwares precisam de donativos para continuar mantendo o ritmo de desenvolvedores totalmente voluntários em full-time.
Não é só usar, além de divulgar, testar, documentar e ajudar a resolver bugs, os softwares precisam de dinheiro, principalmente os que não tem fundação, apoio ou patrocinadores.
Já vi muitos softwares desse gênero morrerem por falta de apoio. Eu gostava pra caramba do Kurumin, mas, infelizmente, acabou.
Abaixo vai uma lista de softwares que merecem um donativo em $$$, para continuarem se mantendo. Alguns nem precisam de donativo, mas merecem consideração.

  1. Browser Firefox - http://br.mozdev.org/
  2. Banco de dados Firebird - http://www.firebirdsql.org/
  3. Computação nas nuvens? Experimente o sistema operacional online EyeOs - http://eyeos.org/
  4. Sistema operacional open-source compatível com o windows - http://www.reactos.org/pt/index.html - Esse é uma jóia!!!
  5. Ubuntu - sem comentários - http://www.ubuntu-br.org/
  6. E-commerce magento - http://www.magentocommerce.com/download/noregister - esse cara não precisa de donativo porque já tem uma versão comercial, mas merece consideração
  7. #Develop, O Visual Studio Livre - http://www.icsharpcode.net/OpenSource/SD/
  8. Blender - http://www.blender.org/
  9. Trocentas linguagens, bibliotecas e frameworks na web
  10. Lazarus e freepascal, não podemos esquecer deles! - http://www.lazarus.freepascal.org/
  11. Projeto JEDI, para quem gosta de delphi e c++ builder, como eu! - http://www.delphi-jedi.org/
  12. Projeto Infra (Integrated Frameworks) - Promete ser o melhor framework OO para Delphi! - http://code.google.com/p/infra/
  13. Dance Dance Revolution de gratis! é o step mania, demais cara! - http://www.stepmania.com/
  14. Guitar Hero de gratis! é o frets on fire - http://fretsonfire.sourceforge.net/
  15. O maravilhoso notepad++ - http://notepad-plus.sourceforge.net/br/site.htm
  16. Já vi vários editores de UML livres, mas o Frame UML é rapido, facil, bonito e atendeu minhas necessidades, ponto pra ele! - http://sourceforge.net/projects/frameuml/
  17. NetBeans - Eu sei o quanto é bom! - http://www.netbeans.org/

Esqueci de algum? Bom, ajude a aumentar essa lista. Se o software livre for seu, pode fazer Jabá a vontade :)


Falando de software livre, gostaria de mencionar o pobre-source. É uma classe de software livre muito interessante. São softwares de um programador só.
O criador geralmente é um programador que ama o que faz e não ganha o que merece, então, como hobby ou freela, cria um software que acaba ficando muito bom.
De repente o cara resolve abrir o código do programa e jogar no sourceforge ou por aí na net na esperança de ser notado e contratado por uma grande empresa do ramo.
Se o software for muito bom, pelo menos famoso ele vai ficar.

Tem muito software livre ruinzinho ou medíocre mesmo por aí, mas eu só posso imaginar que por falta de tempo ou dinheiro do(s) programador(es) o software nasceu e morreu muito rápido.

Bom, é isso, divulquem os softwares livres que gostam e me ajudem a aumentar essa lista ^^

domingo, 7 de junho de 2009

Destacar o Edit em foco: Mesma classe em 4 linguagens!


  Sabe quando você tem varios Edits (ou textbox) num form, quer destacar com uma determinada cor
quando eles ganharem o foco mas todos eles já tem
eventos e você não quer sobrescrever, substituir e
nem mecher nos eventos deles? Tambem não quer escrever o
codigo pra mudar de cor no proprio evento, porque são varios
edits e você quer reaproveitamento de código e o
minimo possivel de retrabalho?


  no C# isso é facil porque
você pode concatenar eventos, colocando facilmente dois
metodos para um mesmo evento. No javascript tambem dá para
você chamar dois ou mais metodos por evento. Mas e no C++,
delphi e Lazarus?


  OBS.: Coloquei delphi e lazarus como
duas "linguagens" diferentes porque apesar de serem praticamente
iguais, no lazarus, para se trabalhar com variaveis de
métodos de objetos e atribuir metodos à variaveis
você precisa obrigatoriamente do operador de
endereço "@". No delphi tambem era assim antigamente, mas
não sei em que versão que isso mudou.


  Com estas classes abaixo você
pode simplesmente criar um objeto, passando a form, a cor quando entra
e a cor quando "passa o mouse" como parametros que todos os Edits (ou
Textboxes) manterão os eventos originais.


  A primeira classe é
simplesmente um container de eventos (esta é apenas um
conteiner de cores no
codigo em C#, uma vez que é desnecessario que ela armazene
os eventos), a outra classe
é uma lista desses containers.


  A principio o codigo desta classe
trabalha somente com   TEdit. Mas usando bem a RTTI,
ispecionando por nomes e valores de propriedades, usando os ancestrais
em comum, uma dose de if's e criatividade você pode adaptar
para que funcione com todos os componentes.


  Num mesmo projeto eu apresento a classe
e a maneira de usar. Em breve postarei um componente para delphi feito
com esse conceito.



  Como isso é só uma
demonstração, eu  não estou
criando os metodos Acessores Get e Set para minhas propriedades. Estou
escrevendo direto no campo privado. Não faça isso
porque é muito feio, viola o encapsulamento e quem faz isso
não vai pro céu :) .



 Primeiro C++ builder:



Cabeçalhos e interfaces das
classes  (arquivo .h)



class TEventContainer: public TObject
{
    private:
       
 TNotifyEvent FOnEnter;
       
 TNotifyEvent FOnExit;
       
 TColor FCorOriginal;
    __published:
       
__property TNotifyEvent OnEnter = {read=FOnEnter, write=FOnEnter};
       
__property TNotifyEvent OnExit = {read=FOnExit, write=FOnExit};
       
__property TColor CorOriginal = {read = FCorOriginal, write =
FCorOriginal};

        
};

class TMudaCor: public TObject
{
    private:
        TForm
*FForm;
        TColor
FCorEntra;
       
TStringList *FlistaEvt;
    public:
       
__fastcall virtual TMudaCor(TForm *frm, TColor corentra);
       
__fastcall virtual ~TMudaCor(void);
        void
__fastcall DoEnter(TObject *sender);
        void
__fastcall  DoExit(TObject *sender);
};

class TForm1 : public TForm
{
__published:    // IDE-managed Components
    TEdit *Edit1;
    TEdit *Edit2;
    TEdit *Edit3;
    TButton *Button1;
    TButton *Button2;
    TLabel *Label1;
    void __fastcall Edit1Enter(TObject
*Sender);
    void __fastcall Edit1Exit(TObject
*Sender);
    void __fastcall Edit2Enter(TObject
*Sender);
    void __fastcall Edit2Exit(TObject
*Sender);
    void __fastcall FormCreate(TObject
*Sender);
    void __fastcall FormDestroy(TObject
*Sender);
private:    // User declarations
    TMudaCor *mudacor;
public:        //
User declarations
    __fastcall TForm1(TComponent* Owner);
};



 

 A implementação
(arquivo cpp)


//--------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//--------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)
{
}
//--------------------------------------------------------------
void __fastcall TForm1::Edit1Enter(TObject *Sender)
{
    Label1->Caption = "Entrou no edit
1";    
}
//-------------------------------------------------------------
void __fastcall TForm1::Edit1Exit(TObject *Sender)
{
    Label1->Caption = "Saiu do edit
1";    
}
//-------------------------------------------------------------
void __fastcall TForm1::Edit2Enter(TObject *Sender)
{
    Label1->Caption = "Entrou no edit
2";    
}
//-------------------------------------------------------------
void __fastcall TForm1::Edit2Exit(TObject *Sender)
{
    Label1->Caption = "saiu do edit
2";
}
//-------------------------------------------------------------


__fastcall TMudaCor::TMudaCor(TForm *frm, TColor corentra)
{
    int i;
    TEventContainer *evtc;

    FlistaEvt = new TStringList();
    FlistaEvt->Sorted = true;
    TEdit *ed;

    FForm = frm;
    FCorEntra=corentra;

  for (i=0; i<FForm->ComponentCount;i++)
  {

       if (
CompareStr(FForm->Components[i]->ClassName(),
"TEdit")   == 0 )
       {
       
    evtc = new TEventContainer();
       
    ed = (TEdit *)
FForm->Components[i];
       
    evtc->OnEnter =
ed->OnEnter;
       
    evtc->OnExit = ed->OnExit;
       
    evtc->CorOriginal =
ed->Color;

       
   
FlistaEvt->AddObject(ed->Name, evtc);

       
    ed->OnEnter=  DoEnter;
       
    ed->OnExit= DoExit;
       };
  };

  FlistaEvt->Sort();
}

__fastcall TMudaCor::~TMudaCor(void)
{
    int i;
     for (i = 0 ; i <
FlistaEvt->Count ; i++)
       
 if (FlistaEvt->Objects[i] != NULL)
       
   
FlistaEvt->Objects[i]->Free();

    FlistaEvt->Free();

}




void __fastcall  TMudaCor::DoEnter(TObject *Sender)
{
    TEventContainer *evtc;
    int idx;

     if
(CompareStr(Sender->ClassName(), "TEdit") == 0)
     {
       
    ((TEdit *)Sender)->Color =
FCorEntra;
     }

     idx =
FlistaEvt->IndexOf(((TEdit *)Sender)->Name);
     if(idx > -1)
     {
       
  if (FlistaEvt->Objects[idx] != NULL)
       
  {
       
     evtc= (TEventContainer
*)(FlistaEvt->Objects[idx]);
       
  }
       
  if ((evtc != NULL ) && (
evtc->OnEnter != NULL)) {
       
     evtc->OnEnter(Sender);
       
  }
     }
}

void __fastcall  TMudaCor::DoExit(TObject *Sender)
{
    TEventContainer *evtc;
    int idx;

     idx =
FlistaEvt->IndexOf(((TEdit *)Sender)->Name);
     if(idx > -1)
     {
       
  if (FlistaEvt->Objects[idx] != NULL)
       
  {
       
     evtc= (TEventContainer
*)(FlistaEvt->Objects[idx]);
       
  }

       
  if (evtc != NULL )
       
  {
       
        if
(CompareStr(Sender->ClassName(), "TEdit") == 0)
       
        {
       
       
    ((TEdit *)Sender)->Color =
evtc->CorOriginal;
       
        }

       
        if (
evtc->OnExit != NULL)
       
        {
       
       
    evtc->OnExit(Sender);
       
        }
       
  }
     }
}
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    mudacor = new TMudaCor(this,
clYellow);    
}
//------------------------------------------------------------

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
   
mudacor->Free();    
}
//------------------------------------------------------------






O dfm:



object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 293
  ClientWidth = 426
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 24
    Top = 8
    Width = 31
    Height = 13
    Caption = 'Label1'
  end
  object Edit1: TEdit
    Left = 24
    Top = 32
    Width = 121
    Height = 21
    Color = clMoneyGreen
    TabOrder = 0
    Text = 'Edit1'
    OnEnter = Edit1Enter
    OnExit = Edit1Exit
  end
  object Edit2: TEdit
    Left = 24
    Top = 72
    Width = 121
    Height = 21
    Color = clSkyBlue
    TabOrder = 1
    Text = 'Edit2'
    OnEnter = Edit2Enter
    OnExit = Edit2Exit
  end
  object Edit3: TEdit
    Left = 24
    Top = 120
    Width = 121
    Height = 21
    Color = clSilver
    TabOrder = 2
    Text = 'Edit3'
  end
  object Button1: TButton
    Left = 176
    Top = 30
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 3
  end
  object Button2: TButton
    Left = 176
    Top = 70
    Width = 75
    Height = 25
    Caption = 'Button2'
    TabOrder = 4
  end
end





em
C#:


using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace MudaCorCSharp
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    /// 



    public class Form1 :
System.Windows.Forms.Form
    {
        private
System.Windows.Forms.TextBox textBox1;
        private
System.Windows.Forms.TextBox textBox2;
        private
System.Windows.Forms.TextBox textBox3;
        private
System.Windows.Forms.Button button1;
        private
System.Windows.Forms.Label label1;
        private
System.Windows.Forms.TextBox a3;
        private
System.Windows.Forms.TextBox a2;
        private
System.Windows.Forms.TextBox a1;
        ///
<summary>
        ///
Required designer variable.
        ///
</summary>
        private
System.ComponentModel.Container components = null;

        public
Form1()
        {
       
    //
       
    // Required for Windows Form Designer
support
       
    //
       
    InitializeComponent();

       
    //
       
    // TODO: Add any constructor code after
InitializeComponent call
       
    //
        }

        ///
<summary>
        /// Clean
up any resources being used.
        ///
</summary>
        protected
override void Dispose( bool disposing )
        {
       
    if( disposing )
       
    {
       
        if
(components != null) 
       
        {
       
       
    components.Dispose();
       
        }
       
    }
       
    base.Dispose( disposing );
        }

        #region
Windows Form Designer generated code
        ///
<summary>
        ///
Required method for Designer support - do not modify
        /// the
contents of this method with the code editor.
        ///
</summary>
        private
void InitializeComponent()
        {
       
    this.textBox1 = new
System.Windows.Forms.TextBox();
       
    this.textBox2 = new
System.Windows.Forms.TextBox();
       
    this.textBox3 = new
System.Windows.Forms.TextBox();
       
    this.button1 = new
System.Windows.Forms.Button();
       
    this.label1 = new
System.Windows.Forms.Label();
       
    this.a3 = new
System.Windows.Forms.TextBox();
       
    this.a2 = new
System.Windows.Forms.TextBox();
       
    this.a1 = new
System.Windows.Forms.TextBox();
       
    this.SuspendLayout();
       
    // 
       
    // textBox1
       
    // 
       
    this.textBox1.BackColor =
System.Drawing.Color.Gainsboro;
       
    this.textBox1.Location = new
System.Drawing.Point(16, 72);
       
    this.textBox1.Name = "textBox1";
       
    this.textBox1.TabIndex = 0;
       
    this.textBox1.Text = "textBox1";
       
    this.textBox1.MouseEnter += new
System.EventHandler(this.textBox1_MouseEnter);
       
    this.textBox1.Leave += new
System.EventHandler(this.textBox1_Leave);
       
    this.textBox1.MouseLeave += new
System.EventHandler(this.textBox1_MouseLeave);
       
    this.textBox1.Enter += new
System.EventHandler(this.textBox1_Enter);
       
    // 
       
    // textBox2
       
    // 
       
    this.textBox2.BackColor =
System.Drawing.Color.MistyRose;
       
    this.textBox2.Location = new
System.Drawing.Point(16, 104);
       
    this.textBox2.Name = "textBox2";
       
    this.textBox2.TabIndex = 1;
       
    this.textBox2.Text = "textBox2";
       
    this.textBox2.MouseEnter += new
System.EventHandler(this.textBox2_MouseEnter);
       
    this.textBox2.Leave += new
System.EventHandler(this.textBox2_Leave);
       
    this.textBox2.MouseLeave += new
System.EventHandler(this.textBox2_MouseLeave);
       
    this.textBox2.Enter += new
System.EventHandler(this.textBox2_Enter);
       
    // 
       
    // textBox3
       
    // 
       
    this.textBox3.BackColor =
System.Drawing.Color.PeachPuff;
       
    this.textBox3.Location = new
System.Drawing.Point(16, 136);
       
    this.textBox3.Name = "textBox3";
       
    this.textBox3.TabIndex = 2;
       
    this.textBox3.Text = "textBox3";
       
    // 
       
    // button1
       
    // 
       
    this.button1.Location = new
System.Drawing.Point(144, 24);
       
    this.button1.Name = "button1";
       
    this.button1.TabIndex = 3;
       
    this.button1.Text = "button1";
       
    this.button1.Click += new
System.EventHandler(this.button1_Click);
       
    // 
       
    // label1
       
    // 
       
    this.label1.Location = new
System.Drawing.Point(16, 16);
       
    this.label1.Name = "label1";
       
    this.label1.TabIndex = 4;
       
    this.label1.Text = "label1";
       
    // 
       
    // a3
       
    // 
       
    this.a3.BackColor =
System.Drawing.Color.PaleTurquoise;
       
    this.a3.Location = new
System.Drawing.Point(144, 136);
       
    this.a3.Name = "a3";
       
    this.a3.TabIndex = 7;
       
    this.a3.Text = "textBox4";
       
    // 
       
    // a2
       
    // 
       
    this.a2.BackColor =
System.Drawing.Color.PaleGreen;
       
    this.a2.Location = new
System.Drawing.Point(144, 104);
       
    this.a2.Name = "a2";
       
    this.a2.TabIndex = 6;
       
    this.a2.Text = "textBox5";
       
    // 
       
    // a1
       
    // 
       
    this.a1.BackColor =
System.Drawing.Color.LightGoldenrodYellow;
       
    this.a1.Location = new
System.Drawing.Point(144, 72);
       
    this.a1.Name = "a1";
       
    this.a1.TabIndex = 5;
       
    this.a1.Text = "textBox6";
       
    // 
       
    // Form1
       
    // 
       
    this.AutoScaleBaseSize = new
System.Drawing.Size(5, 13);
       
    this.ClientSize = new
System.Drawing.Size(292, 273);
       
    this.Controls.Add(this.a3);
       
    this.Controls.Add(this.a2);
       
    this.Controls.Add(this.a1);
       
    this.Controls.Add(this.label1);
       
    this.Controls.Add(this.button1);
       
    this.Controls.Add(this.textBox3);
       
    this.Controls.Add(this.textBox2);
       
    this.Controls.Add(this.textBox1);
       
    this.Name = "Form1";
       
    this.Text = "Form1";
       
    this.Load += new
System.EventHandler(this.Form1_Load);
       
    this.ResumeLayout(false);

        }
        #endregion

        ///
<summary>
        /// The
main entry point for the application.
        ///
</summary>
       
[STAThread]
        static
void Main() 
        {
       
    Application.Run(new Form1());
        }

        private
void textBox1_MouseEnter(object sender, System.EventArgs e)
        {
       
    label1.Text = "Mouse enter 1";
        }

        private
void textBox1_MouseLeave(object sender, System.EventArgs e)
        {
       
    label1.Text = "Mouse leave 1";
        }

        private
void textBox1_Enter(object sender, System.EventArgs e)
        {
       
    label1.Text = " enter 1";
        }

        private
void textBox1_Leave(object sender, System.EventArgs e)
        {
       
    label1.Text = "leave 1";
        }

        private
void textBox2_Enter(object sender, System.EventArgs e)
        {
       
    label1.Text = " enter 2";
        }

        private
void textBox2_Leave(object sender, System.EventArgs e)
        {
       
    label1.Text = "leave 2";
        }

        private
void textBox2_MouseEnter(object sender, System.EventArgs e)
        {
       
    label1.Text = "Mouse enter 2";
        }

        private
void textBox2_MouseLeave(object sender, System.EventArgs e)
        {
       
    label1.Text = "Mouse leave 2";
        }

        private
void button1_Click(object sender, System.EventArgs e)
        {

        }

        private
void Form1_Load(object sender, System.EventArgs e)
        {
       
    TMudaCor mudacor = new TMudaCor(this,
System.Drawing.Color.Yellow, System.Drawing.Color.Orange);
        }
    }


    public class TColorContainer
    {
        private
System.Drawing.Color FCorOriginal;

        public
System.Drawing.Color CorOriginal {get{return FCorOriginal;}
set{FCorOriginal = value;}}
    }


    public class TMudaCor
    {
        private
System.Windows.Forms.Form FForm; 
        private
System.Drawing.Color FCorEntra;
        private
System.Drawing.Color FCorMouseEntra;
        //private
System.Collections.SortedList FlistaEvt;
        private
System.Collections.Hashtable FlistaEvt;

        public
TMudaCor(System.Windows.Forms.Form frm, System.Drawing.Color
corMouseEnter, System.Drawing.Color corEnter )
        {
       
    FForm = frm;
       
    //FlistaEvt = new SortedList();
       
    FlistaEvt = new Hashtable();
       
    FCorEntra = corEnter;
       
    FCorMouseEntra = corMouseEnter;
    
       
    for(int i=0; i <
FForm.Controls.Count; i++)
       
    {
       
        if
(FForm.Controls[i] is TextBox)
       
        {
       
       
    TColorContainer evtc = new
TColorContainer();
       
       
    evtc.CorOriginal = (FForm.Controls[i] as
TextBox).BackColor;
       
       
    FlistaEvt.Add(FForm.Controls[i].Name,
evtc);
       
       
    (FForm.Controls[i] as TextBox).Enter +=
new System.EventHandler( this.DoEnter);
       
       
    (FForm.Controls[i] as TextBox).Leave +=
new System.EventHandler(this.DoExit);
       
       
    (FForm.Controls[i] as
TextBox).MouseEnter += new System.EventHandler( this.DoMouseEnter);
       
       
    (FForm.Controls[i] as
TextBox).MouseLeave += new System.EventHandler(this.DoMouseLeave);

       
        }
       
    }
        }


        public
void DoEnter(object sender, System.EventArgs e)
        {
       
    if(sender is TextBox)
       
    {
       
        (sender
as TextBox).BackColor = FCorEntra;
       
    }
        }
        public
void DoExit(object sender, System.EventArgs e)
        {
       
    if(sender is TextBox)
       
    {
       
       
TColorContainer evtc = (TColorContainer) FlistaEvt[(sender as
TextBox).Name];
       
        if(evtc
!= null)
       
        {
       
       
    (sender as TextBox).BackColor =
evtc.CorOriginal;
       
        }
       
    }
        }

        public
void DoMouseEnter(object sender, System.EventArgs e)
        {
       
    if(sender is TextBox)
       
    {
       
        //sair
sem fazer nada se tiver o foco
       
        if
((sender as TextBox).Focused) return;

       
        (sender
as TextBox).BackColor = FCorMouseEntra;
       
    }
        }
        public
void DoMouseLeave(object sender, System.EventArgs e)
        {
       
    if(sender is TextBox)
       
    {
       
        //sair
sem fazer nada se tiver o foco
       
        if
((sender as TextBox).Focused) return;

       
       
TColorContainer evtc = (TColorContainer) FlistaEvt[(sender as
TextBox).Name];
       
        if(evtc
!= null)
       
        {
       
       
    (sender as TextBox).BackColor =
evtc.CorOriginal;
       
        }
       
    }
        }

    }
}



Agora
a mesma coisa em delphi:

o Pas:


unit
Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms,
  Dialogs, StdCtrls;


type



  TEventContainer = class
  private
        
FOnEnter: TNotifyEvent;
        
FOnExit: TNotifyEvent;
        
FCorOriginal: TColor;
  public
       
property OnEnter: TNotifyEvent read FOnEnter write FOnEnter;
       
property OnExit: TNotifyEvent read FOnExit write FOnExit;
       
property CorOriginal: TColor read FCorOriginal write FCorOriginal;
  end;

  TMudaCor = class
  private
     FForm: TForm;
     FCorEntra: TColor;
     FlistaEvt: TStringList;

  public
       
constructor Create(frm: Tform; corentra:TColor); reintroduce;
       
destructor Destroy; override;
       
procedure DoEnter(sender: tobject);
       
procedure DoExit(sender: tobject);
  end;


  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    aEdit4: TEdit;
    aEdit5: TEdit;
    aEdit6: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    procedure aEdit6Enter(Sender: TObject);
    procedure aEdit6Exit(Sender: TObject);
    procedure Edit1Enter(Sender: TObject);
    procedure Edit1Exit(Sender: TObject);
    procedure Edit2Enter(Sender: TObject);
    procedure Edit2Exit(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { private declarations }
    mudador: TMudaCor;
  public
    { public declarations }
  end; 

  { TMudaCor }





var
  Form1: TForm1; 

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.Edit1Enter(Sender: TObject);
begin
     Label1.Caption:='entrou no
edit 1';
end;



procedure TForm1.aEdit6Enter(Sender: TObject);
begin
     Label1.Caption:='entrou no
edit 6';
end;

procedure TForm1.aEdit6Exit(Sender: TObject);
begin
     Label1.Caption:='saiu do edit
6';
end;

procedure TForm1.Edit1Exit(Sender: TObject);
begin
  Label1.Caption:='saiu do edit 1';
end;



procedure TForm1.Edit2Enter(Sender: TObject);
begin
  Label1.Caption:='entrou no edit 2';
end;

procedure TForm1.Edit2Exit(Sender: TObject);
begin
  Label1.Caption:='saiu do edit 2';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   mudador := TMudaCor.Create(self, clYellow);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  mudador.free;
end;

{ TMudaCor }

constructor TMudaCor.Create(frm: Tform; corentra:TColor);
var i: integer;
    evtc: TEventContainer;
begin
  inherited create;
  FlistaEvt := TStringList.Create;
  FlistaEvt.Sorted:=true;
  FForm := frm;
  FCorEntra:=corentra;

  for i := 0 to FForm.ComponentCount-1 do
  begin
       if
(FForm.Components[i] is TEdit) then
       begin
           
evtc := TEventContainer.Create;
           
evtc.OnEnter := (FForm.Components[i] as TEdit).OnEnter;
           
evtc.OnExit := (FForm.Components[i] as TEdit).OnExit;
           
evtc.CorOriginal := (FForm.Components[i] as TEdit).Color;

           
FlistaEvt.AddObject((FForm.Components[i] as TEdit).Name, evtc);

           
(FForm.Components[i] as TEdit).OnEnter:=  DoEnter;
           
(FForm.Components[i] as TEdit).OnExit:= DoExit;
       end;
  end;

  FlistaEvt.Sort;

end;

destructor TMudaCor.Destroy;
var i: integer;
begin

     for i := 0 to FlistaEvt.Count
-1 do
        
if FlistaEvt.Objects[i] <> nil then
           
FlistaEvt.Objects[i].Free;

     FlistaEvt.Free;
     inherited Destroy;

end;

procedure TMudaCor.DoEnter(sender: tobject);
var evtc: TEventContainer;
    idx: integer;
begin
     if(sender is TEdit) then
              
(sender as TEdit).Color := FCorEntra;

     idx :=
FlistaEvt.IndexOf((sender as TEdit).Name);
     if(idx > -1) then
     begin
         
if (FlistaEvt.Objects[idx] <> nil) then
         
begin
            
evtc:= (FlistaEvt.Objects[idx] as TEventContainer);
         
end;
         
if ((evtc <> nil) and ( Assigned(evtc.OnEnter))) then
            
evtc.OnEnter(sender);
     end;
end;

procedure TMudaCor.DoExit(sender: tobject);
var evtc: TEventContainer;
    idx: integer;
begin


     idx :=
FlistaEvt.IndexOf((sender as TEdit).Name);
     if(idx > -1) then
     begin
         
if (FlistaEvt.Objects[idx] <> nil) then
         
begin
            
evtc:= (FlistaEvt.Objects[idx] as TEventContainer);
         
end;

         
if Assigned(evtc) then
         
begin
              
if (sender is TEdit) then
                 
(sender as TEdit).Color := evtc.CorOriginal;
              
if Assigned(evtc.OnExit)  then
                 
evtc.OnExit(sender);
         
end;
     end;
end;


end.


o DFM:



object Form1: TForm1
  Left = 359
  Top = 191
  Width = 350
  Height = 358
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = True
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 96
    Top = 16
    Width = 32
    Height = 13
    Caption = 'Label1'
    Color = clBtnFace
    ParentColor = False
  end
  object Label2: TLabel
    Left = 8
    Top = 184
    Width = 249
    Height = 65
    Caption = 
      'Repare que o edit 3
n'#227'o tem evento no  onexit'#13#10'onenter, mas mesm' +
      'o assim a
mudan'#231'a de cor'#13#10'ocorre. Os outros edits, alem da mudan' +
      #231'a de
'#13#10'cor ele continua fazendo o evento de antes,'#13#10'que era mud'
+
      'ar o texto do
label1 para entrou, saiu etc'
    Color = clBtnFace
    ParentColor = False
  end
  object Edit1: TEdit
    Left = 24
    Top = 58
    Width = 80
    Height = 21
    Color = clSkyBlue
    TabOrder = 0
    Text = 'Edit1'
    OnEnter = Edit1Enter
    OnExit = Edit1Exit
  end
  object Edit2: TEdit
    Left = 24
    Top = 98
    Width = 80
    Height = 21
    Color = clMoneyGreen
    TabOrder = 1
    Text = 'Edit2'
    OnEnter = Edit2Enter
    OnExit = Edit2Exit
  end
  object Button1: TButton
    Left = 224
    Top = 56
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 2
  end
  object Button2: TButton
    Left = 224
    Top = 96
    Width = 75
    Height = 25
    Caption = 'Button2'
    TabOrder = 3
  end
  object Edit3: TEdit
    Left = 24
    Top = 136
    Width = 80
    Height = 21
    Color = clMedGray
    TabOrder = 4
    Text = 'Edit3'
  end
  object aEdit4: TEdit
    Left = 120
    Top = 58
    Width = 80
    Height = 21
    Color = clFuchsia
    TabOrder = 5
    Text = 'Edit1'
  end
  object aEdit5: TEdit
    Left = 120
    Top = 98
    Width = 80
    Height = 21
    Color = clAqua
    TabOrder = 6
    Text = 'Edit2'
  end
  object aEdit6: TEdit
    Left = 120
    Top = 136
    Width = 80
    Height = 21
    Color = clLime
    TabOrder = 7
    Text = 'Edit3'
    OnEnter = aEdit6Enter
    OnExit = aEdit6Exit
  end
end




A
mesma coisa em Lazarus:
o
Pas


unit Unit1; 

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls,
Graphics, Dialogs,
  StdCtrls;

type



  TEventContainer = class
  private
        
FOnEnter: TNotifyEvent;
        
FOnExit: TNotifyEvent;
        
FCorOriginal: TColor;
  public
       
property OnEnter: TNotifyEvent read FOnEnter write FOnEnter;
       
property OnExit: TNotifyEvent read FOnExit write FOnExit;
       
property CorOriginal: TColor read FCorOriginal write FCorOriginal;
  end;

  TMudaCor = class
  private
     FForm: TForm;
     FCorEntra: TColor;
     FlistaEvt: TStringList;

  public
       
constructor Create(frm: Tform; corentra:TColor); reintroduce;
       
destructor Destroy; override;
       
procedure DoEnter(sender: tobject);
       
procedure DoExit(sender: tobject);
  end;


  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    aEdit4: TEdit;
    aEdit5: TEdit;
    aEdit6: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    procedure aEdit6Enter(Sender: TObject);
    procedure aEdit6Exit(Sender: TObject);
    procedure Edit1Enter(Sender: TObject);
    procedure Edit1Exit(Sender: TObject);
    procedure Edit2Enter(Sender: TObject);
    procedure Edit2Exit(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { private declarations }
    mudador: TMudaCor;
  public
    { public declarations }
  end; 

  { TMudaCor }

var
  Form1: TForm1; 

implementation



{ TForm1 }

procedure TForm1.Edit1Enter(Sender: TObject);
begin
     Label1.Caption:='entrou no
edit 1';
end;



procedure TForm1.aEdit6Enter(Sender: TObject);
begin
     Label1.Caption:='entrou no
edit 6';
end;

procedure TForm1.aEdit6Exit(Sender: TObject);
begin
     Label1.Caption:='saiu do edit
6';
end;

procedure TForm1.Edit1Exit(Sender: TObject);
begin
  Label1.Caption:='saiu do edit 1';
end;



procedure TForm1.Edit2Enter(Sender: TObject);
begin
  Label1.Caption:='entrou no edit 2';
end;

procedure TForm1.Edit2Exit(Sender: TObject);
begin
  Label1.Caption:='saiu do edit 2';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   mudador := TMudaCor.Create(self, clYellow);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  mudador.free;
end;

{ TMudaCor }

constructor TMudaCor.Create(frm: Tform; corentra: TColor);
var i: integer;
    evtc: TEventContainer;
begin
  inherited create;
  FlistaEvt := TStringList.Create;
  FlistaEvt.Sorted:=true;
  FForm := frm;
  FCorEntra:=corentra;

  for i := 0 to FForm.ComponentCount-1 do
  begin
       if
(FForm.Components[i] is TEdit) then
       begin
           
evtc := TEventContainer.Create;
           
evtc.OnEnter := (FForm.Components[i] as TEdit).OnEnter;
           
evtc.OnExit := (FForm.Components[i] as TEdit).OnExit;
           
evtc.CorOriginal:=  (FForm.Components[i] as TEdit).Color;
           
FlistaEvt.AddObject((FForm.Components[i] as TEdit).Name, evtc);

           
(FForm.Components[i] as TEdit).OnEnter:=@DoEnter;
           
(FForm.Components[i] as TEdit).OnExit:=@DoExit;
       end;
  end;

  FlistaEvt.Sort;

end;

destructor TMudaCor.Destroy;
var i: integer;
begin

     for i := 0 to FlistaEvt.Count
-1 do
        
if FlistaEvt.Objects[i] <> nil then
           
FlistaEvt.Objects[i].Free;

     FlistaEvt.Free;
     inherited Destroy;

end;

procedure TMudaCor.DoEnter(sender: tobject);
var evtc: TEventContainer;
    idx: integer;
begin
     if(sender is TEdit) then
              
(sender as TEdit).Color := FCorEntra;

     idx :=
FlistaEvt.IndexOf((sender as TEdit).Name);
     if(idx > -1) then
     begin
         
if (FlistaEvt.Objects[idx] <> nil) then
         
begin
            
evtc:= (FlistaEvt.Objects[idx] as TEventContainer);
         
end;
         
if ((evtc <> nil) and (evtc.OnEnter <>
nil)) then
            
evtc.OnEnter(sender);
     end;
end;

procedure TMudaCor.DoExit(sender: tobject);
var evtc: TEventContainer;
    idx: integer;
begin

     idx :=
FlistaEvt.IndexOf((sender as TEdit).Name);
     if(idx > -1) then
     begin
         
if (FlistaEvt.Objects[idx] <> nil) then
         
begin
            
evtc:= (FlistaEvt.Objects[idx] as TEventContainer);
         
end;
         
if (evtc <> nil) then
         
begin
              
if (sender is TEdit) then
                 
(sender as TEdit).Color := evtc.CorOriginal;
              
if (evtc.OnExit <> nil)   then
                 
evtc.OnExit(sender);
         
end;
     end;
end;

initialization
  {$I unit1.lrs}

end.



o LFM


object
Form1: TForm1
  Left = 359
  Height = 331
  Top = 191
  Width = 342
  Caption = 'Form1'
  ClientHeight = 331
  ClientWidth = 342
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  ParentFont = False
  LCLVersion = '0.9.26'
  object Label1: TLabel
    Left = 96
    Height = 14
    Top = 16
    Width = 32
    Caption = 'Label1'
    ParentColor = False
  end
  object Label2: TLabel
    Left = 8
    Height = 66
    Top = 184
    Width = 259
    Caption = 'Repare que o edit 3
não tem evento no  onexit'#13#10'onenter, mas mesmo
assim a mudança de cor'#13#10'ocorre. Os outros edits, alem
da mudança de '#13#10'cor ele continua fazendo o evento de
antes,'#13#10'que era mudar o texto do label1 para entrou, saiu etc'
    ParentColor = False
  end
  object Edit1: TEdit
    Left = 24
    Height = 23
    Top = 58
    Width = 80
    Color = clSilver
    OnEnter = Edit1Enter
    OnExit = Edit1Exit
    TabOrder = 0
    Text = 'Edit1'
  end
  object Edit2: TEdit
    Left = 24
    Height = 23
    Top = 98
    Width = 80
    Color = clSkyBlue
    OnEnter = Edit2Enter
    OnExit = Edit2Exit
    TabOrder = 1
    Text = 'Edit2'
  end
  object Button1: TButton
    Left = 224
    Height = 25
    Top = 56
    Width = 75
    Caption = 'Button1'
    TabOrder = 2
  end
  object Button2: TButton
    Left = 224
    Height = 25
    Top = 96
    Width = 75
    Caption = 'Button2'
    TabOrder = 3
  end
  object Edit3: TEdit
    Left = 24
    Height = 23
    Top = 136
    Width = 80
    Color = clMoneyGreen
    TabOrder = 4
    Text = 'Edit3'
  end
  object aEdit4: TEdit
    Left = 120
    Height = 23
    Top = 58
    Width = 80
    Color = clFuchsia
    TabOrder = 5
    Text = 'Edit1'
  end
  object aEdit5: TEdit
    Left = 120
    Height = 23
    Top = 98
    Width = 80
    Color = clAqua
    TabOrder = 6
    Text = 'Edit2'
  end
  object aEdit6: TEdit
    Left = 120
    Height = 23
    Top = 136
    Width = 80
    Color = clLime
    OnEnter = aEdit6Enter
    OnExit = aEdit6Exit
    TabOrder = 7
    Text = 'Edit3'
  end
end



Espero que esse artigo seja util para quem precisar implementar algo
assim sem mecher no codigo já existente, ou para quem deseja
estudar as semelhanças e diferenças entre as varias
linguagens de programação.

baixe o conjunto de exemplos no meu sky drive: clicando aqui

Postagens populares

Marcadores

delphi (60) C# (31) poo (21) Lazarus (19) Site aos Pedaços (15) sql (13) Reflexões (10) .Net (9) Humor (9) javascript (9) ASp.Net (8) api (8) Básico (6) Programação (6) ms sql server (5) Web (4) banco de dados (4) HTML (3) PHP (3) Python (3) design patterns (3) jQuery (3) livros (3) metaprogramação (3) Ajax (2) Debug (2) Dicas Básicas Windows (2) Pascal (2) games (2) linguagem (2) música (2) singleton (2) tecnologia (2) Anime (1) Api do Windows (1) Assembly (1) Eventos (1) Experts (1) GNU (1) Inglês (1) JSON (1) SO (1) datas (1) developers (1) dicas (1) easter egg (1) firebird (1) interfaces (1) introspecção (1) memo (1) oracle (1) reflexão (1)