<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CEQHSX46eSp7ImA9WhRUF0g.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653</id><updated>2012-01-28T10:05:38.011-02:00</updated><category term="C#" /><category term="CAPICOM" /><category term="Notícias" /><category term="Script" /><category term="SQL" /><category term="Artigos" /><category term="Ferramentas" /><category term="Delphi" /><category term="HTML" /><category term="Componentes" /><category term="Conceitos" /><category term="XML" /><category term="Indy" /><category term="Threads" /><category term="Windows" /><category term="Registry" /><category term="C++ Builder" /><category term="Design Patterns" /><category term="ADO" /><category term=".NET" /><category term="Excel" /><title>Balaio Tecnológico</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://balaiotecnologico.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>230</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/BalaioTecnolgico" /><feedburner:info uri="balaiotecnolgico" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;A04BSHs7eyp7ImA9WhRUE04.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-1342484286110674330</id><published>2012-01-23T15:32:00.001-02:00</published><updated>2012-01-23T15:32:39.503-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-23T15:32:39.503-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="C++ Builder" /><title>Trabalhando com Ações em Delphi e C++ Builder</title><content type="html">As operações que um usuário pode executar em programas com interface visual podem estar disponíveis de diversas maneiras. As formas mais óbvias e mais utilizadas são os menus, barras de ferramentas, menus de contexto, botões espalhados pela interface e, mais recentemente, os &lt;a href="http://en.wikipedia.org/wiki/Ribbon_%28computing%29"&gt;ribbons&lt;/a&gt; introduzidos pela interface do &lt;a href="http://pt.wikipedia.org/wiki/Microsoft_Office"&gt;Microsoft Office&lt;/a&gt;. Com essa variedade de formas de se acessar uma operação, é bastante comum que esse acesso esteja disponível em mais de um lugar.&lt;br /&gt;
&lt;br /&gt;
Do ponto de vista do programador surge então uma questão: qual a melhor maneira de se gerenciar as operações em uma aplicação, notadamente aquelas que estarão acessíveis por mais de uma via ? A solução para quem desenvolve com Delphi ou C++ Builder é um componente que já existe há um bom tempo nesses ambientes, chamado &lt;a href="http://docwiki.embarcadero.com/VCL/en/ActnMan.TActionManager"&gt;TActionManager&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Como diz o nome, o objetivo do &lt;b&gt;TActionManager&lt;/b&gt; é gerenciar as operações que estarão disponíveis para o usuário em uma aplicação, centralizando a configuração básica de cada operação. O componente permite organizar as operações por afinidade (relativas a arquivo, edição, visualizar ou ajuda, por exemplo); informar textos e imagens descritivos da operação a fim de manter a uniformidade visual independente da forma de acesso escolhida; sinalizar se a operação está ativa ou mesmo visível.&lt;br /&gt;
&lt;br /&gt;
E como é que isso tudo se conecta ? Alimentar o &lt;b&gt;TActionManager&lt;/b&gt; com operações faz com que o &lt;a href="http://pt.wikipedia.org/wiki/Ambiente_de_Desenvolvimento_Integrado"&gt;IDE&lt;/a&gt; crie instâncias de um outro objeto, o &lt;a href="http://docwiki.embarcadero.com/VCL/en/ActnList.TAction"&gt;TAction&lt;/a&gt;. Cada &lt;b&gt;TAction&lt;/b&gt; corresponde a uma operação - ou ação - isolada, independente da interação necessária para ativá-la. Essa ação pode então ser associada à propriedade &lt;b&gt;Action&lt;/b&gt; existente em diversos componentes - itens de menu, botões, itens em barras de ferramenta, etc.&lt;br /&gt;
&lt;br /&gt;
Entretanto, certos componentes - como o &lt;a href="http://docwiki.embarcadero.com/VCL/en/ActnMenus.TActionMainMenuBar"&gt;TActionMainMenuBar&lt;/a&gt; e o &lt;a href="http://docwiki.embarcadero.com/VCL/en/Ribbon.TRibbon"&gt;TRibbon&lt;/a&gt; - são configurados diretamente com uma instância do &lt;b&gt;ActionManager&lt;/b&gt; e não com ações individuais.&lt;br /&gt;
&lt;br /&gt;
Para dar manutenção nas ações gerenciadas pelo &lt;b&gt;ActionManager&lt;/b&gt;, dê um duplo clique nele. Será exibida uma caixa de diálogo como a reproduzida abaixo, onde é possível criar novas ações, excluí-las e rearranjá-las. Selecionar uma ação fará com que o &lt;i&gt;Object Inspector&lt;/i&gt; apresente as propriedades relativas a ela.
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;width: 98%;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lgaf.webs.com/arqs/actionmanager.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://lgaf.webs.com/arqs/actionmanager.png" alt="Configuração do Action Manager" id="actionmanager20120123" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
Há umas poucas propriedades no &lt;b&gt;ActionManager&lt;/b&gt; e elas não são obrigatórias; destaco abaixo aquelas que são mais utilizadas:
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;&lt;b&gt;Images&lt;/b&gt; e &lt;b&gt;DisabledImages&lt;/b&gt; são &lt;b&gt;TImageList&lt;/b&gt; contendo, respectivamente, a imagem que deve ser vinculada a uma ação quando ela está ativa e quando está desabilitada. Em ambos os casos, as imagens devem ser pequenas - 16 x 16 &lt;a href="http://en.wikipedia.org/wiki/Pixel"&gt;pixels&lt;/a&gt;. Uma das propriedades de uma ação é o índice da imagem a ser usada; como só há um índice, a imagem correspondente à ação deve estar exatamente na mesma posição em todas as listas de imagens configuradas.
&lt;br/&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;&lt;b&gt;LargeImages&lt;/b&gt; e &lt;b&gt;LargeDisabledImages&lt;/b&gt; são os &lt;b&gt;TImageList&lt;/b&gt; que contem imagens grandes - 32 por 32 pixels - para as ações configuradas nesse gerenciador. A primeira lista vincula imagens a ações ativas enquanto a segunda traz as imagens grandes para ações desabilitadas. Lembre-se que as imagens relativas a uma ação devem estar na mesma posição, conforme dito no tópico anterior.
&lt;br /&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;&lt;b&gt;State&lt;/b&gt;: Permite desativar todas as ações de um única vez, impedindo-as de serem disparadas.
&lt;br /&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;Use a propriedade &lt;b&gt;ActionBars&lt;/b&gt; para criar barras de ferramentas associadas ao gerenciador.
&lt;br /&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;&lt;b&gt;FileName&lt;/b&gt; indica o caminho completo para um arquivo que armazernará a configuração dinâmica feita pelo usuário final em tempo de execução.
&lt;/div&gt;&lt;br /&gt;
Como se depreende do exposto acima, o gerenciador de ações pode ser usado em conjunto com o &lt;a href="http://docwiki.embarcadero.com/VCL/en/CustomizeDlg.TCustomizeDlg"&gt;TCustomizeDlg&lt;/a&gt; para permitir ao usuário final reorganizar as barras de ferramentas.&lt;br /&gt;
&lt;br /&gt;
Uma vez que o gerenciador está preparado, podemos acrescentar-lhe as ações e configurá-las. A lista abaixo mostra as principais propriedades do &lt;b&gt;TAction&lt;/b&gt;:&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;Use &lt;b&gt;Caption&lt;/b&gt; para informar o texto padrão para a ação. É esse texto que será usado num item de menu ou como texto de um botão onde a ação for vinculada.
&lt;br /&gt;

&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;Use &lt;b&gt;Category&lt;/b&gt; para organizar as ações, agrupando-as por afinidade, o que facilita a manuntenção de ações tanto para o programador quanto para o usuário final - caso a funcionalidade de configuração seja disponibilizada a ele.
&lt;br /&gt;

&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;&lt;b&gt;ImageIndex&lt;/b&gt; é a posição das imagens a serem usadas para representar a ação em diversos contextos. Cada ação terá à sua disposição o mesmo índice em cada uma das 4 listas existentes no gerenciador de ações.
&lt;br /&gt;

&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;Uma combinação de teclas pode ser atribuída em &lt;b&gt;Shortcut&lt;/b&gt;. Essa combinação é um método alternativo para executar a ação associada a ela.
&lt;br /&gt;

&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;O evento &lt;b&gt;OnExecute&lt;/b&gt; é usado para centralizar a execução da ação. Assim, não é preciso acrescentar código em nenhum outro ponto do programa nem responder a outros eventos; basta configurar a propriedade &lt;b&gt;Action&lt;/b&gt; existente no componente que desejar disparar a ação - menus e botões, por exemplo.
&lt;br /&gt;

&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;&lt;b&gt;Enabled&lt;/b&gt; permite habilitar ou desabilitar uma ação individual de forma centralizada. Isto é, altere essa propriedade para que todas as possibilidades de se executar a ação sejam afetadas de uma só vez.
&lt;br /&gt;

&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;Modifique a propriedade &lt;b&gt;Visible&lt;/b&gt; para esconder ou mostrar uma ação de uma só vez em todos os contextos nos quais ela estiver disponível.
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://docwiki.embarcadero.com/VCL/en/ActnMan.TActionManager"&gt;Documentação do TActionManager&lt;/a&gt;, &lt;a href="http://docwiki.embarcadero.com/VCL/en/ActnList.TAction"&gt;Classe TAction&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-1342484286110674330?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/oU6n1-TG2nHLLGcsbDK0Xkewy9E/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/oU6n1-TG2nHLLGcsbDK0Xkewy9E/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/oU6n1-TG2nHLLGcsbDK0Xkewy9E/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/oU6n1-TG2nHLLGcsbDK0Xkewy9E/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/J-B42yJQoXE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/1342484286110674330/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/01/trabalhando-com-acoes-em-delphi-e-c.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/1342484286110674330?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/1342484286110674330?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/J-B42yJQoXE/trabalhando-com-acoes-em-delphi-e-c.html" title="Trabalhando com Ações em Delphi e C++ Builder" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2012/01/trabalhando-com-acoes-em-delphi-e-c.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08MSH0_eCp7ImA9WhRWFko.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-3167242575144689249</id><published>2011-12-30T10:22:00.001-02:00</published><updated>2012-01-04T10:24:49.340-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-04T10:24:49.340-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows" /><category scheme="http://www.blogger.com/atom/ns#" term="C++ Builder" /><title>Preparando a execução de um programa em desktop remoto</title><content type="html">A adoção maciça da internet e os benefícios associados a ela têm levado as empresas a optar cada vez com mais frequência por programas que possam ser executados nessa infraestrutura. O principal benefício aqui está relacionado aos custos já que os &lt;i&gt;desktops&lt;/i&gt; não precisam ser tão potentes - basta que tenham acesso à internet para executarem esses programas remotos - e a manutenção dos equipamentos passa ser centralizada.&lt;br /&gt;
&lt;br /&gt;
Por outro lado, nem todos os programas em uso pelas empresas operam nativamente na internet. Seja por que são programas legados ou por que o fabricamente ainda não os preparou para o ambiente &lt;i&gt;web&lt;/i&gt; ou simplesmente porque há muitos programas e não houve tempo hábil para uma conversão em massa. Por isso, programas como o RDS (&lt;a href="http://en.wikipedia.org/wiki/Remote_Desktop_Services"&gt;Remote Desktop Services&lt;/a&gt;) da &lt;b&gt;Microsoft&lt;/b&gt; e as soluções da &lt;a href="http://www.citrix.com.br/index.php"&gt;Citrix&lt;/a&gt; para virtualização de &lt;i&gt;desktops&lt;/i&gt; têm sido bastante adotados.&lt;br /&gt;
&lt;br /&gt;
Essas soluções permitem que um usuário execute remotamente os programas que necessita, através de um &lt;i&gt;desktop&lt;/i&gt; virtual acessível via rede local ou internet. Com isso, o hardware mais robusto fica centralizado num servidor e pode ser compartilhado por diversos usuários simultâneos.&lt;br /&gt;
&lt;br /&gt;
Nesse ambiente, diversos usuários podem estar executando sua aplicação no mesmo computador remoto, compartilhando recursos como a pasta de trabalho, memória mapeada, disco, etc. Desse modo, as diferentes execuções simultâneas do programa podem conflitar entre si. Decisões baseadas no nome do computador, seu endereço IP ou outra informação de &lt;i&gt;hardware&lt;/i&gt; também podem causar problemas já que todos os usuários remotos lerão os mesmos valores. A &lt;a href="http://www.abc71.com.br"&gt;ABC71&lt;/a&gt;, por exemplo, usa o nome do computador onde nosso &lt;a href="http://www.abc71.com.br/entenda_o_que_e_erp_enterprise_resource_planing_content_ct_5767_2196_.aspx"&gt;ERP&lt;/a&gt; está em execução como parte do controle de licenças.&lt;br /&gt;
&lt;br /&gt;
Em Windows, normalmente as soluções de &lt;i&gt;desktop&lt;/i&gt; virtual se baseiam nos serviços de &lt;b&gt;Remote Desktop&lt;/b&gt; (antes chamado de Terminal Services), razão pela qual podemos usar a &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383459%28v=vs.85%29.aspx"&gt;Remote Desktop Services API&lt;/a&gt; para preparar nossas aplicações para que rodem nesse ambiente. Essa API permite resgatar e modificar informações sobre um usuário específico, além de executar tarefas relativas à administração do serviço.&lt;br /&gt;
&lt;br /&gt;
Para começar, temos que determinar se o programa está executando num &lt;i&gt;desktop&lt;/i&gt; convencional ou num virtual. Isso pode ser conseguido com uma chamada à função &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms724385%28v=vs.85%29.aspx"&gt;GetSystemMetrics&lt;/a&gt;. Saber que estou numa sessão remota me permite, por exemplo, ajustar uma pasta de trabalho coerente para cada execução distinta do meu programa.&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; TForm1.IsRemoteSession : boolean;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; res : integer;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;res := GetSystemMetrics (SM_REMOTESESSION);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Result := (res &lt;&gt; &lt;span style="color:blue;"&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
A função &lt;b&gt;GetSystemMetrics&lt;/b&gt; é um curinga da &lt;b&gt;API&lt;/b&gt; do Windows; com ela é possível recuperar uma porção de parâmetros do ambiente operacional. Chamada com &lt;b&gt;SM_REMOTESESSION&lt;/b&gt;, ela retorna um valor diferente de zero se o programa estiver num desktop virtual.&lt;br /&gt;
&lt;br /&gt;
Muitas informações valiosas sobre a sessão remota em andamento podem ser obtidas através da função &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383838%28v=vs.85%29.aspx"&gt;WTSQuerySessionInformation&lt;/a&gt;. No exemplo abaixo, eu a utilizo para recuperar o nome do computador que está acessando o desktop remoto:&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; TForm1.GetSessionInfo;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; lSessionId: DWORD;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;lBuffer : PChar;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;lBytesReturned : DWORD;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;lStationName : String;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lSessionId := &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Descobre a identificação da sessão do usuário com base na identificação do programa no Windows }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if not&lt;/b&gt;&lt;/span&gt; ProcessIdToSessionId (GetCurrentProcessId (), DWORD(@lSessionId)) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;raise&lt;/b&gt;&lt;/span&gt; Exception.Create (&lt;span style="color:maroon;"&gt;'Não foi possível obter Remote SessoinId'&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lBuffer := &lt;span style="color:navy;"&gt;&lt;b&gt;Nil&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lBytesReturned := &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lStationName := &lt;span style="color:maroon;"&gt;''&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Obtem nome da máquina Client }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (WTSQuerySessionInformation (WTS_CURRENT_SERVER_HANDLE,&lt;/span&gt;&lt;br /&gt;
                                   &lt;span style="margin-left:5em;"&gt;lSessionId,&lt;/span&gt;&lt;br /&gt;
                                   &lt;span style="margin-left:5em;"&gt;WTSClientName,&lt;/span&gt;&lt;br /&gt;
                                   &lt;span style="margin-left:5em;"&gt;lBuffer,&lt;/span&gt;&lt;br /&gt;
                                   &lt;span style="margin-left:5em;"&gt;lBytesReturned))&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;lStationName := String(lBuffer)&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;raise&lt;/b&gt;&lt;/span&gt; Exception.Create (&lt;span style="color:maroon;"&gt;'Não foi possível obter o nome da estação'&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Libera a memória alocada automaticamente }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;WTSFreeMemory (lBuffer);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
Vamos por partes. Para recuperar as informações de uma sessão remota, primeiro temos que identificar essa sessão. A função &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa382990%28v=vs.85%29.aspx"&gt;ProcessIdToSessionId&lt;/a&gt; da API do Windows nos fornece isso, mapeando o &lt;a href="http://en.wikipedia.org/wiki/Process_identifier"&gt;Process ID&lt;/a&gt; de nosso programa para a correspondente identificação da sessão remota onde ele está executando.&lt;br /&gt;
&lt;br /&gt;
O passo seguinte é chamar a função &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383838%28v=vs.85%29.aspx"&gt;WTSQuerySessionInformation&lt;/a&gt; para levantar as informações desejadas. Essa função recebe 5 parâmetros. O primeiro é um &lt;i&gt;handle&lt;/i&gt; para o servidor da sessão remota. No exemplo, passei a constante &lt;b&gt;WTS_CURRENT_SERVER_HANDLE&lt;/b&gt; para indicar que quero informações sobre o servidor atual. Poderia ter usado &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383837%28v=vs.85%29.aspx"&gt;WTSOpenServer&lt;/a&gt; para abrir outro servidor remoto.&lt;br /&gt;
&lt;br /&gt;
O segundo parâmetro é a identificação da sessão que obtivemos no primeiro passo. O parâmetro seguinte é o que determina qual informação será recuperada. Os valores permitidos são os listados no enumerado &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383861%28v=vs.85%29.aspx"&gt;WTS_INFO_CLASS&lt;/a&gt;. No exemplo, usei &lt;b&gt;WTSClientName&lt;/b&gt; para obter o nome do computador do usuário que diparou o acesso remoto; a lista de informações recuperáveis inclui o endereço IP desse mesmo computador, a pasta de trabalho remota (no servidor), o nome do usuário e informações &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb736370%28v=vs.85%29.aspx"&gt;sobre o uso da sessão&lt;/a&gt; e &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb736369%28v=vs.85%29.aspx"&gt;sobre a Client&lt;/a&gt;, dentre outras.&lt;br /&gt;
&lt;br /&gt;
Os dois últimos parâmetros são, respectivamente, um ponteiro para a área que receberá a informação solicitada e a quantidade de &lt;i&gt;bytes&lt;/i&gt; que essa informação está ocupando. Como ambos são calculados pela função &lt;b&gt;WTSQuerySessionInformation&lt;/b&gt;, não é preciso alocar previamente a memória para eles. No entanto, é nossa responsabilidade liberar a memória alocada usando a função &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383834%28v=vs.85%29.aspx"&gt;WTSFreeMemory&lt;/a&gt;, como mostra o passo final do código do exemplo.&lt;br /&gt;
&lt;br /&gt;
Se tivesse usado &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms724295%28v=vs.85%29.aspx"&gt;GetComputerName&lt;/a&gt;, eu obteria o nome do computador remoto, isto é, o servidor onde o programa está efetivamente sendo executado. A questão é que o mesmo nome seria retornado para qualquer usuário que acesse um &lt;i&gt;desktop&lt;/i&gt; remoto nesse servidor ...&lt;br /&gt;
&lt;br /&gt;
A lista de &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383464%28v=VS.85%29.aspx"&gt;funções da Remote Desktop Services API&lt;/a&gt; inclui ainda formas de administrar o &lt;b&gt;RDS&lt;/b&gt; tais como iniciar e encerrar sessões, inventariar as sessões ativas, modificar configurações de uma sessão, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383464%28v=VS.85%29.aspx"&gt;Remote Desktop Services API Functions&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms724385%28v=vs.85%29.aspx"&gt;Função GetSystemMetrics&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa382990%28v=vs.85%29.aspx"&gt;Função ProcessIdToSessionId&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383834%28v=vs.85%29.aspx"&gt;Função WTSFreeMemory&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-3167242575144689249?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4bxsaXeszVWywhcl1kZVUQ_dLt8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4bxsaXeszVWywhcl1kZVUQ_dLt8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4bxsaXeszVWywhcl1kZVUQ_dLt8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4bxsaXeszVWywhcl1kZVUQ_dLt8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/35WtRwghTPI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/3167242575144689249/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/12/preparando-execucao-de-um-programa-em.html#comment-form" title="5 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/3167242575144689249?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/3167242575144689249?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/35WtRwghTPI/preparando-execucao-de-um-programa-em.html" title="Preparando a execução de um programa em desktop remoto" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/12/preparando-execucao-de-um-programa-em.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMHQXoyfip7ImA9WhRXFEQ.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-2333683839626527028</id><published>2011-12-21T17:07:00.000-02:00</published><updated>2011-12-21T17:07:10.496-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-21T17:07:10.496-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Design Patterns" /><title>Design Patterns com Delphi: Template - Parte II</title><content type="html">No meu último post, introduzi o conceito do &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html"&gt;Design Pattern&lt;/a&gt; &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html#categorias"&gt;comportamental&lt;/a&gt; &lt;b&gt;Template&lt;/b&gt;. Em resumo, esse padrão estabelece uma sequência de passos para a execução de uma determinada tarefa, permitindo que sejam criadas heranças que implementem suas próprias versões de um ou mais dos passos, de acordo com a necessidade.&lt;br /&gt;
&lt;br /&gt;
Neste post, eu sugiro uma implementação em Delphi do exemplo envolvendo criação de infraestruturas que usei para apresentar o &lt;b&gt;Template&lt;/b&gt; no outro post. Para facilitar o entendimento, reproduzo novamente abaixo o diagrama UML que modela a infraestrutura da transações de negócio usada como exemplo:&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;width: 96%;"&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lgaf.webs.com/arqs/Template.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;width:100%;" src="http://lgaf.webs.com/arqs/Template.gif" alt="Diagrama UML para o padrão Template" id="designPatternTemplate20111221" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
Como dá para intuir a partir da simplicidade do diagrama, a codificação também não é complexa. A primeira providência é criar a classe que define o formato geral do algorítimo, os passos que o comporão, em qual ordem esses passos devem ser chamados para completar a tarefa e quais deles poderão ser particularizados em heranças do algorítimo. Esta classe - chamada de &lt;b&gt;Abstract Class&lt;/b&gt; - servirá, portanto, de base para as demais implementações do mesmo algorítimo. No nosso exemplo, é a classe &lt;b&gt;TWTransacao&lt;/b&gt; que tem essa responsabilidade:
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
TWTransacao=&lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;protected&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;_Erros: TWErros; &lt;span style="color:green;"&gt;{ Lista de erros da transação }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; BeginTrans;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; CommitTrans;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; RollbackTrans;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; ConsisteDados : boolean;&lt;span style="color:navy;"&gt;&lt;b&gt;virtual;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; GravaDados : integer;&lt;span style="color:navy;"&gt;&lt;b&gt;virtual&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
    &lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; ExecutarTransacao : integer;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; TWTransacao.ConsisteDados : boolean;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Result := true;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; TWTransacao.GravaDados : integer;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Result := &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; TWTransacao.ExecutarTransacao : integer;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Result := &lt;span style="color:blue;"&gt;-99&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;Try&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;_Erros.Clear;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="color:green;margin-left:2em;"&gt;{ Inicia uma transação com o banco de dados }&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;BeginTrans;&lt;/span&gt;&lt;br /&gt;
    &lt;br /&gt;
    &lt;span style="color:green;margin-left:2em;"&gt;{ Se estiver tudo OK com os dados, gravá-los no banco }&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (ConsisteDados) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;Result := GravaDados;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="color:green;margin-left:2em;"&gt;{ Efetiva a transação }&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;CommitTrans;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;Except&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="color:green;margin-left:2em;"&gt;{ Se houve algum erro, aborta a transação com o banco de dados}&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;RollbackTrans;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;Result := &lt;span style="color:blue;"&gt;-100&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;&lt;br /&gt;
Observe que há apenas uma função pública : &lt;b&gt;ExecutarTransacao&lt;/b&gt;. As partes do programa que desejarem executar uma transação de negócio precisam ter acesso apenas a ela, não importando quais ou quantos são os passos necessários para executá-la.&lt;br /&gt;
&lt;br /&gt;
Em contraste, tanto os passos do algorítimo que poderão ser estendidos pelas heranças quanto os métodos internos auxiliares foram colocados na área protegida, escondendo os detalhes para códigos externos. Aqui, as funções &lt;b&gt;ConsisteDados&lt;/b&gt; e &lt;b&gt;GravaDados&lt;/b&gt; poderiam ter sido declaradas como abstratas, o que forçaria as heranças a fornecer-lhes uma implementação. No entanto, não é mandatório que elas tenham essa característica, de modo que o exemplo ilustra como a classe base do &lt;b&gt;Template&lt;/b&gt; pode providenciar uma versão padrão dos passos do algorítimo, mesmo que sejam versões bem simples. Elas poderiam, por exemplo, registrar um log da execução.&lt;br /&gt;
&lt;br /&gt;
As funções relativas a transações com o banco de dados (BeginTrans, CommitTrans e RollbackTrans) apenas repassam suas respectivas chamadas diretamente ao banco; por isso, suas implementações foram omitidas no quadro acima.&lt;br /&gt;
&lt;br /&gt;
Já temos a classe base, podemos então codificar as heranças previstas para transações de produtos, pedidos de venda e notas fiscais:
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
TWTrnProduto = &lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWTransacao)&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;_prod : TWProduto;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;protected&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; ConsisteDados : boolean;&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; GravaDados : integer;&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
TWTrnPedidoVenda = &lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWTransacao)&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;_Pedido : TWPedidoVenda;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;protected&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; ConsisteDados : boolean;&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; GravaDados : integer;&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
  &lt;br /&gt;
TWTrnNotaFiscal = &lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWTransacao)&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;_Nota : TWNotaFiscal;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;protected&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; ConsisteDados : boolean;&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; GravaDados : integer;&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
  &lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; TWTrnProduto.ConsisteDados : boolean;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Result := &lt;span style="color:navy;"&gt;&lt;b&gt;inherited&lt;/b&gt;&lt;/span&gt; ConsisteDados;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (TWProduto.ExisteProd (_Prod) ) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;Result := false;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;_Erros.Add (&lt;span style="color:maroon;"&gt;'Produto já existe'&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; TWTrnProduto.GravaDados : integer;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;inherited&lt;/b&gt;&lt;/span&gt; GravaDados;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_Produto.Insert();&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; TWTrnPedidoVenda.ConsisteDados : boolean;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Result := &lt;span style="color:navy;"&gt;&lt;b&gt;inherited&lt;/b&gt;&lt;/span&gt; ConsisteDados;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (TWPedidoVenda.ExistePedido (_Pedido) ) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;Result := false;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;_Erros.Add (&lt;span style="color:maroon;"&gt;'Já existe pedido com esse número.'&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (&lt;span style="color:navy;"&gt;&lt;b&gt;not&lt;/b&gt;&lt;/span&gt; _Pedido.VerifSaldoProdutos) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;Result := false;&lt;/span&gt;&lt;br /&gt;
    &lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (&lt;span style="color:navy;"&gt;&lt;b&gt;not&lt;/b&gt;&lt;/span&gt; _Pedido.VerifDadosComerciais) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;Result := false;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
   &lt;span style="color:green;margin-left:1em;"&gt;{ Se detectou algum erro, reporta para a transação }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_Erros.Add(_Pedido.Erros);&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; TWTrnPedidoVenda.GravaDados : integer;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;inherited&lt;/b&gt;&lt;/span&gt; GravaDados;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="color:green;margin-left:1em;"&gt;{ Insere o pedido, atualiza saldo dos produtos e faz outros ajustes }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_Pedido.Insert ();&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
Vemos no quadro anterior que as transações reais são heranças da classe de transação básica e que elas fornecem suas próprias versões de passos do algorítimo base. Com isso, elas garantem que suas próprias regras de negócio sejam respeitadas, enquanto são mantidas a ordem de chamada dos passos e outras regras estipuladas pela classe &lt;b&gt;TWTransacao&lt;/b&gt;. A transação de nota fiscal foi omitida no quadro mas a ideia dela é bastante similar à de pedidos de venda.&lt;br /&gt;
&lt;br /&gt;
Para completar o exemplo, falta a classe &lt;b&gt;Client&lt;/b&gt;, isto é, aquela parte do código que utilizará o nosso &lt;b&gt;template&lt;/b&gt;.
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
TWTela = &lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;protected&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;_Trn : TWTransacao;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; ExecutarTransacao();&lt;/span&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
  &lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; TWTela.ExecutarTransacao();&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_Trn := ObtemTransacao ();&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_Trn.ExecutarTransacao;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
Como mostra o quadro, o código da classe &lt;b&gt;TWTela&lt;/b&gt; acaba ficando extremamente simples. Aqui, o maior problema talvez seja decidir o melhor meio de obter uma instância da transação correta. Dependendo das circunstâncias, podemos optar pelo &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/design-patterns-com-delphi-factory.html"&gt;método Factory&lt;/a&gt; ou organizar as telas usando o &lt;a href="http://balaiotecnologico.blogspot.com/2010/11/design-patterns-em-delphi-mediator.html"&gt;padrão Mediator&lt;/a&gt; - o que permitiria cada tela instanciar diretamente a transação adequada.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://balaiotecnologico.blogspot.com/2011/12/design-patterns-com-delphi-template.html"&gt;Design Patterns com Delphi: Template - Parte I&lt;/a&gt;, &lt;a href="http://balaiotecnologico.blogspot.com/search/label/Design%20Patterns"&gt;Posts sobre Design Patterns&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-2333683839626527028?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/jx2o-za-VVmfhe8CI7XObeFldCM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jx2o-za-VVmfhe8CI7XObeFldCM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/jx2o-za-VVmfhe8CI7XObeFldCM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jx2o-za-VVmfhe8CI7XObeFldCM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/EgHCgqoVjbY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/2333683839626527028/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/12/design-patterns-com-delphi-template_21.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/2333683839626527028?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/2333683839626527028?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/EgHCgqoVjbY/design-patterns-com-delphi-template_21.html" title="Design Patterns com Delphi: Template - Parte II" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/12/design-patterns-com-delphi-template_21.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE4HSXs9eip7ImA9WhRQGE0.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-2430925193485039415</id><published>2011-12-13T17:00:00.000-02:00</published><updated>2011-12-13T17:02:18.562-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-13T17:02:18.562-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Design Patterns" /><title>Design Patterns com Delphi: Template - Parte I</title><content type="html">Criar uma infraestrutura de software é padronizar a forma como as coisas acontececerão dentro de um programa, estabelecendo regras e ditando as mensagens que cada parte do código está preparada para receber. Por exemplo, uma infraestrutura para realizar transações de negócio dentro do sistema pode ser descrita simplificadamente em poucos passos : abertura de transação com o banco de dados; consistência das informações contidas no(s) objeto(s) de negócio envolvido(s); persistência das informações nas respectivas tabelas; encerramento da transação. Todo objeto com capacidade de realizar uma transação terá necessariamente que implementar esses passos.&lt;br /&gt;
&lt;br /&gt;
Se cada &lt;a href="http://pt.wikipedia.org/wiki/Caso_de_uso"&gt;Caso de Uso&lt;/a&gt; implementar uma versão independente dos passos, mudanças nessa sequência teriam que ser replicadas em todas as implementações. O alvo do &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html"&gt;Design Pattern&lt;/a&gt; &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html#categorias"&gt;comportamental&lt;/a&gt; &lt;b&gt;Template&lt;/b&gt; é justamente situações como esta, onde um algorítimo é definido de modo centralizado, moldando a forma de trabalho a ser seguida por todas as classes de objeto que desejarem implementá-lo. Um ou mais passos podem ser sobrepostos pelas heranças, permitindo que elas implementem comportamentos diferenciados quando for necessário.&lt;br /&gt;
&lt;br /&gt;
Essa idéia é similar à do &lt;i&gt;Pattern&lt;/i&gt; &lt;a href="http://balaiotecnologico.blogspot.com/2011/09/design-patterns-com-delphi-strategy.html"&gt;Strategy&lt;/a&gt;. A diferença mais importante entre ambos é que o &lt;b&gt;Template&lt;/b&gt; permite que heranças alterem partes de um algorítimo enquanto no &lt;b&gt;Strategy&lt;/b&gt; temos que optar por uma das versões de um algorítimo bem conhecido e executar todo o trabalho com esse algorítimo.&lt;br /&gt;
&lt;br /&gt;
O quadro a seguir traz um diagrama UML mostrando as relações esperadas entre as classes participantes da solução para o &lt;b&gt;Template&lt;/b&gt;. O cenário abordado é o da transação de negócio citado no primeiro parágrafo deste &lt;i&gt;post&lt;/i&gt;:&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;width: 96%;"&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lgaf.webs.com/arqs/Template.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;width:100%;" src="http://lgaf.webs.com/arqs/Template.gif" alt="Diagrama UML para o padrão Template" id="designPatternTemplate20111213" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
Neste exemplo, nem todos os métodos são virtuais. São declarados como virtuais apenas aqueles que poderão (ou deverão) ter uma implementação distinta nas classes herdadas. Como podemos ver, o algorítimo é decomposto em métodos mais granulares que podem ser sobrepostos quando ncessários. Neste contexto, tais métodos são chamados de &lt;b&gt;operações primitivas&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
No exemplo, o método &lt;b&gt;ExecutarTransacao&lt;/b&gt; é responsável por chamar cada &lt;i&gt;operação primitiva&lt;/i&gt; no tempo correto, moldando efetivamente o algorítimo que deve ser executado por cada classe da hierarquia. Este método é chamado de &lt;b&gt;Template&lt;/b&gt; (modelo).&lt;br /&gt;
&lt;br /&gt;
Formalmente, as classes participantes de uma solução para o &lt;i&gt;pattern&lt;/i&gt; &lt;b&gt;Template&lt;/b&gt; recebem os seguintes nomes:
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;É denominada &lt;b&gt;Abstract Class&lt;/b&gt; a classe base que define as operações primitivas que estarão disponíveis para o algorítimo. Ela também define o esqueleto do algorítimo ao implementar o método &lt;b&gt;Template&lt;/b&gt;, chamando cada operação primitiva na ordem correta. No diagrama acima, este é o papel da classe &lt;b&gt;TWTransacao&lt;/b&gt;. É importante ressaltar que, apesar do nome, essa classe não precisa ser obrigatoriamente abstrata; se for adequado, a &lt;i&gt;Abstract Class&lt;/i&gt; pode prover versões básicas de todas as operações primitivas.&lt;br /&gt;
&lt;br /&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;As classes que provêm versões particulares de uma ou mais das operações primitivas são chamadas &lt;b&gt;Concrete Class&lt;/b&gt;. Isso permite-lhes realizar ações específicas dentro dos passos básicos que formam o algorítimo determinado pela classe base. No exemplo, as classes &lt;b&gt;TWTrnProduto&lt;/b&gt;, &lt;b&gt;TWTrnNotaFiscal&lt;/b&gt; e &lt;b&gt;TWTrnPedidoVenda&lt;/b&gt; são desse tipo. Elas fornecem suas próprias versões dos métodos que consistem e gravam os dados relativos, respectivamente, às transações para inserir um novo produto, criar uma nota fiscal e criar um pedido de venda.&lt;br /&gt;
&lt;br /&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;O &lt;b&gt;Client&lt;/b&gt; é qualquer parte do sistema que esteja apta a disparar o algorítimo definido na classe base. A classe &lt;b&gt;TWTela&lt;/b&gt; do diagrama de exemplo detem esse papel.
&lt;/div&gt;
No próximo post, eu apresento uma sugestão de como implementar o exemplo proposto usando Delphi.&lt;br /&gt;
&lt;br /&gt;

&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://balaiotecnologico.blogspot.com/search/label/Design%20Patterns"&gt;Posts sobre Design Patterns&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-2430925193485039415?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/gRQuYxM6Mp53TNQccT_zMR8b8ZI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/gRQuYxM6Mp53TNQccT_zMR8b8ZI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/gRQuYxM6Mp53TNQccT_zMR8b8ZI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/gRQuYxM6Mp53TNQccT_zMR8b8ZI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/YcRSxjbJC9o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/2430925193485039415/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/12/design-patterns-com-delphi-template.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/2430925193485039415?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/2430925193485039415?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/YcRSxjbJC9o/design-patterns-com-delphi-template.html" title="Design Patterns com Delphi: Template - Parte I" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/12/design-patterns-com-delphi-template.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQDRXw_eCp7ImA9WhRQFE4.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-4748885259484559293</id><published>2011-12-08T17:36:00.002-02:00</published><updated>2011-12-09T10:06:14.240-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-09T10:06:14.240-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Notícias" /><title>HTML5 criará novos desafios para os profissionais de Segurança em TI</title><content type="html">Agora parece que a Adobe se rendeu em definitivo ao avanço do HTML5, que nasceu com a missão de flexibilizar o desenvolvimento para aplicações Web, eliminando a necessidade de instalação de plugins de terceiros - como o próprio Flash da Adobe. Em &lt;a href="http://blogs.adobe.com/flex/2011/11/your-questions-about-flex.html"&gt;post recente no blog do Flex&lt;/a&gt;, a empresa recomenda que se opte pelo HTML5 pois essa tecnologia prevalecerá no longo prazo.&lt;br /&gt;
&lt;/br&gt; Eles também anunciaram que &lt;a href="http://www.computerworld.com/s/article/9221674/Adobe_explains_ditching_Flash_for_mobile"&gt;não desenvolverão o plugin do Flash&lt;/a&gt; para versões futuras dos navegadores de dispositivos móveis. É claro que não pretendem deixar de criar ferramentas e estão usando o &lt;i&gt;know-how&lt;/i&gt; que têm e a base fiel de clientes conquistados para se manterem relevantes. Ao que parece, a ideia é criar novas ferramentas mantendo a essência da filosofia de desenvolvimento das ferramentas atuais - só que produzindo HTML5 e Javascript ao invés do código próprietário do Flahs. &lt;a href="http://blogs.adobe.com/conversations/2011/11/flash-focus.html"&gt;Veja aqui&lt;/a&gt; o comunicado publicado no site da empresa, revelando os planos para o futuro do Flash.&lt;br /&gt;
&lt;br /&gt;
Com isso, a euforia com o HTML5 já começa a assentar, dando lugar ao pragmatismo. Os especialistas começam a fazer avaliações mais realistas sobre a nova tecnologia e levantam questões até aqui deixadas em segundo plano. A expectativa de adoção dela vem suscitando, por exemplo, questões relativas à segurança, conforme mostra o artigo abaixo, cujo original (em inglês) foi publicado pela &lt;a href="https://www.infoworld.com/d/security/html5-create-new-challenges-security-pros-in-2012-180827?source=rss_application_development"&gt;InfoWorld&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 5px 10px 1em 5px;width:98%;background-color:#e9e9fb"&gt;A adoção do HTML5 abrirá espaço para a criação de uma vasta gama de novas aplicações Web, mas poderá também introduzir novos desafios para os profissionais de segurança nas empresas, de acordo com a firma de segurança Sophos.&lt;br /&gt;
&lt;br /&gt;
Em suas previsões sobre segurança para 2012, a Sophos identifica como principais riscos as novas tecnologias para Web e redes - incluindo HTML5. Enquanto essas tecnologias introduzem novos recursos impressionantes para desenvolvimento de aplicações Web ricas, elas também introduzem novas formas de ataque, explicou a companhia.&lt;br /&gt;
&lt;br /&gt;
O HTML4 supriu conteúdo na Web por muitos anos, mas é uma linguagem de programação muito básica, de modo que os desenvolvedores tiveram que complementá-lo com add-ons como o JavaScript, Flash e Google Gears. Estes add-ons têm frequentemente muitas vulnerabilidades, tornando o sistema inseguro como um todo.&lt;br /&gt;
&lt;br /&gt;
HTML5 remove a necessidade da maioria dos add-ons, porque é uma linguagem mais sofisticada e vem com um banco de dados completo, permitindo que os usuários armazenem gigas de informação. Então, por exemplo, você pode criar uma animação completa, realidade virtual em 3D ou guardar aplicações completas dentro do navegador.&lt;br /&gt;
&lt;br /&gt;
De acordo com James Lyne, tecnólogo sênior na Sophos, isso chega muito perto da visão in-client originalmente associada à computação na nuvem. No entanto, armazenar dados dentro do navegador torna o navegador em si um alvo para os cyber criminosos.&lt;br /&gt;
&lt;br /&gt;
"Tradicionalmente, o navegador é um meio para que cyber criminosos obtenham acesso ao seu PC. Agora, eles tentarão atacar o próprio navegador para roubar seus dados", diz Lyne.&lt;br /&gt;
&lt;br /&gt;
A execução em &lt;i&gt;sandbox &lt;/i&gt;do HTML5 também aumenta os riscos de "clickjacking" (induzir um usuário Web a revelar informações confidentiais ou tomar o controle do computador desse usuário quando ele clica num link aparentemente inócuo) já que as páginas Web não são mais capazes de identificar de onde os comandos estão vindo.&lt;br /&gt;
&lt;br /&gt;
"Todo aquele código escrito pelos desenvolvedores para prevenir que aplicações Web sejam capturadas por alguém não autorizado ou sofram clickjacking agora não funcionará", diz Lyne. "Implementaram um recurso para aumentar a segurança mas inadivertidamente desativaram um outro mais importante."&lt;br /&gt;
&lt;br /&gt;
Além disso, HTML levanta novas questões sobre &lt;i&gt;cookies&lt;/i&gt;, que poderão tornar redundantes as &lt;a href="http://news.techworld.com/sme/3282148/european-countries-ignoring-privacy-directive-says-commission-spokesman/"&gt;recomendações para remoção deles após um determinado período&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
"O HTML5 poderia até ter novos super-cookies," diz Lyne. "Se um site não for codificado de forma apropriada, os caras maus poderão compilar uma enorme base de dados com as URLs por onde você navegou e rastrear as informações que você eventualmente tenha fornecido nelas. Eles poderão capturar uma grande quantidade de dados."&lt;br /&gt;
&lt;br /&gt;
Apesar desses problemas pontenciais, Lyne diz que adotar o HTML5 trará muitos benefícios para a segurança. Haverá redução nos riscos relacionados aos &lt;i&gt;add-ons&lt;/i&gt;, bem como mais segurançã ao facilitar validação de dados no lado client das aplicações. Também haverão bibliotecas capazes de lidar com questões como SQL injection.&lt;br /&gt;
&lt;br /&gt;
"Ao longo do tempo, o HTML5 vai resolver muitos dos problemas que temos, mas, como qualquer nova tencologia, há uma tendência a uma regressão num primeiro momemto," diz ele. "De maneira geral, deveríamos acelerar na direção do HTML5 porque Flash tem sido traumático e as novas aplicações Web estão muito legais - só temos que nos certificar de não estarmos adotando um pesadelo." &lt;/div&gt;&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="https://www.infoworld.com/d/security/html5-create-new-challenges-security-pros-in-2012-180827?source=rss_application_development"&gt;HTML5 to create new challenges for security pros in 2012&lt;/a&gt;, &lt;a href="http://blogs.adobe.com/flex/2011/11/your-questions-about-flex.html"&gt;Your Questions about Flex&lt;/a&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-4748885259484559293?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ecCdVIyEbpcfoxDE_vFPQYRuiys/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ecCdVIyEbpcfoxDE_vFPQYRuiys/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ecCdVIyEbpcfoxDE_vFPQYRuiys/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ecCdVIyEbpcfoxDE_vFPQYRuiys/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/iY9-JNTWJ-E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/4748885259484559293/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/12/html5-criara-novos-desafios-para-os.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4748885259484559293?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4748885259484559293?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/iY9-JNTWJ-E/html5-criara-novos-desafios-para-os.html" title="HTML5 criará novos desafios para os profissionais de Segurança em TI" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/12/html5-criara-novos-desafios-para-os.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE4GQnc-fip7ImA9WhRVEUQ.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-7591531105757258392</id><published>2011-11-04T14:12:00.001-02:00</published><updated>2012-01-10T10:02:03.956-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-10T10:02:03.956-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Indy" /><title>Trabalhando com emails em uma caixa postal usando IMAP4 em Delphi</title><content type="html">Mostrei num outro post aqui no blog &lt;a href="http://balaiotecnologico.blogspot.com/2011/08/recuperando-emails-de-uma-caixa-postal.html"&gt;como ter acesso aos emails numa caixa postal&lt;/a&gt; através do protocolo &lt;a href="http://pt.wikipedia.org/wiki/Post_Office_Protocol"&gt;POP3&lt;/a&gt; no Delphi. O &lt;b&gt;POP3&lt;/b&gt; é um protocolo amplamente adotado para permitir o acesso remoto aos emails de uma caixa postal mas ele é bastante limitado. Seus recursos estão restritos basicamente à manipulação das mensagens existentes na caixa postal, permitindo lê-las, apagá-las ou arquivá-las.&lt;br /&gt;
&lt;br /&gt;
Se precisar de recursos mais avançados - tais como gerenciar pastas, localizar uma mensagem pesquisando o texto dela, compartilhar caixas postais com um grupo de trabalho, entre outras - temos que apelar para o &lt;b&gt;IMAP4&lt;/b&gt;, um protocolo mais completo. &lt;br /&gt;
&lt;br /&gt;
O primeiro passo para trabalhar com o &lt;b&gt;IMAP4&lt;/b&gt;, assim como acontece com os outros protocolos baseados no TCP/IP, é estabelecer uma conexão com o servidor. Aqui também isso exige que alguns parâmetros sejam informados, tais como o endereço do servidor, a porta onde ele estará aguardando requisições e um usuário com permissão de acesso ao serviço, bem como sua respectiva senha:&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 98%;"&gt;
&lt;span style="color: navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; iMap TIdIMAP4;&lt;br /&gt;
&lt;span style="color: navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;iMap := TIdIMAP4.Create (&lt;b&gt;Nil&lt;/b&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color: green;"&gt;{ Atribui os dados fornecidos pelo usuário e tenta se conectar }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;iMap.Host := _ServerIMAP; &lt;span style="color: green;"&gt;{ Endereço do servidor }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;iMap.Port := _PortaIMAP; &lt;span style="color: green;"&gt;{ Porta que o servidor está ouvindo }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;iMap.Username := _UserIMAP;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;iMap.Password := _SenhaIMAP;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;iMap.Connect(&lt;span style="color: blue;"&gt;100000&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color: green;"&gt; {  Realiza aqui algumas tarefas com o IMAP conectado}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color: green;"&gt;{ Descarta a conexão e outros recursos qdo não forem mais necessários }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;iMap.Disconnect();&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;iMap.Free ();&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
Uma grande diferença em relação ao funcionamento do &lt;b&gt;POP3&lt;/b&gt; é que o &lt;b&gt;IMAP4&lt;/b&gt; pode gerenciar várias caixas postais numa única conexão. Do ponto de vista do usuário, cada caixa postal é normalmente encarada como uma pasta. Como os comandos do &lt;b&gt;IMAP4&lt;/b&gt; são direcionados a uma caixa postal, isso nos obriga a selecionar uma antes de submeter os comandos.&lt;br /&gt;
&lt;br /&gt;
Ao menos a caixa chamada &lt;i&gt;INBOX&lt;/i&gt; (caixa de entrada) deve existir mas você pode levantar uma lista completa com todos os nomes das caixas que existem na conta usando a função &lt;b&gt;ListMailBoxes&lt;/b&gt;. Um usuário pode, então, ser apresentado a essa lista para que escolha a caixa mais apropriada para as necessidades dele. Considerando o &lt;i&gt;iMap&lt;/i&gt; criado e conectado no quadro anterior, fazer o levantamento é bem simples:&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 98%;"&gt;
&lt;span style="color: navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; lMaixBoxes : TStringList;&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;lCaixaSel : String;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color: green;"&gt;{ ... }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;lMaixBoxes := TStringList.Create();&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;iMap.ListMailBoxes(lMaixBoxes);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color: green;"&gt;{ Carrega a lista na tela para o usuário escolher uma delas. }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;lCaixaSel := SelecionaCaixaPostal (lMaixBoxes);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;lMailBoxes.Free();&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color: navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: navy;"&gt;&lt;b&gt;not&lt;/b&gt;&lt;/span&gt; iMap.SelectMailBox (lCaixaSel) ) &lt;span style="color: navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;&lt;span style="color: navy;"&gt;&lt;b&gt;raise&lt;/b&gt;&lt;/span&gt; Exception.Create(&lt;span style="color: maroon;"&gt;'Erro na seleção da caixa postal'&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color: green;"&gt;{ ... }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
Uma vez que a caixa foi escolhida, precisamos repassá-la ao &lt;i&gt;iMap&lt;/i&gt; para que possamos operar com a caixa específica. É o que faz a chamada à função &lt;i&gt;SelectMailBox &lt;/i&gt; no código acima. Essa chamada faz com que o &lt;b&gt;TidIMAP4&lt;/b&gt; alimente sua propriedade &lt;b&gt;MailBox&lt;/b&gt; com um resumo do estado atual da caixa selecionada, disponibilizando informações como a quantidade total de mensagens e quantas dessas permanecem não lidas, entre outras informações.&lt;br /&gt;
&lt;br /&gt;
Com uma caixa selecionada, podemos realizar operações como pesquisar os emails contidos nela. Nesse quesito, o &lt;b&gt;IMAP4&lt;/b&gt; é muito mais flexível que o &lt;b&gt;POP3&lt;/b&gt; já que nos fornece uma opção para filtrar as mensagens desejadas usando a estrutura &lt;a href="http://www.e-iter.net/Knowledge/Indy9/007411.html"&gt;TIdIMAP4SearchRec&lt;/a&gt;. O principal recurso dessa estrutura é o campo &lt;a href="http://www.e-iter.net/Knowledge/Indy9/007409.html"&gt;SearchKey&lt;/a&gt;. É esse campo que determina quais critérios devem ser respeitados na consulta e, portanto, quais dos outros campos da estrutura serão considerados quando a consulta for submetida pela função &lt;b&gt;SearchMailBox&lt;/b&gt;. O exemplo abaixo usa o &lt;i&gt;iMap&lt;/i&gt; conectado para procurar todas as mensagens que ainda não foram lidas na caixa postal atual e varre a lista encontrada, recuperando cada uma delas.&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 98%;"&gt;
&lt;span style="color: navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; rec : &lt;span style="color: navy;"&gt;&lt;b&gt;array of&lt;/b&gt;&lt;/span&gt; TIdIMAP4SearchRec;&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;TheMsg : TIdMessage;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;contMsg, i, idMsg : Integer;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color: green;"&gt;{ Procura por emails do tipo skUnseen - ou seja, somente os "não lidos" }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;rec[0].SearchKey := skUnseen;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color: navy;"&gt;&lt;b&gt;if not&lt;/b&gt;&lt;/span&gt; iMap.SearchMailBox (rec)  &lt;span style="color: navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;&lt;span style="color: navy;"&gt;&lt;b&gt;raise&lt;/b&gt;&lt;/span&gt; Exception.Create(&lt;span style="color: maroon;"&gt;'Erro na pesquisa da caixa postal'&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
    &lt;br /&gt;
      &lt;span style="margin-left: 1em;"&gt;&lt;span style="color: green;"&gt;{ Quantas mensagens foram encontradas ? }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left: 1em;"&gt;contMsg := iMap.MailBox.SearchResult.Length;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color: navy;"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt;  i := 0 &lt;span style="color: navy;"&gt;&lt;b&gt;to&lt;/b&gt;&lt;/span&gt; contMsg - 1 &lt;span style="color: navy;"&gt;&lt;b&gt;do begin&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left: 2em;"&gt;TheMsg := TIdMessage.Create(&lt;span style="color: navy;"&gt;&lt;b&gt;Nil&lt;/b&gt;&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
         &lt;br /&gt;
         &lt;span style="margin-left: 2em;"&gt;&lt;span style="color: green;"&gt;{ Obtem a identificação da mensagem ... }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
         &lt;span style="margin-left: 2em;"&gt;idMsg := iMap.MailBox.SearchResult[i];&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
          &lt;span style="margin-left: 2em;"&gt;&lt;span style="color: green;"&gt;{ ... e a usa para recuperar o email completo }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
          &lt;span style="margin-left: 2em;"&gt;iMap.Retrieve (idMsg, TheMsg);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;&lt;span style="color: green;"&gt;{ Analisa anexos e outros procedimentos }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color: navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
Veja que a a função de pesquisa aceita um  &lt;i&gt;array&lt;/i&gt; de filtros como parâmetro. Isso significa que podemos construir uma combinação de filtros para que uma lista mais refinada seja retornada. Outras possibilidades de filtros para pesquisar a caixa incluem o texto contido nas mensagens ou seus cabeçalhos, a data de recepção delas ou até mesmo seu tamanho.&lt;br /&gt;
&lt;br /&gt;
Um outro ponto importante a destacar é que o resultado da pesquisa é armazenado na propriedade &lt;b&gt;SearchResult&lt;/b&gt; do &lt;b&gt;MailBox&lt;/b&gt;. O resultado fica acessível como uma lista de identificadores das mensagens que atenderam o critério estipulado para a busca. Esses identificadores são números inteiros que podem ser usados em diversas funções da caixa postal, como a que recupera o conteúdo da mensagem ou que permite excluí-la.&lt;br /&gt;
&lt;br /&gt;
Uma vez que uma mensagem foi recuperada com sucesso, a instância da classe &lt;b&gt;TIdMessage&lt;/b&gt; nos dá acesso a todas as informações pertinentes a ela, incluindo os anexos, caso ela possua algum. O trecho que trata os anexos foi removido pra não poluir muito o quadro. Como a recuperação de anexos funciona exatamente igual ao do &lt;b&gt;POP3&lt;/b&gt;, o processo descrito no &lt;i&gt;post&lt;/i&gt; &lt;a href="http://balaiotecnologico.blogspot.com/2011/08/recuperando-emails-de-uma-caixa-postal.html"&gt;Recuperando emails de uma caixa postal com Delphi&lt;/a&gt; pode ser usado para realizar esse trabalho.&lt;br /&gt;
&lt;br /&gt;
Um outro recurso do &lt;b&gt;IMAP4&lt;/b&gt; é que você pode copiar mensagens da caixa atualmente selecionada pra uma outra caixa usando a função &lt;b&gt;CopyMsgs&lt;/b&gt;. Ela aceita 2 parâmetros : um &lt;i&gt;array&lt;/i&gt; com os identificadores das mensagens a serem copiadas e o nome da caixa postal que receberá as mensagens. Caso precise mover as mensagens, use essa função combinada com a &lt;b&gt;DeleteMsgs&lt;/b&gt;, que exclui uma lista de mensagens da caixa atual.&lt;br /&gt;
&lt;br /&gt;
O &lt;b&gt;IMAP4&lt;/b&gt; ainda disponibiliza funções para gerenciar as caixas postais. É possível criar uma caixa nova, renomer uma caixa e excluir caixas existentes. Os nomes das funções com esses objetivos são bastante intuitivos : &lt;b&gt;CreateMailBox&lt;/b&gt;, &lt;b&gt;DeleteMailBox&lt;/b&gt; e &lt;b&gt;RenameMailBox&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="background-color: #ffffdc; border: 1px solid silver; padding: 10px 5px 10px 5px; text-align: justify; width: 96%;"&gt;
&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border: 0; vertical-align: middle;" /&gt;&lt;span style="font-weight: bold; margin: 0pt 0pt 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://balaiotecnologico.blogspot.com/2011/08/recuperando-emails-de-uma-caixa-postal.html"&gt;Recuperando emails de uma caixa postal com POP3 em Delphi&lt;/a&gt;, &lt;a href="http://pt.wikipedia.org/wiki/Internet_Message_Access_Protocol"&gt;IMAP4&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-7591531105757258392?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Eo2ya_WnfByTKK0M5q53KbQ9MX0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Eo2ya_WnfByTKK0M5q53KbQ9MX0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Eo2ya_WnfByTKK0M5q53KbQ9MX0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Eo2ya_WnfByTKK0M5q53KbQ9MX0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/la2sQsDGLaY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/7591531105757258392/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/11/trabalhando-com-emails-em-uma-caixa.html#comment-form" title="3 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/7591531105757258392?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/7591531105757258392?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/la2sQsDGLaY/trabalhando-com-emails-em-uma-caixa.html" title="Trabalhando com emails em uma caixa postal usando IMAP4 em Delphi" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/11/trabalhando-com-emails-em-uma-caixa.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcHRn44eCp7ImA9WhdaFUs.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-7584122658789202962</id><published>2011-10-21T11:55:00.002-02:00</published><updated>2011-10-25T14:27:17.030-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-25T14:27:17.030-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="HTML" /><title>Trabalhando com a tag Canvas do HTML5 - parte IV</title><content type="html">Até agora , nos posts que escrevi sobre o uso do canvas do HTML5, quando precisei me referir a uma cor nos scripts de exemplo, eu  sempre usei a representação tradicional para cores estabelecida pelo &lt;a href="http://pt.wikipedia.org/wiki/Cascading_Style_Sheets"&gt;CSS&lt;/a&gt; (Cascading Style Sheet). Isto é, as cores sempre foram especificadas como uma mistura da intensidade de vermelho, verde e azul (o código RGB) que resultasse na cor desejada. Neste post, mostro que o Canvas permite aplicar um grau de transparência às cores e também trabalhar com gradientes de cores. &lt;br /&gt;
&lt;br /&gt;
As regras para cores no canvas são as mesmas definidas para o &lt;b&gt;CSS&lt;/b&gt;. Portanto, podemos usar aqui também a função &lt;b&gt;rgba()&lt;/b&gt;, que introduz um quarto parâmetro para controlar o nível de transparência de cores. Os 3 primeiros parâmetros são os conhecidos níveis de intensidade do vermelho, verde e azul (representados por números de 0 a 255). O último valor – chamado de &lt;b&gt;alpha&lt;/b&gt; – corresponde ao grau de transparência a ser aplicado aos desenhos subsequentes. Ele pode assumir valores entre 0 (completamente transparente) e 1 (desenha a imagem opaca, sobrepondo totalmente o fundo, sendo esse o efeito padrão obtido até aqui). &lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;"&gt;
&lt;center&gt; &lt;table &gt;&lt;tr&gt;&lt;td style="width:60%;"&gt; &lt;b&gt;var&lt;/b&gt; myCanvas = document.getElementById(&lt;span style="color:maroon;"&gt;"cnvCores2"&lt;/span&gt;);&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; ctx = myCanvas.getContext(&lt;span style="color:maroon;"&gt;"2d"&lt;/span&gt;);&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; incrY = myCanvas.height / 10;&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; grausFin = 360;&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; radFin = (Math.PI/180)* grausFin;&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; meioCompr = myCanvas.width / 2;&lt;br /&gt;
&lt;br /&gt;
ctx.font = &lt;span style="color:maroon;"&gt;"11px Arial"&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:green;"&gt;/* Primeiro, preenche com cor do fundo opaca */&lt;/span&gt;&lt;br /&gt;
ctx.fillStyle = &lt;span style="color:maroon;"&gt;'rgb(20,230,20)'&lt;/span&gt;;&lt;br /&gt;
ctx.fillRect(0, 0, meioCompr, myCanvas.height / 2);&lt;br /&gt;
ctx.fillRect(meioCompr, myCanvas.height / 2, meioCompr, myCanvas.height / 2);&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;for&lt;/b&gt; (&lt;b&gt;var&lt;/b&gt; i = 0; i &lt; 10;i++) {
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;/* agora, pinta por cima usando branco mas variando a transparência */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:1em;"&gt;ctx.fillStyle = &lt;span style="color:maroon;"&gt;'rgba(255,255,255,' + (1.0 - (i / 10.0)) + ')'&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:1em;"&gt;ctx.fillRect(0, i*incrY, meioCompr, incrY);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left:1em;"&gt;ctx.fillStyle = &lt;span style="color:maroon;"&gt;"navy"&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:1em;"&gt;ctx.fillText (Math.ceil (10.0 - i) / 10.0, 8, (i+1)*incrY - 4);&lt;/span&gt;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:green;"&gt;/* preenche no centro um círculo marrom com alto grau de transparência */&lt;/span&gt;&lt;br /&gt;
ctx.beginPath();&lt;br /&gt;
ctx.fillStyle = &lt;span style="color:maroon;"&gt;'rgba(128,0,0,0.4)'&lt;/span&gt;;&lt;br /&gt;
ctx.arc(meioCompr, myCanvas.height / 4, meioCompr, 0, radFin, false);&lt;br /&gt;
ctx.fill();&lt;br /&gt;
ctx.closePath();&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:green;"&gt;/* Como seria sem o parâmetro de transparência */&lt;/span&gt;&lt;br /&gt;
ctx.beginPath();&lt;br /&gt;
ctx.fillStyle = &lt;span style="color:maroon;"&gt;'rgb(128,0,0)'&lt;/span&gt;;&lt;br /&gt;
ctx.arc(meioCompr, 3 * myCanvas.height / 4, meioCompr, 0, radFin, false);&lt;br /&gt;
ctx.fill();   &lt;br /&gt;
ctx.closePath(); &lt;/td&gt;
 &lt;td&gt;&lt;canvas id="cnvCores2" style="border:1px solid silver;" width="200px" height="600px"&gt;Seu navegador (ou leitor de RSS) não suporta canvas ...&lt;/canvas&gt; &lt;script language="JavaScript" type="text/javascript"&gt;
function exemploCores ()  {
var myCanvas = document.getElementById("cnvCores2");
var ctx = myCanvas.getContext("2d");
var incrY = myCanvas.height / 20;
var grausFin = 360;
var radFin = (Math.PI/180)* grausFin;
var meioCompr = myCanvas.width / 2;

ctx.font = "11px Arial";

  /* Primeiro, preenche com cor do fundo opaca */
  ctx.fillStyle = 'rgb(20,230,20)';
  ctx.fillRect(0, 0, meioCompr, myCanvas.height / 2);
  ctx.fillRect(meioCompr, myCanvas.height / 2, meioCompr, myCanvas.height / 2);

  for (var i = 0; i &lt; 10;i++){
    /* agora, pinta por cima usando branco mas variando a transparência */
    ctx.fillStyle = 'rgba(255,255,255,' + (1.0 - (i / 10.0)) + ')';
    ctx.fillRect(0, i*incrY, meioCompr, incrY);
    
    ctx.fillStyle = "navy";    
    ctx.fillText (Math.ceil (10.0 - i) / 10.0, 8, (i+1)*incrY - 4);
  }
  
  /* preenche no centro um círculo marrom com alto grau de transparência */
  ctx.beginPath();
  ctx.fillStyle = 'rgba(128,0,0,0.4)';
  ctx.arc(meioCompr, myCanvas.height / 4, meioCompr, 0, radFin, false);
  ctx.fill();
  ctx.closePath();
  
  /* Como seria sem o parâmetro de transparência */
  ctx.beginPath();
  ctx.fillStyle = 'rgb(128,0,0)';
  ctx.arc(meioCompr, 3 * myCanvas.height / 4, meioCompr, 0, radFin, false);
  ctx.fill();   
  ctx.closePath();
 }

exemploCores ();

&lt;/script&gt;

&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;/center&gt;
&lt;/div&gt;
Parte do código é dedicada a escrever o grau de transparência de cada uma das faixas horizontais. Como o desenho de texto também é afetado pelo valor de &lt;b&gt;fillStyle&lt;/b&gt; - incluindo a transparência configurada nele -, eu atribuo a ela uma outra cor sólida para que o texto esteja plenamente visível, sem qualquer interferência do fundo previamente desenhado.&lt;br /&gt;
&lt;br /&gt;
Há uma propriedade do contexto de pintura chamada &lt;a href="http://dev.w3.org/html5/2dcontext/#dom-context-2d-globalalpha"&gt;globalAlpha&lt;/a&gt; que permite mudar o grau de transparência dos desenhos, influenciando preenchimentos e contornos num único comando. Essa característica tem sua utilidade, mas é menos flexível do que controlar separadamente pelo tipo de desenho.&lt;br /&gt;
&lt;br /&gt;
Uma outra forma de trabalhar com cores prevista no canvas do HTML5 é o preenchimento de áreas com um gradiente, isto é, a pintura é iniciada com uma cor e vai gradualmente se aproximando de uma segunda cor, que é finalmente usada para concluir a pintura. Estão previstos dois tipos de gradiente : um linear e outro radial. Para usar um deles, basta criar o tipo desejado, alimentar as cores que comporão o gradiente e então associá-lo à propriedade &lt;b&gt;fillStyle&lt;/b&gt; do contexto do Canvas, exatamente como fizemos com cores e transparências.&lt;br /&gt;
&lt;br /&gt;
O tipo linear é instanciado através da função &lt;a href="http://dev.w3.org/html5/2dcontext/#dom-context-2d-createlineargradient"&gt;createLinearGradient&lt;/a&gt; enquanto para o gradiente radial usamos &lt;a href="http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient"&gt;createRadialGradient&lt;/a&gt;. Ambos os métodos criam objetos que respeitam a especificação da interface &lt;a href="http://dev.w3.org/html5/2dcontext/#canvasgradient"&gt;CanvasGradient&lt;/a&gt;, atualmente composta por apenas uma função cujo objetivo é adicionar pontos de parada para as cores no gradiente. Ou seja, essa função define quantas cores básicas haverão no gradiente resultante e quanto espaço cada uma ocupará nele. As cores intermediárias são calculadas automaticamente de modo a preencher toda a área definida pela função de criação.&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;"&gt;
&lt;center&gt;
&lt;table&gt;&lt;tr&gt;&lt;td style="width:50%;"&gt;
&lt;span style="color:green;"&gt;/* Gradiente linear simples com 2 cores: uma vai do
início do retângulo até o meio e a outra do meio até o fim */&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; lineargradient = ctx.createLinearGradient(0,0,120,120);&lt;br /&gt;
lineargradient.addColorStop (0, &lt;span style="color:maroon;"&gt;'navy'&lt;/span&gt;);&lt;br /&gt;
lineargradient.addColorStop (0.5, &lt;span style="color:maroon;"&gt;'rgb(50,50,180)'&lt;/span&gt;);&lt;br /&gt;
lineargradient.addColorStop (1, &lt;span style="color:maroon;"&gt;'rgb(120,120,220)'&lt;/span&gt;);&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:green;"&gt;/* Preenche o retângulo real com o padrão gradiente criado acima */&lt;/span&gt;&lt;br /&gt;
ctx.fillStyle = lineargradient &lt;br /&gt;
ctx.fillRect (0,0,180,180);&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:green;"&gt;/* Outro gradiente, agora com mais cores ... */&lt;/span&gt;&lt;br /&gt;
lineargradient = ctx.createLinearGradient(0,200,180,280);&lt;br /&gt;
lineargradient.addColorStop (0, &lt;span style="color:maroon;"&gt;'navy'&lt;/span&gt;);&lt;br /&gt;
lineargradient.addColorStop (0.2, &lt;span style="color:maroon;"&gt;'red'&lt;/span&gt;);&lt;br /&gt;
lineargradient.addColorStop (0.8, &lt;span style="color:maroon;"&gt;'rgb(50,50,180)'&lt;/span&gt;);&lt;br /&gt;
lineargradient.addColorStop (1, &lt;span style="color:maroon;"&gt;'green'&lt;/span&gt;);&lt;br /&gt;
&lt;br /&gt;
ctx.fillStyle = lineargradient &lt;br /&gt;
ctx.fillRect (0,200,180, 280);
&lt;/td&gt;
    &lt;td style="width:50%;"&gt;&lt;canvas id="cnvGrad" style="border:1px solid silver;" width="200px" height="500px"&gt;
Seu navegador (ou leitor de RSS) não suporta canvas ... 
&lt;/canvas&gt;
&lt;script language="JavaScript" type="text/javascript"&gt;
function exemploGrad1 ()  {
var myCanvas = document.getElementById("cnvGrad");
var ctx = myCanvas.getContext("2d");

var lineargradient = ctx.createLinearGradient(0,0,120,120);
lineargradient.addColorStop (0, 'navy');
lineargradient.addColorStop (0.5, 'rgb(50,50,180)');
lineargradient.addColorStop (1, 'rgb(120,120,220)');

ctx.fillStyle = lineargradient 
ctx.fillRect (0,0,180,180);

lineargradient = ctx.createLinearGradient(0,200,180,280);
lineargradient.addColorStop (0, 'navy');
lineargradient.addColorStop (0.2, 'red');
lineargradient.addColorStop (0.8, 'rgb(50,50,180)');
lineargradient.addColorStop (1, 'green');

ctx.fillStyle = lineargradient 
ctx.fillRect (0,200,180, 280);
}
exemploGrad1 ();
&lt;/script&gt;

&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;
A função &lt;b&gt;createLinearGradient&lt;/b&gt; cria uma área retangular - definida por pontos que indicam o canto superior esquerdo e o inferior direito. O gradiente é criado nesse retângulo virtual e ele então é usado para preencher o retângulo real no canvas. Como o retângulo real pode ter tamanho diferente daquele usado para criar o gradiente, o canvas faz alguns ajustes para que caiba. Se o retângulo real for maior, a última cor de parada é usada para preencher o resto da área.&lt;br /&gt;
&lt;br /&gt;
Veja que para adicionarmos uma cor de parada temos que informar um valor entre 0 e 1. Esse valor é chamado de &lt;i&gt;offset&lt;/i&gt; e indica a que distância do início do retângulo a nova cor deve começar a aparecer. Uma cor prevalece até que a próxima cor de parada seja encontrada. Então, o tanto de espaço ocupado por cada uma é definido pelo &lt;i&gt;offset&lt;/i&gt; da parada seguinte.&lt;br /&gt;
&lt;br /&gt;
Para o gradiente radial, a principal diferença é que, ao invés do efeito ser aplicado num retângulo, ele é aplicado numa área delimitada por dois círculos Os círculos são definidos na criação do gradiente, sendo que os 3 primeiros parâmetros correspondem ao ponto central e raio do círculo inicial e os 3 parâmetros seguintes correspondem ao ponto central e raio do círculo final. A área fora dos círculos é mantida com a cor original da área preenchida.
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;"&gt;
&lt;center&gt;
&lt;table&gt;&lt;tr&gt;&lt;td&gt;
&lt;span style="color:green;"&gt;/* Círculo com gradiente */&lt;/span&gt;
  &lt;b&gt;var&lt;/b&gt; radgrad = ctx.createRadialGradient (105, 115, 20, 112, 130, 50);&lt;br /&gt;
  radgrad.addColorStop(0, &lt;span style="color:maroon;"&gt;'#FF5F98'&lt;/span&gt;);&lt;br /&gt;
  radgrad.addColorStop(0.75, &lt;span style="color:maroon;"&gt;'#FF0188'&lt;/span&gt;);&lt;br /&gt;
  radgrad.addColorStop(1, &lt;span style="color:maroon;"&gt;'rgba(255,1,136,0)'&lt;/span&gt;);&lt;br /&gt;
&lt;span style="color:green;"&gt;/* Ao preencher retângulo, somente a área com o gradiente circular é considerada !*/&lt;/span&gt;&lt;br /&gt;
  ctx.fillStyle = radgrad;&lt;br /&gt;
  ctx.fillRect(0,0,250,500);&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:green;"&gt;/* Outro círculo com gradiente */&lt;/span&gt;&lt;br /&gt;
  radgrad = ctx.createRadialGradient(95,35,15,102,40,40);&lt;br /&gt;
  radgrad.addColorStop(0, &lt;span style="color:maroon;"&gt;'#00C9FF'&lt;/span&gt;);&lt;br /&gt;
  radgrad.addColorStop(0.8, &lt;span style="color:maroon;"&gt;'#00B5E2'&lt;/span&gt;);&lt;br /&gt;
  radgrad.addColorStop(1, &lt;span style="color:maroon;"&gt;'rgba(0,201,255,0)'&lt;/span&gt;);&lt;br /&gt;
  ctx.fillStyle = radgrad;&lt;br /&gt;
  ctx.fillRect(0,0,250,500);&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:green;"&gt;/* Aqui , a área circular resultante é maior que o retângulo; então, o retângulo todo é preenchido */&lt;/span&gt;&lt;br /&gt;
radgrad = ctx.createRadialGradient (200, 350, 65, 200, 350, 140);&lt;br /&gt;
radgrad.addColorStop (0, &lt;span style="color:maroon;"&gt;'navy'&lt;/span&gt;);&lt;br /&gt;
radgrad.addColorStop (0.5, &lt;span style="color:maroon;"&gt;'rgb(50,50,180)'&lt;/span&gt;);&lt;br /&gt;
radgrad.addColorStop (1, &lt;span style="color:maroon;"&gt;'rgb(120,120,220)'&lt;/span&gt;);&lt;br /&gt;
ctx.fillStyle = radgrad &lt;br /&gt;
ctx.fillRect (50,200,150,150);
&lt;/td&gt;
    &lt;td style="width:60%;"&gt;&lt;canvas id="cnvGradR" style="border:1px solid silver;" width="200px" height="400px"&gt;
Seu navegador (ou leitor de RSS) não suporta canvas ... 
&lt;/canvas&gt;
&lt;script language="JavaScript" type="text/javascript"&gt;
function exemploGrad2 () {
var myCanvas = document.getElementById("cnvGradR");
var ctx = myCanvas.getContext("2d");

  var radgrad = ctx.createRadialGradient(105,115,20,112,130,50);
  radgrad.addColorStop(0, '#FF5F98');
  radgrad.addColorStop(0.75, '#FF0188');
  radgrad.addColorStop(1, 'rgba(255,1,136,0)');
  ctx.fillStyle = radgrad;
  ctx.fillRect(0,0,250,500);

  radgrad = ctx.createRadialGradient(95,35,15,102,40,40);
  radgrad.addColorStop(0, '#00C9FF');
  radgrad.addColorStop(0.8, '#00B5E2');
  radgrad.addColorStop(1, 'rgba(0,201,255,0)');
  ctx.fillStyle = radgrad;
  ctx.fillRect(0,0,250,500);

radgrad = ctx.createRadialGradient(200,350,65,200,350,140);
radgrad.addColorStop (0, 'navy');
radgrad.addColorStop (0.5, 'rgb(50,50,180)');
radgrad.addColorStop (1, 'rgb(120,120,220)');

ctx.fillStyle = radgrad 
ctx.fillRect (50,200,150,150);
}
exemploGrad2 ();
&lt;/script&gt;

&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;

Parte do exemplo acima foi retirada do &lt;a href="https://developer.mozilla.org/en/Canvas_tutorial/Applying_styles_and_colors"&gt;tutorial de canvas da Fundação Mozilla&lt;/a&gt;. Veja que a criação do gradiente aceita a função &lt;b&gt;rgba()&lt;/b&gt;, significando que podemos aplicar transparência neste momento também.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;
&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
Trabalhando com a tag Canvas do HTML5 - &lt;a href="http://balaiotecnologico.blogspot.com/2011/08/trabalhando-com-tag-canvas-do-html5.html"&gt;parte I&lt;/a&gt;, &lt;a href="http://balaiotecnologico.blogspot.com/2011/09/trabalhando-com-tag-canvas-do-html5_06.html"&gt;parte II&lt;/a&gt; e &lt;a href="http://balaiotecnologico.blogspot.com/2011/09/trabalhando-com-tag-canvas-do-html5.html"&gt;parte III&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en/Canvas_tutorial"&gt;Tutorial de Canvas na Fundação Mozilla&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-7584122658789202962?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/1JruAXmBnq0ALcFbePNG0BgZh_E/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1JruAXmBnq0ALcFbePNG0BgZh_E/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/1JruAXmBnq0ALcFbePNG0BgZh_E/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1JruAXmBnq0ALcFbePNG0BgZh_E/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/4XjsqeiNPUA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/7584122658789202962/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/10/trabalhando-com-tag-canvas-do-html5.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/7584122658789202962?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/7584122658789202962?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/4XjsqeiNPUA/trabalhando-com-tag-canvas-do-html5.html" title="Trabalhando com a tag Canvas do HTML5 - parte IV" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/10/trabalhando-com-tag-canvas-do-html5.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkECRXwycCp7ImA9WhdUGU8.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-2037436505082819472</id><published>2011-10-06T15:11:00.000-03:00</published><updated>2011-10-06T15:11:04.298-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-06T15:11:04.298-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Design Patterns" /><title>Design Patterns com Delphi: Strategy - Parte II</title><content type="html">No último post, eu apresentei o conceito e a  aplicabilidade do &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html"&gt;Design Pattern&lt;/a&gt; &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html#categorias"&gt;comportamental&lt;/a&gt; &lt;b&gt;Strategy&lt;/b&gt;. Aqui, vou mostrar como implementar em Delphi o exemplo prático utilizado naquele post, relacionado a pagamento de títulos. Para facilitar o entendimento, reproduzo abaixo o diagrama UML com a sugestão de modelagem proposta:
&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;width: 96%;"&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lgaf.webs.com/arqs/Strategy.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;width:100%;" src="http://lgaf.webs.com/arqs/Strategy.gif" alt="Diagrama UML para o padrão Strategy" id="designPatternStrategy20111004" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
A implementação das relações expostas no diagrama não é especialmente complexa. Ela envolve apenas conceitos comuns da programação orientada a objetos, como herança e polimorfismo.&lt;br/&gt;
&lt;br/&gt;
O primeiro passo é declarar uma classe abstrata (ou interface, se preferir), definindo nela as linhas mestras que deverão ser respeitadas por todos as implementações reais do algoritmo em questão. Isto é, essa classe introduz funções que determinam a estratégia para execução da tarefa, impondo-a a todas as classes que queiram atuar como um algoritmo alternativo para a tarefa - daí o nome do padrão ser &lt;b&gt;Strategy&lt;/b&gt;:
&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
TWTitulo = &lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;;&lt;br/&gt;
&lt;br/&gt;
TWPagamento=&lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; efetuaPgto (ATitulo: TWTitulo) : integer;&lt;span style="color:navy;"&gt;&lt;b&gt;virtual&lt;/b&gt;&lt;/span&gt;;&lt;span style="color:navy;"&gt;&lt;b&gt;abstract&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
Nesse exemplo, há uma única função abstrata que obrigatoriamente terá que existir em cada nova implementação do algoritmo. Essa função aceita como parâmetro uma instância da classe &lt;b&gt;Context&lt;/b&gt; da solução, papel encarnado aqui pelo título a pagar (&lt;b&gt;TWTitulo&lt;/b&gt;). Com isso, qualquer algoritmo que adote a estratégia definida tem acesso às informações relevantes do título, bem como a suas operações. Permitir essa comunicação é imprescindível para que a tarefa (o pagamento do título) possa ser concretizada.&lt;br/&gt;
&lt;br/&gt;
Agora que temos a interface estabelecida, podemos adicionar os diferentes algoritmos previstos no diagrama, criando cada um deles como uma herança simples que forneça código para a função abstrata da interface:
&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;TWContaBancaria = &lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;;&lt;br/&gt;
&lt;br/&gt;
  TWPgtoBoleto=&lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWPagamento)&lt;br/&gt;
    &lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;br/&gt;
    &lt;span style="color:navy;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; efetuaPgto (ATitulo: TWTitulo) : integer;&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br/&gt;
&lt;br/&gt;
  TWPgtoDebitoAuto=&lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWPagamento)&lt;br/&gt;
    &lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;_Conta : TWContaBancaria;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="color:navy;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;constructor&lt;/b&gt;&lt;/span&gt; Create (AConta: TWContaBancaria);&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; efetuaPgto (ATitulo: TWTitulo) : integer;&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br/&gt;
  &lt;br/&gt;
  TWPgtoInternet=&lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWPagamento)&lt;br/&gt;
    &lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;br/&gt;
    &lt;span style="color:navy;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; efetuaPgto (ATitulo: TWTitulo) : integer;&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;implementation&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;constructor&lt;/b&gt;&lt;/span&gt; TWPgtoDebitoAuto.Create (AConta: TWContaBancaria);&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;_Conta := AConta;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ ... }&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; TWPgtoDebitoAuto.efetuaPgto (ATitulo: TWTitulo) : integer;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;_Conta.Conecta;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;_Conta.DebitaValor(ATitulo.ObtemValor);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;ATitulo.RegistraPagto;&lt;/span&gt;  &lt;br/&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ ... }&lt;/span&gt;  &lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
A implementação da &lt;b&gt;TWPgtoDebitoAuto&lt;/b&gt; no quadro acima mostra que podem ser necessárias outras informações para que a tarefa seja executada num determinado algorítmo. A função que executa a tarefa, no entanto, foi fixada na classe base (a interface) e não deve ser alterada já que isso implicaria que todas as outras heranças teriam que respeitar os novos parâmetros, o que nem sempre é desejável. Então, uma solução é passar as informações extras no construtor da própria classe.&lt;br /&gt;
&lt;br /&gt;
Esse detalhe tem que ser levado em conta pela &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/design-patterns-com-delphi-factory.html"&gt;Factory&lt;/a&gt; responsável pela criação de instâncias da classe de pagamento. De acordo com o conceito de &lt;b&gt;Factory&lt;/b&gt;, devemos criar uma função que centraliza a instanciação de uma família de classes:
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;TWTipoPagto = (tpBoleto, tpDebitoAuto, tpInternet);&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; CriaNovoPagto (ATipo: TWTipoPagto; AContaDebito : TWContaBancaria) : TWPagamento;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;Result := &lt;span style="color:navy;"&gt;&lt;b&gt;Nil&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;case&lt;/b&gt;&lt;/span&gt; (ATipo) &lt;span style="color:navy;"&gt;&lt;b&gt;of&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;tpBoleto: &lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;Result :=  TWPgtoBoleto.Create;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;tpDebitoAuto: &lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;Result := TWPgtoDebitoAuto.Create (AContaDebito);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;tpInternet: &lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;Result := TWPgtoInternet.Create;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="color:navy;margin-left:1em;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
O último aspecto que falta abordar é com relação às características da classe de contexto &lt;b&gt;TWTitulo&lt;/b&gt;. Além de propriedades inerentes a títulos - como seu valor, data de vencimento, código de barras, identificação do beneficiário, etc. - essa classe terá que manter uma instância da classe base de estratégia (o pagamento) para poder trocar mensagens com ela.
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;TWTitulo=&lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="color:navy;"&gt;&lt;b&gt;protected&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;_Id : String;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;_DataVencto : TDateTime;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;_Valor : Double;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;_Pagto : TWPagamento;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;_FoiPago : Boolean;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; RegistraPagto;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:green;margin-left:2em;"&gt;{ ... }&lt;/span&gt;  &lt;br/&gt;
    &lt;span style="color:navy;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; ObtemValor : Double;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; Pagar (AMeioPgto: TWTipoPagto): integer;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:green;margin-left:2em;"&gt;{ ... }&lt;/span&gt;  &lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:green;margin-left:2em;"&gt;{ ... }&lt;/span&gt;  &lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; TWTitulo.Pagar (AMeioPgto: TWTipoPagto): integer;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (_Pagto = &lt;span style="color:navy;"&gt;&lt;b&gt;Nil&lt;/b&gt;&lt;/span&gt;) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;_Pagto := CriaNovoPagto (AMeioPgto, _Sessao.ObtemContaBancaria);&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;_Pagto.efetuaPgto (&lt;span style="color:navy;"&gt;&lt;b&gt;Self&lt;/b&gt;&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
Com isso, temos a classe de contexto armazenando internamente uma instância do pagamento (a estratégia) e controlando seu ciclo de vida. A instância fica disponível para que o contexto possa utilizá-la sempre que for necessário executar a tarefa embutida nela.&lt;br /&gt;
&lt;br /&gt;
Note que a solução fica aberta para receber facilmente novos algoritmos, preservando o fraco acoplamento entre as classes já previstas e implementadas. Assim, poucos pontos têm que ser alterados para se introduzir uma nova forma de realizar a tarefa: basta codificar a nova classe e prever a criação de suas instâncias na função &lt;b&gt;factory&lt;/b&gt;.&lt;br/&gt;
&lt;br/&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;
&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;
&lt;a href="http://balaiotecnologico.blogspot.com/2011/09/design-patterns-com-delphi-strategy.html"&gt;Design Patterns com Delphi: Strategy - Parte I&lt;/a&gt;, &lt;a href="http://balaiotecnologico.blogspot.com/search/label/Design%20Patterns"&gt;Posts sobre Design Patterns&lt;/a&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-2037436505082819472?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vuKfK7SvZyuCZGptpUrHFz_iYMo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vuKfK7SvZyuCZGptpUrHFz_iYMo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vuKfK7SvZyuCZGptpUrHFz_iYMo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vuKfK7SvZyuCZGptpUrHFz_iYMo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/G_yHKpYASz8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/2037436505082819472/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/10/design-patterns-com-delphi-strategy.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/2037436505082819472?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/2037436505082819472?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/G_yHKpYASz8/design-patterns-com-delphi-strategy.html" title="Design Patterns com Delphi: Strategy - Parte II" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/10/design-patterns-com-delphi-strategy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYAQXo4eyp7ImA9WhdUE00.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-3630738593966235676</id><published>2011-09-29T11:22:00.000-03:00</published><updated>2011-09-29T11:22:20.433-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-29T11:22:20.433-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Design Patterns" /><title>Design Patterns com Delphi: Strategy - Parte I</title><content type="html">Certas tarefas em um sistema computacional podem ser implementadas de diferentes maneiras sem que isso afete o resultado final esperado. Isto é, partindo de um determinado contexto, podemos selecionar um algoritmo entre vários possíveis e atingir o mesmo objetivo com qualquer um deles. Por exemplo, dada uma lista que precisa ser ordenada, há diversos &lt;a href="http://pt.wikipedia.org/wiki/Algoritmo_de_ordena%C3%A7%C3%A3o"&gt;algoritmos de ordenação&lt;/a&gt; que podem realizar a tarefa, como o método da bolha, &lt;i&gt;quick sort&lt;/i&gt; ou busca binária. Independentemente do algoritmo escolhido, ao final do processo teremos a lista classificada. É claro que há diferenças de performance de um método pra outro mas isso é parte do processo de escolha daquele que melhor se adapta a uma situação. Cada situação encontrada pode levar a uma escolha distinta, sem que uma seja necessariamente preferida em relação às outras.&lt;br /&gt;
&lt;br /&gt;
O programa pode, então, ter que intercambiar dinamicamente o algoritmo, seja por opção explícita do usuário ou por causa de outras questões circunstanciais encontradas durante a execução. Em projetos orientados a objetos, podemos desenhar uma solução para esse tipo de cenário usando o  &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html"&gt;Design Pattern&lt;/a&gt; &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html#categorias"&gt;comportamental&lt;/a&gt; &lt;b&gt;Strategy&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
O objetivo do &lt;b&gt;Strategy&lt;/b&gt; é permitir que o programa utilize de forma transparente qualquer algoritmo capaz de realizar uma determinada tarefa, construindo para isso uma estrutura de classes com baixo acoplamento. Com isso, fica fácil adicionar novos algoritmos, enquanto os códigos que os utilizarão continuam independentes da escolha feita.&lt;br /&gt;
&lt;br /&gt;
Num sistema real, essa solução pode ser aplicada, por exemplo, no pagamento de títulos. Considere que um título pode ser pago levando o respectivo boleto ao banco, cadastrando a conta como débito automático ou registrando o pagamento no &lt;i&gt;Internet Banking&lt;/i&gt;. Qualquer que seja a forma selecionada, o resultado é o título pago. O diagrama &lt;a href="http://pt.wikipedia.org/wiki/UML"&gt;UML&lt;/a&gt; abaixo mostra as classes e suas relações para o &lt;b&gt;Strategy&lt;/b&gt; aplicado a este cenário:&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;width: 96%;"&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lgaf.webs.com/arqs/Strategy.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;width:100%;" src="http://lgaf.webs.com/arqs/Strategy.gif" alt="Diagrama UML para o padrão Strategy" id="designPatternStrategy20110928" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
A nomenclatura formal para as classes que participam da solução com o &lt;i&gt;pattern&lt;/i&gt; &lt;b&gt;Strategy&lt;/b&gt; é a seguinte:
&lt;div style="border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;A classe &lt;b&gt;Strategy&lt;/b&gt; é uma interface onde é definido o comportamento comum a ser respeitado por todos os algoritmos. Em outras palavras, devemos incluir nesta classe funções virtuais (e provavelmente abstratas) que fixarão a forma com que a tarefa estará acessível às outras partes do programa. A classe &lt;b&gt;TWPagamento&lt;/b&gt; do diagrama acima exerce esse papel, definindo que pagamentos deverão ser feitos através da função &lt;i&gt;efetuaPgto&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;São chamadas de &lt;b&gt;Concrete Strategy&lt;/b&gt; as classes que atendem a definição introduzida no &lt;b&gt;Strategy&lt;/b&gt; e que, portanto, implementam um algoritmo que efetivamente realize a tarefa proposta. No diagrama, esse papel cabe a três classes distintas : &lt;b&gt;TWPgtoBoleto&lt;/b&gt;, &lt;b&gt;TWPgtoDebitoAuto&lt;/b&gt; e &lt;b&gt;TWPgtoInternete&lt;/b&gt;. Cada uma delas executará a tarefa a sua maneira, providenciando uma versão própria da função &lt;i&gt;efetuaPgto&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;O &lt;b&gt;Context&lt;/b&gt; é a classe que usará o comportamento definido pela &lt;b&gt;Strategy&lt;/b&gt;, invocando as funções disponibilizadas por ela. Portanto, o &lt;b&gt;Context&lt;/b&gt; deverá armazenar internamente uma referência ao &lt;b&gt;Strategy&lt;/b&gt;. Em geral, ele também terá que expor formas de interagir com o &lt;b&gt;Strategy&lt;/b&gt;, publicando propriedade e funções. No nosso exemplo, o &lt;b&gt;Context&lt;/b&gt; é a classe &lt;b&gt;TWTitulo&lt;/b&gt;; a interação com o &lt;b&gt;Strategy&lt;/b&gt; é conseguida passando-se para a tarefa uma instância do próprio título a ser pago.&lt;br /&gt;
&lt;br /&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;Um &lt;b&gt;Client&lt;/b&gt; é qualquer parte do sistema que solicite uma operação à classe &lt;b&gt;Context&lt;/b&gt;. Esse tipo de classe foi omitido do diagrama.&lt;/div&gt;
No próximo post, mostro uma sugestão de como implementar na prática essa solução usando o Delphi.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://balaiotecnologico.blogspot.com/search/label/Design%20Patterns"&gt;Posts sobre Design Patterns&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-3630738593966235676?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/qs2gGfL5DXuP4DUNSQV4tF6ZshQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qs2gGfL5DXuP4DUNSQV4tF6ZshQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/qs2gGfL5DXuP4DUNSQV4tF6ZshQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qs2gGfL5DXuP4DUNSQV4tF6ZshQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/yJbi4MAcGKE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/3630738593966235676/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/09/design-patterns-com-delphi-strategy.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/3630738593966235676?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/3630738593966235676?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/yJbi4MAcGKE/design-patterns-com-delphi-strategy.html" title="Design Patterns com Delphi: Strategy - Parte I" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/09/design-patterns-com-delphi-strategy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck8HR3g9fCp7ImA9WhdbEE8.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-4095793666167895894</id><published>2011-09-23T16:03:00.000-03:00</published><updated>2011-10-07T17:53:56.664-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-07T17:53:56.664-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="HTML" /><title>Trabalhando com a tag Canvas do HTML5 - parte III</title><content type="html">Dando continuidade aos posts sobre uso da tag Canvas (veja &lt;a href="http://balaiotecnologico.blogspot.com/2011/08/trabalhando-com-tag-canvas-do-html5.html"&gt;parte I&lt;/a&gt; e &lt;a href="http://balaiotecnologico.blogspot.com/2011/09/trabalhando-com-tag-canvas-do-html5_06.html"&gt;parte II&lt;/a&gt;), falo aqui sobre o uso de textos no canvas e a manipulação de imagens.&lt;br /&gt;
&lt;br /&gt;
As propriedades básicas disponíveis para formatarmos a exibição de textos no Canvas são o tipo de fonte e a cor para o desenho. O tipo do fonte pode ser modificado através da propriedade &lt;b&gt;font&lt;/b&gt;. Como a interpretação do valor contido nessa propriedade é idêntica ao de &lt;a href="http://en.wikipedia.org/wiki/Cascading_Style_Sheets"&gt;folhas de estilo CSS&lt;/a&gt;, podemos configurar com ela a família do fonte (Arial, Tahoma, Courier, etc.), o tamanho das letras e estilos especiais (negrito, itálico, etc.).&lt;br /&gt;
&lt;br /&gt;
Quando trabalhamos com figuras geométricas &lt;a href="http://balaiotecnologico.blogspot.com/2011/09/trabalhando-com-tag-canvas-do-html5_06.html"&gt;no outro post&lt;/a&gt;, vimos que há duas formas de comandar um desenho : traçando apenas a borda ou preenchendo também o interior da figura, sendo que as cores para um ou outro são configuradas em propriedades separadas. O mesmo vale para o desenho de textos.&lt;br /&gt;
&lt;br /&gt;
Assim, a propriedade &lt;b&gt;fillStyle&lt;/b&gt; conterá a cor para preencher o texto quando este for desenhado usando a função &lt;b&gt;fillText&lt;/b&gt;. Por outro lado, a propriedade &lt;b&gt;strokeStyle&lt;/b&gt; define a cor das bordas do texto vazado a ser desenhado usando a função &lt;b&gt;strokeText&lt;/b&gt;. Ambas as propriedades aceitam valores que estejam em conformidade com as regras de definição de cores estabelecidas pelo padrão CSS. Veja um exemplo :&lt;br /&gt;
&lt;div style="font-size:8pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 97%;"&gt;&lt;center&gt; &lt;table&gt;&lt;tr&gt;&lt;td style="width:50%;"&gt;&lt;b&gt;var&lt;/b&gt; myCanvas = document.getElementById(&lt;span style="color:maroon"&gt;"cnvText2"&lt;/span&gt;);&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; ctx = myCanvas.getContext(&lt;span style="color:maroon"&gt;"2d"&lt;/span&gt;);&lt;br /&gt;
&lt;br /&gt;
ctx.fillText (&lt;span style="color:maroon"&gt;"Fonte e cores padrões"&lt;/span&gt;, &lt;span style="color:blue;"&gt;5&lt;/span&gt;, &lt;span style="color:blue;"&gt;20&lt;/span&gt;);&lt;br /&gt;
&lt;br /&gt;
ctx.font = &lt;span style="color:maroon"&gt;"bold 16px Verdana"&lt;/span&gt;;&lt;br /&gt;
ctx.fillStyle = &lt;span style="color:maroon"&gt;"blue"&lt;/span&gt;;&lt;br /&gt;
ctx.fillText (&lt;span style="color:maroon"&gt;"Verdana 16px negrito"&lt;/span&gt;, &lt;span style="color:blue;"&gt;5&lt;/span&gt;, &lt;span style="color:blue;"&gt;40&lt;/span&gt;);&lt;br /&gt;
&lt;br /&gt;
ctx.font = &lt;span style="color:maroon"&gt;"20px Courier"&lt;/span&gt;;&lt;br /&gt;
ctx.strokeStyle = &lt;span style="color:maroon"&gt;"#0FAF0F"&lt;/span&gt;;&lt;br /&gt;
ctx.strokeText (&lt;span style="color:maroon"&gt;"Courier 20px stroke"&lt;/span&gt;, &lt;span style="color:blue;"&gt;5&lt;/span&gt;, &lt;span style="color:blue;"&gt;65&lt;/span&gt;);&lt;br /&gt;
&lt;br /&gt;
ctx.font = &lt;span style="color:maroon"&gt;"36px Arial"&lt;/span&gt;;&lt;br /&gt;
ctx.strokeStyle = &lt;span style="color:maroon"&gt;"maroon"&lt;/span&gt;;&lt;br /&gt;
ctx.strokeText (&lt;span style="color:maroon"&gt;"Arial 36px stroke"&lt;/span&gt;, &lt;span style="color:blue;"&gt;5&lt;/span&gt;, &lt;span style="color:blue;"&gt;100&lt;/span&gt;);&lt;/td&gt;     &lt;td style="width:50%;"&gt;&lt;canvas id="cnvText2"&gt; Seu navegador (ou leitor de RSS) não suporta canvas ... &lt;/canvas&gt; &lt;script language="JavaScript" type="text/javascript"&gt;

var myCanvas = document.getElementById("cnvText2");
var ctx = myCanvas.getContext("2d");

ctx.fillText ("Fonte e cores padrões", 5, 20);

ctx.font = "bold 16px Verdana";
ctx.fillStyle = "blue";
ctx.fillText ("Verdana 16px negrito", 5, 40);

ctx.font = "20px Courier";
ctx.strokeStyle = "#0FAF0F";
ctx.strokeText ("Courier 20px stroke", 5, 65);

ctx.font = "36px Arial";
ctx.strokeStyle = "maroon";
ctx.strokeText ("Arial 36px stroke", 5, 100);
&lt;/script&gt; &lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;/center&gt; &lt;/div&gt;&lt;br /&gt;
Usando fontes pequenas, o efeito de desenhar somente a borda acaba diluído, dando a impressão que o texto está todo preenchido. Portanto, ele funciona melhor com fontes maiores.&lt;br /&gt;
&lt;br /&gt;
Conforme vemos no quadro anterior, as funções de desenho de texto aceitam 3 parâmetros : o próprio texto que será escrito e as coordenadas da posição no canvas onde ele deve ser renderizado. Normalmente, a posição indica o canto superior esquerdo de um retângulo virtual que conterá o texto. O significado dessa posição, no entanto, pode variar de acordo com o valor das propriedades &lt;a href="http://dev.w3.org/html5/2dcontext/#dom-context-2d-textalign"&gt;textAlign&lt;/a&gt; e &lt;a href="http://dev.w3.org/html5/2dcontext/#dom-context-2d-textbaseline"&gt;textBaseline&lt;/a&gt;. A primeira altera a interpretação do posicionamento horizontal do texto enquanto a segunda controla a coordenada vertical. Não é muito comum ter que alterar esses valores pois, no geral, os valores originais dão conta do recado.&lt;br /&gt;
&lt;br /&gt;
Poderíamos ainda ter passado como 4o parâmetro o comprimento máximo que o texto deve ocupar - caso o tamanho real exceda esse valor, o tamanho do fonte é alterado automaticamente para que o texto caiba.&lt;br /&gt;
&lt;br /&gt;
Um outro aspecto para incrementar a renderização de textos é a criação do efeito de sombra. Essa característica é controlada pelas propriedades &lt;b&gt;shadowColor&lt;/b&gt; - que corresponde à cor da sombra - e o par &lt;b&gt;shadowOffsetX&lt;/b&gt; e &lt;b&gt;shadowOffsetY&lt;/b&gt; - respectivamente, o deslocamento horizontal e vertical da sombra a ser projetada em relação ao texto. É possível também esfumaçar a sombra, deixando o efeito mais sutil. Consegue-se isso usando a propriedade &lt;b&gt;shadowBlur&lt;/b&gt;, cujo valor indica o quão borrada deve ser a sombra projetada. Seguem alguns exemplos:&lt;br /&gt;
&lt;div style="font-size:8pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 97%;"&gt;&lt;center&gt; &lt;table&gt;&lt;tr&gt;&lt;td style="width:50%;"&gt; ctx.font = &lt;span style="color:maroon;"&gt;"18pt Arial"&lt;/span&gt;;&lt;br /&gt;
ctx.fillStyle = &lt;span style="color:maroon;"&gt;"#0F0FA0"&lt;/span&gt;;&lt;br /&gt;
ctx.shadowColor = &lt;span style="color:maroon;"&gt;"gray"&lt;/span&gt;;&lt;br /&gt;
ctx.shadowOffsetX = &lt;span style="color:blue;"&gt;3&lt;/span&gt;;&lt;br /&gt;
ctx.shadowOffsetY = &lt;span style="color:blue;"&gt;3&lt;/span&gt;;&lt;br /&gt;
ctx.fillText (&lt;span style="color:maroon;"&gt;"Texto com sombra comum"&lt;/span&gt;, &lt;span style="color:blue;"&gt;5&lt;/span&gt;, &lt;span style="color:blue;"&gt;40&lt;/span&gt;);&lt;br /&gt;
&lt;br /&gt;
ctx.fillStyle = &lt;span style="color:maroon;"&gt;"#7F0FA0"&lt;/span&gt;;&lt;br /&gt;
ctx.shadowColor = &lt;span style="color:maroon;"&gt;"black"&lt;/span&gt;;&lt;br /&gt;
ctx.shadowOffsetX = &lt;span style="color:blue;"&gt;2&lt;/span&gt;;&lt;br /&gt;
ctx.shadowOffsetY = &lt;span style="color:blue;"&gt;2&lt;/span&gt;;&lt;br /&gt;
ctx.shadowBlur = &lt;span style="color:blue;"&gt;2&lt;/span&gt;;&lt;br /&gt;
ctx.fillText (&lt;span style="color:maroon;"&gt;"Texto com sombra borrada"&lt;/span&gt;, &lt;span style="color:blue;"&gt;5&lt;/span&gt;, &lt;span style="color:blue;"&gt;70&lt;/span&gt;);&lt;br /&gt;
&lt;br /&gt;
ctx.fillStyle = &lt;span style="color:maroon;"&gt;"green"&lt;/span&gt;;&lt;br /&gt;
ctx.shadowColor = &lt;span style="color:maroon;"&gt;"black"&lt;/span&gt;;&lt;br /&gt;
ctx.shadowOffsetX = &lt;span style="color:blue;"&gt;2&lt;/span&gt;;&lt;br /&gt;
ctx.shadowOffsetY = &lt;span style="color:blue;"&gt;2&lt;/span&gt;;&lt;br /&gt;
ctx.shadowBlur = &lt;span style="color:blue;"&gt;8&lt;/span&gt;;&lt;br /&gt;
ctx.fillText (&lt;span style="color:maroon;"&gt;"Sombra muito borrada"&lt;/span&gt;, &lt;span style="color:blue;"&gt;5&lt;/span&gt;, &lt;span style="color:blue;"&gt;100&lt;/span&gt;);&lt;br /&gt;
&lt;/td&gt;     &lt;td style="width:50%;"&gt;&lt;canvas id="cnvText3"&gt; Seu navegador (ou leitor de RSS) não suporta canvas ... &lt;/canvas&gt; &lt;script language="JavaScript" type="text/javascript"&gt;

var myCanvas = document.getElementById("cnvText3");
var ctx = myCanvas.getContext("2d");

ctx.font = "18pt Arial";
ctx.fillStyle = "#0F0FA0";
ctx.shadowColor = "gray";
ctx.shadowOffsetX = 3;
ctx.shadowOffsetY = 3;
ctx.fillText ("Texto com sombra comum", 5, 40);

ctx.fillStyle = "#7F0FA0";
ctx.shadowColor = "black";
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.shadowBlur = 2;
ctx.fillText ("Texto com sombra borrada", 5, 70);

ctx.fillStyle = "green";
ctx.shadowColor = "black";
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.shadowBlur = 8;
ctx.fillText ("Sombra muito borrada", 5, 100);

&lt;/script&gt;  &lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;/center&gt; &lt;/div&gt;&lt;br /&gt;
De acordo com a padronização da &lt;a href="http://dev.w3.org/html5/2dcontext/#images"&gt;W3C&lt;/a&gt;, para desenharmos uma imagem no canvas devemos usar a função &lt;b&gt;drawImage&lt;/b&gt;. Com ela, podemos transferir para o canvas uma imagem inteira ou uma parte retangular dela. Também podemos modificar a proporção da imagem renderizada no canvas, indicando se ela é cópia exata da imagem original ou se será ajustada para um novo comprimento e altura. &lt;a href="http://dev.w3.org/html5/2dcontext/#images"&gt;Neste link publicado pela W3C&lt;/a&gt; há uma explicação e um gráfico que ilustram o funcionamento dos parâmetros envolvidos na cópia da imagem original para o Canvas.&lt;br /&gt;
&lt;br /&gt;
Em sua versão mais simples, o &lt;b&gt;drawImage&lt;/b&gt; aceita como parâmetros a imagem em si e a coordenada do canto superior esquerdo no canvas a partir de onde a imagem será renderizada. Neste contexto, uma imagem pode ser tanto uma tag &lt;b&gt;IMG&lt;/b&gt; quanto um outro canvas ou até mesmo a &lt;a href="http://www.w3schools.com/html5/tag_video.asp"&gt;tag VIDEO&lt;/a&gt;, introduzida no HTML5. No caso da &lt;b&gt;IMG&lt;/b&gt;, podemos recuperar uma referência à imagem usando a função &lt;b&gt;getElementById&lt;/b&gt; do documento HTML (se a imagem já estiver embutida na página HTML) ou criar uma nova referência do zero, instanciando o objeto &lt;span style="color:fuchsia;"&gt;Image&lt;/span&gt;: &lt;br /&gt;
&lt;div style="font-size:8pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 97%;"&gt;&lt;center&gt; &lt;table&gt;&lt;tr&gt;&lt;td style="width:50%;"&gt; &lt;b&gt;var&lt;/b&gt; img = &lt;b&gt;new&lt;/b&gt; &lt;span style="color:fuchsia;"&gt;Image&lt;/span&gt;();&lt;br /&gt;
img.onload = &lt;b&gt;function&lt;/b&gt; () {&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.drawImage (img, &lt;span style="color:blue;"&gt;10&lt;/span&gt;, &lt;span style="color:blue;"&gt;10&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.drawImage (img, &lt;span style="color:blue;"&gt;110&lt;/span&gt;, &lt;span style="color:blue;"&gt;10&lt;/span&gt;, &lt;span style="color:blue;"&gt;70&lt;/span&gt;, &lt;span style="color:blue;"&gt;110&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.drawImage (img, &lt;span style="color:blue;"&gt;10&lt;/span&gt;, &lt;span style="color:blue;"&gt;15&lt;/span&gt;, &lt;span style="color:blue;"&gt;45&lt;/span&gt;, &lt;span style="color:blue;"&gt;60&lt;/span&gt;, &lt;span style="color:blue;"&gt;220&lt;/span&gt;, &lt;span style="color:blue;"&gt;20&lt;/span&gt;, &lt;span style="color:blue;"&gt;45&lt;/span&gt;, &lt;span style="color:blue;"&gt;60&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
}&lt;br /&gt;
img.src = &lt;span style="color:maroon"&gt;'40anos.gif'&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
ctx.font = &lt;span style="color:maroon"&gt;"10pt Tahoma"&lt;/span&gt;;&lt;br /&gt;
ctx.fillText (&lt;span style="color:maroon"&gt;"Normal"&lt;/span&gt;, &lt;span style="color:blue;"&gt;30&lt;/span&gt;, &lt;span style="color:blue;"&gt;130&lt;/span&gt;);&lt;br /&gt;
ctx.fillText (&lt;span style="color:maroon"&gt;"Novo tamanho"&lt;/span&gt;, &lt;span style="color:blue;"&gt;110&lt;/span&gt;, &lt;span style="color:blue;"&gt;130&lt;/span&gt;);&lt;br /&gt;
ctx.fillText (&lt;span style="color:maroon"&gt;"Cópia parcial"&lt;/span&gt;,&lt;span style="color:blue;"&gt;210&lt;/span&gt;, &lt;span style="color:blue;"&gt;130&lt;/span&gt;); &lt;/td&gt;     &lt;td style="width:50%;"&gt;&lt;canvas id="cnvImg1" style="border:1px solid silver;"&gt; Seu navegador (ou leitor de RSS) não suporta canvas ... &lt;/canvas&gt; &lt;script language="JavaScript" type="text/javascript"&gt;
function cnvImg1 () {
var myCanvas = document.getElementById("cnvImg1");
var ctx = myCanvas.getContext("2d");

var img = new Image();
img.onload = function(){
  ctx.drawImage (img, 10, 10);
  ctx.drawImage (img, 110, 10, 70, 110);
  ctx.drawImage (img, 10, 15, 45, 60, 220, 20, 45, 60);
}
img.src = 'http://www.abc71.com.br/images/40anos.gif';

ctx.font = "10pt Tahoma";
ctx.fillText ("Normal",        30, 130);
ctx.fillText ("Novo tamanho", 110, 130);
ctx.fillText ("Cópia parcial",210, 130);
}
cnvImg1 ();
&lt;/script&gt;  &lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;/center&gt; &lt;/div&gt;É importante ressaltar que a carga da imagem é disparada de modo assíncrono, logo após a URL para a imagem ter sido informada. Isto significa que o script continua a executar enquanto o navegador localiza e carrega a imagem. Por isso, no script acima a imagem é desenhada no canvas dentro do evento &lt;b&gt;&lt;span style="font-family:Courier;"&gt;onload&lt;/span&gt;&lt;/b&gt; da tag da imagem. Ou seja, o desenho só é feito quando efetivamente a imagem está disponível.&lt;br /&gt;
&lt;br /&gt;
As propriedades para sombreamento de texto discutidas neste post também são aplicáveis ao desenho de imagens. Assim, podemos incrementar o resultado adicionando esse efeito conforme a necessidade:&lt;br /&gt;
&lt;div style="font-size:8pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 97%;"&gt;&lt;center&gt; &lt;table&gt;&lt;tr&gt;&lt;td style="width:50%;"&gt;  &lt;b&gt;var&lt;/b&gt; img = &lt;b&gt;new&lt;/b&gt; &lt;span style="color:fuchsia;"&gt;Image&lt;/span&gt;();&lt;br /&gt;
img.onload = &lt;b&gt;function&lt;/b&gt; () {&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;&lt;span style="color:green;"&gt;/* Remove o recurso de sombreamento para a 1a imagem */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.shadowOffsetX = &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.shadowOffsetY = &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.shadowBlur = &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.drawImage (img, &lt;span style="color:blue;"&gt;10&lt;/span&gt;, &lt;span style="color:blue;"&gt;10&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;&lt;span style="color:green;"&gt;/* Aplica o recurso de sombreamento para as demais imagens */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.shadowColor = &lt;span style="color:maroon"&gt;"#2D90E0"&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.shadowOffsetX = &lt;span style="color:blue;"&gt;7&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.shadowOffsetY = &lt;span style="color:blue;"&gt;10&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.shadowBlur = &lt;span style="color:blue;"&gt;8&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;&lt;span style="color:green;"&gt;/* Copia a imagem completa para um local no canvas */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.drawImage (img, &lt;span style="color:blue;"&gt;110&lt;/span&gt;, &lt;span style="color:blue;"&gt;10&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;&lt;span style="color:green;"&gt;/* Copia parte da imagem para um local no canvas */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:0.6em;"&gt;ctx.drawImage (img, &lt;span style="color:blue;"&gt;10&lt;/span&gt;, &lt;span style="color:blue;"&gt;15&lt;/span&gt;, &lt;span style="color:blue;"&gt;45&lt;/span&gt;, &lt;span style="color:blue;"&gt;60&lt;/span&gt;, &lt;span style="color:blue;"&gt;220&lt;/span&gt;, &lt;span style="color:blue;"&gt;20&lt;/span&gt;, &lt;span style="color:blue;"&gt;45, 60&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
}&lt;br /&gt;
img.src = &lt;span style="color:maroon"&gt;'40anos.gif'&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:green;"&gt;/* Para os textos, remove os efeitos de sombreamento */&lt;/span&gt;&lt;br /&gt;
ctx.font = &lt;span style="color:maroon"&gt;"10pt Tahoma"&lt;/span&gt;;&lt;br /&gt;
ctx.shadowColor = &lt;span style="color:maroon"&gt;"black"&lt;/span&gt;;&lt;br /&gt;
ctx.shadowOffsetX = &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;br /&gt;
ctx.shadowOffsetY = &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;br /&gt;
ctx.shadowBlur = &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;br /&gt;
ctx.fillText (&lt;span style="color:maroon"&gt;"Normal"&lt;/span&gt;, &lt;span style="color:blue;"&gt;30&lt;/span&gt;, &lt;span style="color:blue;"&gt;130&lt;/span&gt;);&lt;br /&gt;
ctx.fillText (&lt;span style="color:maroon"&gt;"Com Sombra"&lt;/span&gt;, &lt;span style="color:blue;"&gt;110&lt;/span&gt;, &lt;span style="color:blue;"&gt;130&lt;/span&gt;);&lt;br /&gt;
ctx.fillText (&lt;span style="color:maroon"&gt;"Cópia parcial"&lt;/span&gt;, &lt;span style="color:blue;"&gt;210&lt;/span&gt;, &lt;span style="color:blue;"&gt;123&lt;/span&gt;);&lt;br /&gt;
ctx.fillText (&lt;span style="color:maroon"&gt;"com sombra"&lt;/span&gt;, &lt;span style="color:blue;"&gt;210&lt;/span&gt;, &lt;span style="color:blue;"&gt;137&lt;/span&gt;); &lt;/td&gt;     &lt;td style="width:50%;"&gt;&lt;canvas id="cnvImg2" style="border:1px solid silver;"&gt; Seu navegador (ou leitor de RSS) não suporta canvas ... &lt;/canvas&gt; &lt;script language="JavaScript" type="text/javascript"&gt;
function cnvImg2 (){
var myCanvas = document.getElementById("cnvImg2");
var ctx = myCanvas.getContext("2d");

var img = new Image();
img.onload = function(){
  ctx.shadowOffsetX = 0;
  ctx.shadowOffsetY = 0;
  ctx.shadowBlur = 0;
  ctx.drawImage (img, 10, 10);

  ctx.shadowColor = "#2D90E0";  
  ctx.shadowOffsetX = 7;
  ctx.shadowOffsetY = 10;
  ctx.shadowBlur = 8;
  ctx.drawImage (img, 110, 10);  
  ctx.drawImage (img, 10, 15, 45, 60, 220, 20, 45, 60);
}
img.src = 'http://www.abc71.com.br/images/40anos.gif';

ctx.font = "10pt Tahoma";
ctx.shadowColor = "black";
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = 0;
ctx.fillText ("Normal",      30, 130);
ctx.fillText ("Com Sombra", 110, 130);
ctx.fillText ("Cópia parcial",210, 123);
ctx.fillText ("com sombra"   ,210, 137);
}
cnvImg2 ();
&lt;/script&gt;  &lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;/center&gt; &lt;/div&gt;Note pelo exemplo anterior que mesmo na cópia de apenas parte de uma imagem o efeito de sombreamento se aplica.&lt;br /&gt;
&lt;br /&gt;
Em outra oportunidade mostrarei mais recursos do canvas associado a cores e imagens (como rotação e criação de gradientes) e como misturar isso tudo.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
Trabalhando com a tag Canvas do HTML5 - &lt;a href="http://balaiotecnologico.blogspot.com/2011/08/trabalhando-com-tag-canvas-do-html5.html"&gt;parte I&lt;/a&gt; e &lt;a href="http://balaiotecnologico.blogspot.com/2011/09/trabalhando-com-tag-canvas-do-html5_06.html"&gt;parte II&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en/Canvas_tutorial"&gt;Tutorial de Canvas na Fundação Mozilla&lt;/a&gt;, &lt;a href="http://dev.w3.org/html5/2dcontext/#text"&gt;Definições da W3C para o uso de textos no Canvas&lt;/a&gt;,&lt;a href="http://dev.w3.org/html5/2dcontext/#images"&gt;Definições da W3C para o uso de imagens no Canvas&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-4095793666167895894?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/o3r_O0ltnyJ8ANfYARExijXNAq4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/o3r_O0ltnyJ8ANfYARExijXNAq4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/o3r_O0ltnyJ8ANfYARExijXNAq4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/o3r_O0ltnyJ8ANfYARExijXNAq4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/aTmtiNNYq-k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/4095793666167895894/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/09/trabalhando-com-tag-canvas-do-html5.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4095793666167895894?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4095793666167895894?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/aTmtiNNYq-k/trabalhando-com-tag-canvas-do-html5.html" title="Trabalhando com a tag Canvas do HTML5 - parte III" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/09/trabalhando-com-tag-canvas-do-html5.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUMR38zeCp7ImA9WhdVEU8.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-959767177870278790</id><published>2011-09-15T17:58:00.000-03:00</published><updated>2011-09-15T17:58:06.180-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-15T17:58:06.180-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Windows" /><title>Funcionamento do Certificate Store do Windows</title><content type="html">Tenho recebido com frequência dúvidas a respeito do acesso a certificados digitais importados no &lt;b&gt;Certificate Store&lt;/b&gt; do Windows. Pela forma com que as dúvidas têm sido colocadas, percebi que faltou nos posts sobre esse assunto dar uma ideia global do que é o Certificate Store e como ele funciona.&lt;br /&gt;
&lt;br /&gt;
Como disse no post sobre &lt;a href="http://balaiotecnologico.blogspot.com/2009/04/trabalhando-com-o-certificate-store-do.html"&gt;acesso ao Certificate Store do Windows com C#&lt;/a&gt;, o Certificate Store é um repositório centralizado onde são armazenados os certificados digitais disponíveis em um computador. Há uma aplicação que permite acessá-lo visualmente, sendo que uma forma fácil de iniciá-la é usando a opção &lt;b&gt;Executar&lt;/b&gt; do menu &lt;b&gt;Iniciar&lt;/b&gt; do Windows. Na caixa de edição que se abre, digite o comando abaixo:

&lt;div style="padding:0.5em 0 0.5em 0"&gt;&lt;center&gt;&lt;b&gt;mmc \windows\system32\certmgr.msc&lt;/b&gt;&lt;/center&gt;&lt;/div&gt;

Normalmente, a tela que aparece é a que está reproduzida a seguir:
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;padding: 5px 10px 0 5px;width: 96%;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lgaf.webs.com/arqs/certificados.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;width:100%;" src="http://lgaf.webs.com/arqs/certificados.jpg" alt="Certificados Digitais" id="Cert20110915" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
Com essa aplicação, é possível gerenciar os certificados instalados no computador, importando novos e eliminando aqueles que não são mais desejados. Observe que o painel à esquerda mostra uma organização hierárquica, com uma raiz e diversas pastas embaixo dela. O nó raiz nesse exemplo apresenta o nome &lt;b&gt;Certificates - Current User&lt;/b&gt;. Isso significa que todas as pastas sob ele bem como os certificados listados no painel à direita estão disponíveis apenas para o usuário que atualmente está logado no Windows.&lt;br /&gt;
&lt;br /&gt;
As pastas servem para agrupar os certificados por semelhança na finalidade de uso. Na imagem, a pasta &lt;b&gt;Personal&lt;/b&gt; está selecionada, permitindo-nos visualizar à direita os certificados catalogados como sendo de uso pessoal do usuário atual. Outros exemplos de pastas são as que contém certificados que identificam as &lt;a href="http://en.wikipedia.org/wiki/Certificate_authority"&gt;Autoridades Certificadoras&lt;/a&gt; (CA), entidades responsáveis pela emissão dos certificados.&lt;br /&gt;
&lt;br /&gt;
Do ponto de vista do programador que vai acessar o Store usando a classe &lt;a href="http://msdn.microsoft.com/pt-br/library/system.security.cryptography.x509certificates.x509store.aspx"&gt;X509Store&lt;/a&gt; (ou o CAPICOM), essas duas informações - nó raiz e pasta - são imprescindíveis. O construtor da &lt;b&gt;X509Store&lt;/b&gt; aceita como parâmetros o &lt;b&gt;Store Name&lt;/b&gt; e o &lt;b&gt;Store Location&lt;/b&gt;, sendo que o &lt;i&gt;name&lt;/i&gt; corresponde à "pasta" onde está o certificado e &lt;i&gt;location&lt;/i&gt; é o nó raiz ao qual a pasta está atrelada. A pasta &lt;b&gt;personal&lt;/b&gt; é mapeada com o nome "My" para essa função.&lt;br /&gt;
&lt;br /&gt;
Agora, imagine que você construiu um serviço que acessa o Certificate Store. No Windows, cada serviço é executado com um usuário específico, o qual pode ser configurado na guia &lt;i&gt;Log On&lt;/i&gt; das propriedades do serviço no gerenciador de serviços do Windows. Com isso, ele poderá entrar no ar mesmo que nimguém esteja logado no Windows - o login será feito automaticamente para o usuário que tiver sido associado ao serviço. Portanto, se você importou um certificado para seu usuário mas está executando o serviço com um usuário diferente, esse outro usuário não enxergará o seu certificado.&lt;br /&gt;
&lt;br /&gt;
Isso vale também para aplicações &lt;a href="http://en.wikipedia.org/wiki/Internet_Server_Application_Programming_Interface"&gt;ISAPI&lt;/a&gt; - sites construídos em ASP ou ASP.NET se encaixam nessa categoria - uma vez que elas rodam como parte do serviço do &lt;a href="http://en.wikipedia.org/wiki/Internet_Information_Services"&gt;IIS&lt;/a&gt; (Internet Information Services). O IIS é atrelado normalmente a um usuário padrão do Windows chamado &lt;b&gt;Local System&lt;/b&gt; e, portanto, loga-se no Windows com esse usuário, mesmo que você tenha feito login.&lt;br /&gt;
&lt;br /&gt;
Para resolver esse impasse, podemos importar o certificado num &lt;i&gt;Store Location&lt;/i&gt; acessível por todos os usuários. Como a aplicação disponível carrega apenas originalmente o Location "Current User", teremos que adicionar na mão um &lt;i&gt;plugin&lt;/i&gt; para o Location com a característica que precisamos. Esse Location é o "Local Computer".&lt;br/&gt;
&lt;br/&gt;
Para isso, execute o &lt;a href="http://en.wikipedia.org/wiki/Microsoft_Management_Console"&gt;MMC.exe&lt;/a&gt; sem parâmetros no &lt;b&gt;Iniciar -&gt; Executar&lt;/b&gt; do Windows. No menu &lt;i&gt;File&lt;/i&gt; da aplicação, clique na opção &lt;i&gt;Add/Remove snap-in&lt;/i&gt; e então o botão "Add" para ativar a tela de adição dos plugins. Na lista de plugins que aparece, selecione &lt;b&gt;certificates&lt;/b&gt; e novamente clique em "Add". A imagem abaixo mostra a tela de adição do plugin de gerenciamento de certificados com a opção "Computer Account" (o computer local) selecionada. &lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;padding: 5px 10px 0 5px;width: 96%;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lgaf.webs.com/arqs/addsnapin.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;width:100%;" src="http://lgaf.webs.com/arqs/addsnapin.jpg" alt="Add snap-in" id="addsnapin0110915" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Após a adição, o console mostrará uma hierarquia similar à da imagem no início deste post, com a exceção de que o nó raiz será "Local Computer". Agora podemos importar certificados na pasta "Personal" e torná-los disponíveis para os programas, independentemente das credenciais do usuário que está executando esse programa ou serviço.&lt;br /&gt;
&lt;br /&gt;
Certificados importados na pasta "Personal" do "Local Computer" podem, então, ser acessados abrindo-se o Certificate Store com os parâmetros mostrados abaixo:
&lt;div style="font-size:8pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;span style="color:teal;"&gt;X509Store&lt;/span&gt; lStore = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:teal;"&gt;X509Store&lt;/span&gt; (&lt;span style="color:teal;"&gt;StoreName&lt;/span&gt;.My, &lt;span style="color:teal;"&gt;StoreLocation&lt;/span&gt;.LocalComputer);&lt;br/&gt;
&lt;i&gt;&lt;span style="margin:1em;color:green;"&gt;/* ... */&lt;/span&gt;&lt;/i&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://balaiotecnologico.blogspot.com/2009/04/trabalhando-com-o-certificate-store-do.html"&gt;Trabalhando com o Certificate Store do Windows (C#)&lt;/a&gt;, &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/acessando-o-certificate-store-do.html"&gt;Acessando o Certificate Store do Windows com CAPICOM (Delphi)&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Microsoft_Management_Console"&gt;Microsoft Management Console&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-959767177870278790?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xm0OpGcZmkAIuAYtBTLlPR2aClI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xm0OpGcZmkAIuAYtBTLlPR2aClI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xm0OpGcZmkAIuAYtBTLlPR2aClI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xm0OpGcZmkAIuAYtBTLlPR2aClI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/brPz_Y-ybho" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/959767177870278790/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/09/funcionamento-do-certificate-store-do.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/959767177870278790?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/959767177870278790?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/brPz_Y-ybho/funcionamento-do-certificate-store-do.html" title="Funcionamento do Certificate Store do Windows" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/09/funcionamento-do-certificate-store-do.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YERnY7fCp7ImA9WhdWE08.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-6540023201339842998</id><published>2011-09-06T11:58:00.000-03:00</published><updated>2011-09-06T11:58:27.804-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-06T11:58:27.804-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="HTML" /><title>Trabalhando com a tag Canvas do HTML5 - parte II</title><content type="html">No &lt;a href="http://balaiotecnologico.blogspot.com/2011/08/trabalhando-com-tag-canvas-do-html5.html"&gt;último post&lt;/a&gt;, apresentei o funcionamento básico da tag Canvas do HMTL 5, sua inserção numa página HTML e código JavaScript simples para traçar linhas na área do Canvas. Avançando nesse assunto, gostaria de apresentar aqui outras funções de desenho e como lidar com cores.&lt;br /&gt;
&lt;br /&gt;
Além de linhas, a lista de funções para traçar figuras geométricas básicas inclui também funções para criar retângulos e arcos. No caso dos retângulos, há 2 funções : uma para desenhar apenas a borda, sem preencher o interior - &lt;b&gt;strokeRect&lt;/b&gt; - e outra para desenhá-lo preenchido - &lt;b&gt;fillRect&lt;/b&gt;.
&lt;br /&gt;
&lt;div style="font-size:8pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;center&gt;
&lt;table style="width:96%;"&gt;
&lt;tr&gt;&lt;td style="width:50%;"&gt;

&lt;span style="color:green;"&gt;/* ... */&lt;/span&gt;&lt;br /&gt;
ctx.beginPath();&lt;br /&gt;
ctx.fillRect (&lt;span style="color:blue;"&gt;10&lt;/span&gt;,&lt;span style="color:blue;"&gt;10&lt;/span&gt;,&lt;span style="color:blue;"&gt;60&lt;/span&gt;,&lt;span style="color:blue;"&gt;100&lt;/span&gt;);&lt;br /&gt;
ctx.strokeRect (&lt;span style="color:blue;"&gt;75&lt;/span&gt;,&lt;span style="color:blue;"&gt;10&lt;/span&gt;,&lt;span style="color:blue;"&gt;60&lt;/span&gt;,&lt;span style="color:blue;"&gt;100&lt;/span&gt;);&lt;br /&gt;
ctx.clearRect (&lt;span style="color:blue;"&gt;30&lt;/span&gt;, &lt;span style="color:blue;"&gt;50&lt;/span&gt;, &lt;span style="color:blue;"&gt;25&lt;/span&gt;, &lt;span style="color:blue;"&gt;25&lt;/span&gt;);&lt;br /&gt;
ctx.closePath();&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; grausFin = &lt;span style="color:blue;"&gt;360&lt;/span&gt;;&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; radFin = (Math.PI/&lt;span style="color:blue;"&gt;180&lt;/span&gt;) * grausFin;&lt;br /&gt;
&lt;br /&gt;
ctx.beginPath();&lt;br /&gt;
ctx.arc(&lt;span style="color:blue;"&gt;180&lt;/span&gt;, myCanvas.height / &lt;span style="color:blue;"&gt;2&lt;/span&gt;, &lt;span style="color:blue;"&gt;25&lt;/span&gt;, &lt;span style="color:blue;"&gt;0&lt;/span&gt;, radFin, &lt;span style="color:navy;"&gt;false&lt;/span&gt;);&lt;br /&gt;
ctx.stroke();&lt;br /&gt;
ctx.closePath();&lt;br /&gt;
&lt;br /&gt;
ctx.beginPath();&lt;br /&gt;
ctx.arc(&lt;span style="color:blue;"&gt;230&lt;/span&gt;, myCanvas.height / &lt;span style="color:blue;"&gt;2&lt;/span&gt;, &lt;span style="color:blue;"&gt;25&lt;/span&gt;, &lt;span style="color:blue;"&gt;0&lt;/span&gt;, radFin, &lt;span style="color:navy;"&gt;false&lt;/span&gt;);&lt;br /&gt;
ctx.fill();&lt;br /&gt;
ctx.closePath();
&lt;/td&gt;
    &lt;td style="width:50%;"&gt;&lt;canvas id="cnvRect" style="border:1px solid silver;width:99%;"&gt;
Seu navegador não suporta canvas ...
&lt;/canvas&gt;
&lt;script language="JavaScript" type="text/javascript"&gt;

var myCanvas = document.getElementById("cnvRect");
var ctx = myCanvas.getContext("2d");

ctx.beginPath();
ctx.fillRect (10,10,60,100);
ctx.strokeRect (75,10,60,100);
ctx.clearRect (30, 50, 25, 25);
ctx.closePath();

var grausFin = 360;
var radFin = (Math.PI/180)* grausFin;

ctx.beginPath();
ctx.arc(180, myCanvas.height / 2, 25, 0, radFin, false);
ctx.stroke();
ctx.closePath();

ctx.beginPath();
ctx.arc(230, myCanvas.height / 2, 25, 0, radFin, false);
ctx.fill();
ctx.closePath();

&lt;/script&gt;

&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;br /&gt;
Já a função &lt;b&gt;clearRect&lt;/b&gt; que aparece no código acima serve para limpar uma área retangular do canvas, tornando-a transparente. Isto é, a área é totalmente preenchida com a cor de fundo da tag onde o Canvas está inserido, substituindo os pixels contidos na área. A utilidade desse recurso está em preparar o canvas para receber novos desenhos sem sofrer interferência daqueles que existiam anteriormente.&lt;br /&gt;
&lt;br /&gt;
Os parâmetros das funções de retângulo são sempre o ponto superior esquerdo (x, y) seu comprimento e sua altura.&lt;br /&gt;
&lt;br /&gt;
Como mostra o exemplo anterior, o desenho de um círculo é feito através da função &lt;b&gt;arc&lt;/b&gt;. O que determina se ele será preenchido ou não é a função chamada depois : use &lt;b&gt;fill&lt;/b&gt; para preenchê-lo ou &lt;b&gt;stroke&lt;/b&gt; para desenhar apenas o seu contorno.&lt;br /&gt;
&lt;br /&gt;
Os parâmetros da função para desenhar arco são o ponto central (x, y), seu raio, o ângulo na circunferência onde o desenho será iniciado, o ângulo final e um booleano indicando se o desenho será feito no sentido anti-horário. Como diz o nome da função, ela traça um arco entre o ângulo inicial e final, formando parte de um círculo com centro em (x, y) e o raio dado. Isso implica que temos que informar os ângulos 0 (zero) e 2pi se quisermos desenhar um círculo completo. Observe que os ângulos são informados em radianos e não em graus. A fórmula  (PI * 180 / graus) que aparece no exemplo faz a conversão de graus para radianos.&lt;br /&gt;
&lt;br /&gt;
As cores aplicadas em linhas e nos preenchimentos são controladas de forma independente entre si. Ao traçar linhas – aí incluindo a função para desenhar somente as bordas de um retângulo ou arco – a cor é ditada pela propriedade &lt;b&gt;strokeStyle&lt;/b&gt; do canvas, enquanto para fazer qualquer preenchimento, a cor usada é aquela atribuída ao &lt;b&gt;fillStyle&lt;/b&gt;.&lt;br /&gt;
&lt;div style="font-size:8pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;center&gt;
&lt;table style="width:96%;"&gt;
&lt;tr&gt;&lt;td style="width:50%;"&gt;
&lt;span style="color:green;"&gt;/* ... */&lt;/span&gt;&lt;br /&gt;
ctx.beginPath();&lt;br /&gt;
ctx.fillStyle = &lt;span style="color:maroon;"&gt;"rgb(45,80,150)"&lt;/span&gt;;&lt;br /&gt;
ctx.strokeStyle = &lt;span style="color:maroon;"&gt;"maroon"&lt;/span&gt;;&lt;br /&gt;
ctx.fillRect (&lt;span style="color:blue;"&gt;10&lt;/span&gt;,&lt;span style="color:blue;"&gt;10&lt;/span&gt;,&lt;span style="color:blue;"&gt;60&lt;/span&gt;,&lt;span style="color:blue;"&gt;100&lt;/span&gt;);&lt;br /&gt;
ctx.strokeRect (&lt;span style="color:blue;"&gt;75&lt;/span&gt;,&lt;span style="color:blue;"&gt;10&lt;/span&gt;,&lt;span style="color:blue;"&gt;60&lt;/span&gt;,&lt;span style="color:blue;"&gt;100&lt;/span&gt;);&lt;br /&gt;
ctx.closePath();&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; grausFin = &lt;span style="color:blue;"&gt;360&lt;/span&gt;;&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; radFin = (Math.PI/&lt;span style="color:blue;"&gt;180&lt;/span&gt;)* grausFin;&lt;br /&gt;
&lt;br /&gt;
ctx.fillStyle = &lt;span style="color:maroon;"&gt;"#FFA500"&lt;/span&gt;;&lt;br /&gt;
ctx.strokeStyle = &lt;span style="color:maroon;"&gt;"green"&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
ctx.beginPath();&lt;br /&gt;
&lt;br /&gt;
ctx.arc(180, myCanvas.height / &lt;span style="color:blue;"&gt;2&lt;/span&gt;, &lt;span style="color:blue;"&gt;25&lt;/span&gt;, &lt;span style="color:blue;"&gt;0&lt;/span&gt;, radFin, &lt;span style="color:navy;"&gt;false&lt;/span&gt;);&lt;br /&gt;
ctx.stroke();&lt;br /&gt;
ctx.closePath();&lt;br /&gt;
&lt;br /&gt;
ctx.beginPath();&lt;br /&gt;
ctx.arc(&lt;span style="color:blue;"&gt;230&lt;/span&gt;, myCanvas.height / &lt;span style="color:blue;"&gt;2&lt;/span&gt;, &lt;span style="color:blue;"&gt;25&lt;/span&gt;, &lt;span style="color:blue;"&gt;0&lt;/span&gt;, radFin, &lt;span style="color:navy;"&gt;false&lt;/span&gt;);&lt;br /&gt;
ctx.fill();&lt;br /&gt;
ctx.closePath();
&lt;/td&gt;
    &lt;td style="width:50%;"&gt;&lt;canvas id="cnvRect2" style="border:1px solid silver;width:99%;"&gt;
Seu navegador não suporta canvas ...
&lt;/canvas&gt;
&lt;script language="JavaScript" type="text/javascript"&gt;

var myCanvas = document.getElementById("cnvRect2");
var ctx = myCanvas.getContext("2d");

ctx.beginPath();
ctx.fillStyle = "rgb(45,80,150)";
ctx.strokeStyle = "maroon";
ctx.fillRect (10,10,60,100);
ctx.strokeRect (75,10,60,100);
ctx.closePath();

var grausFin = 360;
var radFin = (Math.PI/180) * grausFin;

ctx.fillStyle = "#FFA500";
ctx.strokeStyle = "green";

ctx.beginPath();

ctx.arc(180, myCanvas.height / 2, 25, 0, radFin, false);
ctx.stroke();
ctx.closePath();

ctx.beginPath();
ctx.arc(230, myCanvas.height / 2, 25, 0, radFin, false);
ctx.fill();
ctx.closePath();

&lt;/script&gt;

&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/center&gt;

&lt;/div&gt;
No exemplo acima, utilizei cores especificando diretamente seu nome (com em “green”) ou sua composição RGB (como em "rgb(45,80,150)"). Também poderia ter usado um código hexadecimal (como em "#FFA500"). Ou seja: são os mesmos mecanismos aceitos pelo CSS3.&lt;br /&gt;
&lt;br /&gt;
Um outro aspecto importante para traçar linhas e desenhar bordas é a espessura que a linha deve ter. Podemos modificar o valor contido na propriedade &lt;b&gt;lineWidth&lt;/b&gt; do canvas para obter linhas mais grossas. O valor padrão dela que corresponde a 1 unidade, sendo que ela aceita valores positivos.&lt;br /&gt;
&lt;div style="font-size:8pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;center&gt;
&lt;table style="width:96%;"&gt;
&lt;tr&gt;&lt;td style="width:50%;"&gt;
&lt;span style="color:green;"&gt;/* ... */&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; angIni = &lt;span style="color:blue;"&gt;3&lt;/span&gt; * Math.PI / &lt;span style="color:blue;"&gt;2&lt;/span&gt;;&lt;br /&gt;
&lt;b&gt;var&lt;/b&gt; angFin = Math.PI / &lt;span style="color:blue;"&gt;2&lt;/span&gt;, x, i;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:green;"&gt;/* Linhas e arcos */&lt;/span&gt;&lt;br /&gt;
x = &lt;span style="color:blue;"&gt;5&lt;/span&gt;;&lt;br /&gt;
&lt;b&gt;for&lt;/b&gt; (i = &lt;span style="color:blue;"&gt;0&lt;/span&gt;; i &lt; &lt;span style="color:blue;"&gt;10&lt;/span&gt;; i ++)&lt;br /&gt;
{&lt;br /&gt;
  &lt;span style="margin-left:0.5em;"&gt;ctx.lineWidth = i + &lt;span style="color:blue;"&gt;1&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:0.5em;"&gt;ctx.lineCap = &lt;span style="color:maroon;"&gt;"round"&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt; 
  &lt;span style="margin-left:0.5em;"&gt;ctx.beginPath();&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:0.5em;"&gt;ctx.moveTo (x, &lt;span style="color:blue;"&gt;5&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:0.5em;"&gt;ctx.lineTo (x, &lt;span style="color:blue;"&gt;35&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:0.5em;"&gt;ctx.stroke(); &lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:0.5em;"&gt;ctx.closePath();&lt;/span&gt;&lt;br /&gt;
  &lt;br /&gt;
 &lt;span style="margin-left:0.5em;"&gt; ctx.beginPath();&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:0.5em;"&gt;ctx.arc(x, &lt;span style="color:blue;"&gt;75&lt;/span&gt;, &lt;span style="color:blue;"&gt;20&lt;/span&gt;, angIni, angFin, &lt;b&gt;false&lt;/b&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:0.5em;"&gt;ctx.stroke();&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:0.5em;"&gt;ctx.closePath();&lt;/span&gt;&lt;br /&gt;
  &lt;br /&gt;
  &lt;span style="margin-left:0.5em;"&gt;x = x + &lt;span style="color:blue;"&gt;15&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:green;"&gt;/* Bordas de retângulos */&lt;/span&gt;&lt;br /&gt;
ctx.beginPath();&lt;br /&gt;
ctx.lineWidth = &lt;span style="color:blue;"&gt;8&lt;/span&gt;;&lt;br /&gt;
ctx.strokeRect(&lt;span style="color:blue;"&gt;180&lt;/span&gt;,  &lt;span style="color:blue;"&gt;5&lt;/span&gt;, &lt;span style="color:blue;"&gt;100&lt;/span&gt;, &lt;span style="color:blue;"&gt;100&lt;/span&gt;);&lt;br /&gt;
ctx.lineWidth = &lt;span style="color:blue;"&gt;6&lt;/span&gt;;&lt;br /&gt;
ctx.strokeRect(&lt;span style="color:blue;"&gt;190&lt;/span&gt;, &lt;span style="color:blue;"&gt;15&lt;/span&gt;,  &lt;span style="color:blue;"&gt;80&lt;/span&gt;,  &lt;span style="color:blue;"&gt;80&lt;/span&gt;);&lt;br /&gt;
ctx.lineWidth = &lt;span style="color:blue;"&gt;4&lt;/span&gt;;&lt;br /&gt;
ctx.strokeRect(&lt;span style="color:blue;"&gt;200&lt;/span&gt;, &lt;span style="color:blue;"&gt;25&lt;/span&gt;,  &lt;span style="color:blue;"&gt;60&lt;/span&gt;,  &lt;span style="color:blue;"&gt;60&lt;/span&gt;);&lt;br /&gt;
ctx.lineWidth = &lt;span style="color:blue;"&gt;2&lt;/span&gt;;&lt;br /&gt;
ctx.strokeRect(&lt;span style="color:blue;"&gt;210&lt;/span&gt;, &lt;span style="color:blue;"&gt;35&lt;/span&gt;,  &lt;span style="color:blue;"&gt;40&lt;/span&gt;,  &lt;span style="color:blue;"&gt;40&lt;/span&gt;);&lt;br /&gt;
ctx.closePath();
&lt;/td&gt;
    &lt;td style="width:50%;"&gt;&lt;canvas id="cnvEspess" style="border:1px solid silver;width:99%;"&gt;
Seu navegador não suporta canvas ...
&lt;/canvas&gt;
&lt;script language="JavaScript" type="text/javascript"&gt;

var myCanvas = document.getElementById("cnvEspess");
var ctx = myCanvas.getContext("2d");
var i, x;
var angIni = 3 * Math.PI / 2;
var angFin = Math.PI / 2;

/* Linhas e arcos */
x = 5;
for (i = 0; i &lt; 10; i ++)
{
  ctx.lineWidth = i + 1;
  ctx.lineCap = "round";
 
  ctx.beginPath();
  ctx.moveTo (x, 5);
  ctx.lineTo (x, 35);
  ctx.stroke(); 
  ctx.closePath();
  
  ctx.beginPath();
  ctx.arc(x, 85, 20, angIni, angFin, false);
  ctx.stroke();
  ctx.closePath();
  
  x = x + 15;
};

/* Bordas de retângulos */
ctx.beginPath();
ctx.lineWidth = 8;
ctx.strokeRect(180,  5, 100, 100);
ctx.lineWidth = 6;
ctx.strokeRect(190, 15,  80,  80);
ctx.lineWidth = 4;
ctx.strokeRect(200, 25,  60,  60);
ctx.lineWidth = 2;
ctx.strokeRect(210, 35,  40,  40);
ctx.closePath();

&lt;/script&gt;

&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;br /&gt;
No exemplo acima, modifiquei também a propriedade &lt;b&gt;lineCap&lt;/b&gt;, que determina como o desenho de linhas será arrematado. Ao usar o valor "round", instruo o canvas a arredondar as pontas das linhas ao invés de deixá-las retas, como no comportamento padrão.&lt;br /&gt;
&lt;br /&gt;
No próximo post, falo sobre uso de textos, imagens e como modificar o modo que os desenhos aplicados ao canvas interagem entre si, criando composições entre eles.
&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://balaiotecnologico.blogspot.com/2011/08/trabalhando-com-tag-canvas-do-html5.html"&gt;Trabalhando com a tag Canvas do HTML5 - parte I&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en/Canvas_tutorial"&gt;Tutorial do Canvas no site da Fundação Mozilla&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-6540023201339842998?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/JaY3YtPk2lhCih6z0PEfW9hBiUU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JaY3YtPk2lhCih6z0PEfW9hBiUU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/JaY3YtPk2lhCih6z0PEfW9hBiUU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JaY3YtPk2lhCih6z0PEfW9hBiUU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/7RKdCXYmX70" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/6540023201339842998/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/09/trabalhando-com-tag-canvas-do-html5_06.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/6540023201339842998?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/6540023201339842998?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/7RKdCXYmX70/trabalhando-com-tag-canvas-do-html5_06.html" title="Trabalhando com a tag Canvas do HTML5 - parte II" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/09/trabalhando-com-tag-canvas-do-html5_06.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcBRn87eip7ImA9WhdXFkk.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-6194407619848580047</id><published>2011-08-29T16:44:00.000-03:00</published><updated>2011-08-29T16:44:17.102-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-29T16:44:17.102-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="HTML" /><title>Trabalhando com a tag Canvas do HTML5 - parte I</title><content type="html">Dentre as inovações introduzidas pelo HTML5, certamente a que causou maior impacto foi a adoção da tag &lt;a href="http://en.wikipedia.org/wiki/Canvas_element"&gt;Canvas&lt;/a&gt;. A discussão em torno desse recurso acabou ampliada pelo potencial que ele tem de eliminar a necessidade de outras tecnologias bem estabelecidas, como o &lt;b&gt;Adobe Flash&lt;/b&gt;, usado para criar animações em páginas da Internet.&lt;br/&gt;
&lt;br/&gt;
Mas, o que é a &lt;i&gt;tag&lt;/i&gt; Canvas, como ela funciona e pra que exatamente ela serve ? A grosso modo, essa &lt;i&gt;tag&lt;/i&gt; cria uma área retangular dentro de uma página HTML onde é possível desenhar livremente. Ela faz isso franqueando ao desenvolvedor acesso aos pontos (&lt;a href="http://en.wikipedia.org/wiki/Pixel"&gt;pixels&lt;/a&gt;) que compõem a área, o que pode ser combinado com eventos para criar animações. É um comportamento análogo ao disponível através da classe &lt;a href="http://balaiotecnologico.blogspot.com/2009/11/customizando-aparencia-de-um-grid-em.html#canvas"&gt;TCanvas&lt;/a&gt; que há no Delphi. Tal analogia é reforçada pelo fato que a &lt;i&gt;tag&lt;/i&gt; Canvas em si apenas demarca a região na página HTML, sendo que quaisquer desenhos ou interações que se queira implementar têm que ser obtidos através de programação, usando os métodos e propriedades disponibilizados para uso com JavaScript.&lt;br/&gt;
&lt;br/&gt;
Para começar, então, devemos incluir no corpo do texto HTML a marcação do lugar onde o Canvas será renderizado, exatamente do mesmo modo que fazemos com outras tags. O exemplo abaixo cria uma página HTML que possui apenas um Canvas, com comprimento de 400 pontos e altura de 200 pontos:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;span style="color:maroon;"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:maroon;"&gt;&amp;lt;canvas&lt;/span&gt; &lt;span style="color:blue;"&gt;id=&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;"myCanvas"&lt;/span&gt; &lt;span style="color:blue;"&gt;width=&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;"400"&lt;/span&gt; &lt;span style="color:blue;"&gt;height=&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;"200"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="margin-left:5em;"&gt;&lt;span style="color:blue;"&gt;style=&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;"border:1px solid #c3c3c3;"&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;Seu navegador não suporta canvas ...&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:maroon;"&gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:green;margin-left:1em;"&gt;/* ... */&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:maroon;"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/div&gt;
O texto inserido na tag será exibido apenas se a página for aberta por um navegador que não implementa o recurso de Canvas. Neste caso, para obter um resultado mais profissional, o texto pode ser substituído por um conteúdo HTML apropriado - como uma imagem, por exemplo.&lt;br/&gt;
&lt;br/&gt;
Daqui em diante, todo o trabalho em cima do Canvas tem que ser feito por JavasScript. Primeiro, precisamos recuperar o contexto para desenho pois é nele que o conteúdo apresentado pelo Canvas é criado e manipulado:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;b&gt;function&lt;/b&gt; desenha () {&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;b&gt;var&lt;/b&gt; myCanvas = document.getElementById(&lt;span style="color:maroon;"&gt;"myCanvas"&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;b&gt;var&lt;/b&gt; ctx = myCanvas.getContext(&lt;span style="color:maroon;"&gt;"2d"&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:green;margin-left:1em;"&gt;/* ... */&lt;/span&gt;&lt;br/&gt;
}
&lt;/div&gt;
&lt;br/&gt;
Todas as funções disponíveis no contexto que recuperamos deverão informar coordenadas, isto é, pares de valores (x,y) para se referir a um ponto dentro do plano delimitado pela área do Canvas. A diferença em relação a um &lt;a href="http://pt.wikipedia.org/wiki/Sistema_de_coordenadas_cartesiano"&gt;plano cartesiano&lt;/a&gt; é que no canvas o canto superior esquerdo é sempre (0,0), com os valores de X crescendo para a direita e os de Y crescendo para baixo, como mostra essa imagem da fundação Mozilla :&lt;br /&gt;&lt;center&gt;
&lt;div style="font-size:9pt;font-family:Courier New;width: 300px;"&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://developer.mozilla.org/@api/deki/files/78/=Canvas_default_grid.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;width:100%;" src="https://developer.mozilla.org/@api/deki/files/78/=Canvas_default_grid.png" alt="Coordenadas na tag Canvas" id="canvas20110829" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/center&gt;
&lt;br /&gt;
O exemplo abaixo é bastante básico : move a posição atual do cursor de desenho para o centro do Canvas, traça uma linha até o canto inferior esquerdo, outra até o canto inferior direito e uma terceira até o ponto original. Por fim, a figura fechada é preenchida com a cor corrente :&lt;br /&gt;
&lt;center&gt;
&lt;table style="width:96%;font-size:10pt;border:1px solid silver;"&gt;
&lt;tr&gt;&lt;td style="width:50%;"&gt;
&lt;span style="color:green;margin-left:1em;"&gt;/* ... */&lt;/span&gt;&lt;br/&gt;
ctx.beginPath ();&lt;br /&gt;
&lt;br /&gt;
ctx.moveTo (myCanvas.width / &lt;span style="color:blue;"&gt;2&lt;/span&gt;, &lt;br /&gt; 
    &lt;span style="margin-left:4em;"&gt;myCanvas.height / &lt;span style="color:blue;"&gt;2&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
ctx.lineTo (&lt;span style="color:blue;"&gt;0&lt;/span&gt;,&lt;br /&gt;
     &lt;span style="margin-left:4em;"&gt;myCanvas.height);&lt;/span&gt;&lt;br /&gt;
ctx.lineTo (myCanvas.width, myCanvas.height);&lt;br /&gt;
ctx.lineTo (myCanvas.width / &lt;span style="color:blue;"&gt;2&lt;/span&gt;,&lt;br /&gt;
     &lt;span style="margin-left:4em;"&gt;myCanvas.height / &lt;span style="color:blue;"&gt;2&lt;/span&gt;);&lt;br /&gt;
&lt;br /&gt;
ctx.stroke();&lt;br /&gt;
ctx.fill();&lt;br /&gt;
&lt;br /&gt;
ctx.closePath();&lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;/* ... */&lt;/span&gt;&lt;br/&gt;

    &lt;/td&gt;
    &lt;td style="width:50%;"&gt;&lt;canvas id="myCanvas2" style="border:1px solid silver;width:99%;height:10em;"&gt;
Seu navegador não suporta canvas ...
&lt;/canvas&gt;
&lt;script language="JavaScript" type="text/javascript"&gt;

var myCanvas = document.getElementById("myCanvas2");
var ctx = myCanvas.getContext("2d");

ctx.beginPath();
ctx.moveTo(myCanvas.width / 2, myCanvas.height / 2);
ctx.lineTo(0, myCanvas.height);
ctx.lineTo(myCanvas.width, myCanvas.height);
ctx.lineTo(myCanvas.width / 2, myCanvas.height / 2);
ctx.stroke();
ctx.fill();
ctx.closePath();
&lt;/script&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/center&gt;
Vamos por partes ! As funções &lt;b&gt;beginPath()&lt;/b&gt; e &lt;b&gt;closePath()&lt;/b&gt; do contexto delimitam passos que constituirão um único desenho para o Canvas, não importando quantos passos são necessários para montá-lo. Com isso, os passos entre essas funções compartilham estilos para traçar linhas e preencher áreas, por exemplo. Então, se há partes com cores diferentes, elas deverão ser traçadas como desenhos diferentes dentro do Canvas.&lt;br /&gt;
&lt;br /&gt;
No exemplo, o primeiro passo é uma chamada à função &lt;b&gt;moveTo()&lt;/b&gt;. Ela em si não faz qualquer desenho, servindo apenas para estabelecer um ponto de partida para passos seguintes. Ou seja, é o ponto onde o pincel primeiro tocará a área de pintura. Assim, ao chamarmos a função &lt;b&gt;lineTo()&lt;/b&gt;, traçamos uma linha reta a partir daquele ponto até o ponto indicado nos parâmetros do lineTo. Esse novo ponto, então, passa a ser a posição atual do pincel. Se fosse preciso, poderíamos mover novamente sua posição para qualquer outro ponto sem afetar visualmente o canvas.&lt;br /&gt;
&lt;br /&gt;
A função &lt;b&gt;stroke()&lt;/b&gt; efetiva todos os comandos dados antes, forçando as linhas a serem traçadas com os estilos estabelecidos. Como não comandamos nada diferente, o canvas usará o estilo padrão de cor, espessura e tracejado.&lt;br /&gt;
&lt;br /&gt;
Para encerrar, a função &lt;b&gt;fill()&lt;/b&gt; é chamada para preencher a área interna da figura - também usando estilos padronizados.&lt;br /&gt;
&lt;br /&gt;
Há muitas outras funções para desenhar retângulos, arcos e até curvas mais elaboradas, além da capacidade de incluir textos e imagens externas, o que permite combinar vários recursos para compor figuras bastante complexas. Em outro &lt;i&gt;post&lt;/i&gt;, mostra mais desses recursos.&lt;br /&gt;
&lt;br /&gt;
Os exemplos mostrados neste post usam o contexto para desenhos 2D mas já há uma versão experimental de contexto 3D, baseado no &lt;a href="http://www.khronos.org/webgl/"&gt;WebGL&lt;/a&gt;. Veja um exemplo de uso &lt;a href="https://developer.mozilla.org/en/WebGL/Getting_started_with_WebGL"&gt;neste link&lt;/a&gt;.&lt;br/&gt;
&lt;br/&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://en.wikipedia.org/wiki/Canvas_element"&gt;Canvas element&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en/Canvas_tutorial"&gt;Tutorial do Canvas no site da Fundação Mozilla&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-6194407619848580047?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/zPmh1WgRR01TbgjYNYAOod4Trxg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zPmh1WgRR01TbgjYNYAOod4Trxg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/zPmh1WgRR01TbgjYNYAOod4Trxg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zPmh1WgRR01TbgjYNYAOod4Trxg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/FL6_vvOluxc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/6194407619848580047/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/08/trabalhando-com-tag-canvas-do-html5.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/6194407619848580047?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/6194407619848580047?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/FL6_vvOluxc/trabalhando-com-tag-canvas-do-html5.html" title="Trabalhando com a tag Canvas do HTML5 - parte I" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/08/trabalhando-com-tag-canvas-do-html5.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIBSX04fSp7ImA9WhdQFkQ.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-4454126157575975500</id><published>2011-08-18T13:42:00.001-03:00</published><updated>2011-08-18T16:42:38.335-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-18T16:42:38.335-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Notícias" /><title>Atualização da especificação do C++ ganha aprovação unânime</title><content type="html">Já faz algum tempo, o órgão responsável por padronizações internacionais (&lt;a href="http://www.iso.org/iso/home.html"&gt;ISO&lt;/a&gt;) tem um comitê para discutir novos recursos para a linguagem de programação C++. Após 8 anos de trabalho, &lt;a href="http://www.infoworld.com/d/application-development/iso-finalizes-c-update-935?source=fssr"&gt;um rascunho das especificações já tinha sido liberado&lt;/a&gt; no início deste ano para que a comunidade decidisse se aprovava ou não.&lt;br /&gt;
&lt;br /&gt;
O foco principal das mudanças na especificação foi a adequação do C++ a arquiteturas mais modernas de processamento paralelo, isto é, teve como objetivo facilitar o desenvolvimento de software C++ para esse tipo de ambiente. Além de alterações na &lt;a href="http://en.wikipedia.org/wiki/Standard_Template_Library"&gt;STL&lt;/a&gt; (Standard Template Library), o novo C++ também ganha tratamento para &lt;b&gt;expressões lambda&lt;/b&gt; (veja &lt;a href="http://en.wikipedia.org/wiki/Anonymous_function"&gt;funções anônimas&lt;/a&gt;) e novos tipos de dado para trabalhar com computação paralela. Há ainda mudanças sintáticas para melhorar a performance dos programas.&lt;br /&gt;
&lt;br /&gt;
Um resumo das alterações introduzidas pode ser consultado no &lt;a href="http://en.wikipedia.org/wiki/C%2B%2B0x"&gt;artigo da Wikipedia sobre o C++0x&lt;/a&gt; - nome pelo qual a versão era conhecida mas que agora foi batizado oficialmente como &lt;b&gt;C++11&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Na semana passada, o rascunho foi finalmente aprovado - por unanimidade - e passa a ser a recomendação oficial para a linguagem C++. Abaixo, segue matéria da InfoWorld que anuncia a aprovação. A matéria original em inglês está &lt;a href="https://www.infoworld.com/d/application-development/c-upgrade-gets-unanimous-approval-170061?source=rss_application_development"&gt;neste link&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="background-color: #ebebf5; border: 1px solid silver; padding: 5px 10px 1em 5px; width: 96%;"&gt;"Com a recente aprovação do upgrade para a linguagem C++, o ISO (International Organization for Standards) está fornecendo aos desenvolvedores ferramentas que alavancarão o uso de algorítmos paralelos e permitirão uma melhor performance", disse na terça-feira o presidente do comitê responsável pela linguagem, Herb Sutter.&lt;br /&gt;
&lt;br /&gt;
"O &lt;b&gt;C++11&lt;/b&gt; é a primeira grande revisão do ISO C++", disse o presidente. "Foi introduzido no C++11 as &lt;i&gt;funções lambda&lt;/i&gt;, que são peças chaves para os emergentes algorítmos paralelos e que revolucionam o uso da &lt;i&gt;Standard Template Library&lt;/i&gt; (STL)", disse Sutter, que é também um dos principais arquitetos para linguagens nativas na Microsoft. "O que já existia na biblioteca padrão do C++98 se tornará imediatamente mais fácil de ser usado", disse. Além disso, alterações na semântica do C++11 trazem melhoria na performance. Os novos recursos para tratamento de concorrência incluem tipos de dados para programação portável e livre de locks.&lt;br /&gt;
&lt;br /&gt;
A votação final para o padrão C++ se encerrou na quarta-feira passada e foi unanimemente aprovada, disse Sutter em seu blog. O C++11 era conhecido como C++0x e sua publicação oficial se dará dentro de algumas semanas. "A linguagem", ele diz, "é usada para quase tudo -- o mundo está construído sobre C++."&lt;br /&gt;
&lt;br /&gt;
O C++, incluindo seu subconjunto, o C, é usado para criar compiladores e runtimes de virtualmente todas as linguagens que concorrem com ele, todos os principais navegadores da internet, todos os principais sistemas operacionais, diz Sutter. É também a principal linguagem usada pelo Google e pelo Facebook e a principal linguagem para quase todos os produtos da Microsoft, afirma. "O C++ é a linguagem a se escolher na construção de aplicações de alta performance, qualquer que seja o domínio dessa aplicação", diz Sutter.&lt;br /&gt;
&lt;br /&gt;
"C++ é uma linguagem de uso geral", afirma Henry Skoglund, desenvolvedor C++. "Muito do que foi incluído no novo padrão eu diria que é importante para desenvolvimento de sistemas e de compiladores," ele diz. "Os recursos do Lamdba", assegura Skoglund, "permitem aos desenvolvedores escrever código com menos bugs e em menos linhas."&lt;br /&gt;
&lt;br /&gt;
Também contempladas no C++11 estão as funções &lt;b&gt;auto&lt;/b&gt; e &lt;b&gt;decltype&lt;/b&gt;, onde a primeira é útil para dedução de tipos e a segunda permite obter o tipo de dado real de qualquer expressão. Ainda, ponteiros &lt;b&gt;smart&lt;/b&gt;, tais como o &lt;i&gt;unique_ptr&lt;/i&gt;, oferecem um gerenciamento de memória automatizado e padronizado.&lt;br /&gt;
&lt;br /&gt;
O próximo passo para o padrão C++ é ser implementado pelos compiladores nos próximos um ou dois anos, afirma Sutter. "Enquanto isso se desenrola, o comitê de padrões continuará a trabalhar nos recursos já incluídos no C++11, incrementando a biblioteca padrão de modo que uma biblioteca maior, portável (que não requeira novos recursos da linguagem além dos que já foram incluídos), esteja disponível dentro de cada implementação C++." Está sendo cogitada também uma nova rodada de extensões à linguagem, como conceitos de &lt;i&gt;template&lt;/i&gt; ou &lt;i&gt;lambdas&lt;/i&gt; mais fortes para o C++11. &lt;/div&gt;&lt;br /&gt;
Mesmo antes de se tornar oficial, alguns compiladores - como o C++ da Embarcadero (&lt;a href="http://www.embarcadero.com/products/cbuilder"&gt;C++ Builder XE&lt;/a&gt;) e da Microsoft (&lt;a href="http://blogs.msdn.com/b/vcblog/archive/2010/04/06/c-0x-core-language-features-in-vc10-the-table.aspx"&gt;Visual C++ 2010&lt;/a&gt;) - já incorporaram às suas bibliotecas recursos definidos por esse novo padrão.  &lt;br /&gt;
&lt;br /&gt;
&lt;div style="background-color: #ffffdc; border: 1px solid silver; padding: 10px 5px 10px 5px; text-align: justify; width: 96%;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border: 0; vertical-align: middle;" /&gt;&lt;span style="font-weight: bold; margin: 0pt 0pt 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="https://www.infoworld.com/d/application-development/c-upgrade-gets-unanimous-approval-170061?source=rss_application_development"&gt;C++ upgrade wins unanimous approval&lt;/a&gt;,  &lt;a href="http://www.embarcadero.com/products/cbuilder"&gt;Site do C++ Builder&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/b/vcblog/archive/2010/04/06/c-0x-core-language-features-in-vc10-the-table.aspx"&gt;Características do C++0x implementadas no Visual Studio&lt;/a&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-4454126157575975500?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/6zZeBQvi1FXbvZx6hEuYxziLRuQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6zZeBQvi1FXbvZx6hEuYxziLRuQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/6zZeBQvi1FXbvZx6hEuYxziLRuQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6zZeBQvi1FXbvZx6hEuYxziLRuQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/7Ccaj9FtZM4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/4454126157575975500/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/08/atualizacao-da-especificacao-do-c-ganha.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4454126157575975500?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4454126157575975500?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/7Ccaj9FtZM4/atualizacao-da-especificacao-do-c-ganha.html" title="Atualização da especificação do C++ ganha aprovação unânime" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/08/atualizacao-da-especificacao-do-c-ganha.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUCRHY5fip7ImA9WhdRFEQ.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-1846463967238474755</id><published>2011-08-04T19:34:00.000-03:00</published><updated>2011-08-04T19:34:25.826-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-04T19:34:25.826-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Indy" /><title>Recuperando emails de uma caixa postal com Delphi</title><content type="html">Até pouco tempo atrás, o &lt;b&gt;ERP&lt;/b&gt; da &lt;a href="http://www.abc71.com.br"&gt;ABC71&lt;/a&gt; possuia um recurso que permitia aos usuários enviarem sugestões de melhorias do &lt;i&gt;software&lt;/i&gt; por email. Uma aplicação em nossos servidores monitorava a caixa postal específica, interpretava algumas informações incluídas em cada email, vinculava a solicitação a um responsável e respondia automaticamente o email do usuário com uma mensagem pré-formatada preparada pelo atendimento a Clientes.&lt;br/&gt;
&lt;br/&gt;
Hoje esse esquema não existe mais - foi substituído por outros canais com papel similar - mas a ideia da aplicação capaz de monitorar uma caixa postal ainda é válida e pode ser reaproveitada em outros cenários.&lt;br/&gt;
&lt;br/&gt;
A solução adotada por nós é baseada no protocolo chamado &lt;b&gt;POP3&lt;/b&gt; (&lt;a href="http://pt.wikipedia.org/wiki/Post_Office_Protocol"&gt;Post Office Protocol&lt;/a&gt;). Com ele é possível recuperar todas as mensagens existentes na caixa de entrada de uma conta de email. A implementação dele que usamos é a do &lt;a href="http://www.indyproject.org/index.en.aspx"&gt;Projeto Indy&lt;/a&gt; distribuida junto com o IDE do Delphi;&lt;br/&gt;
&lt;br/&gt;
Da mesma forma que outros protocolos baseados no &lt;a href="http://en.wikipedia.org/wiki/Internet_Protocol"&gt;IP&lt;/a&gt;, usar o POP3 exige que se faça a conexão com o servidor antes de realizar qualquer operação. Temos, então, que informar o nome (ou endereço) desse servidor, a porta onde se conectar e um nome de usuário e sua senha, válidos para a operação desejada.&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; _IdPOP3 : TIdPOP3;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;_IdPOP3 := TIdPOP3.Create (&lt;span style="color:navy;"&gt;&lt;b&gt;Nil&lt;/b&gt;&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
   &lt;span style="margin-left:1em;"&gt;_IdPOP3.Host := _ServidorPOP;&lt;/span&gt;&lt;br/&gt;
   &lt;span style="margin-left:1em;"&gt;_IdPOP3.Port := _PortaPOP;&lt;/span&gt;&lt;br/&gt;
   &lt;span style="margin-left:1em;"&gt;_IdPOP3.Username := _Username;&lt;/span&gt;&lt;br/&gt;
   &lt;span style="margin-left:1em;"&gt;_IdPOP3.Password := _Userpwd;&lt;/span&gt;&lt;br/&gt;
   &lt;span style="margin-left:1em;"&gt;_IdPOP3.AutoLogin := &lt;span style="color:blue;"&gt;True&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;_IdPOP3.Connect ();&lt;/span&gt;
&lt;/div&gt;&lt;br/&gt;
A propriedade &lt;b&gt;AutoLogin&lt;/b&gt; ajustada com o valor &lt;span style="color:blue;"&gt;true&lt;/span&gt; indica que o componente tentará automaticamente fazer o login no servidor sempre que isso for necessário, evitando que tenhamos que comandar o login manualmente.&lt;br/&gt;
&lt;br/&gt;
Uma vez que temos a conexão estabelecida, podemos iniciar a recuperação das mensagens da caixa de entrada. Há basicamente dois níveis de informação que conseguimos recuperar sobre uma mensagem. Em ambos os casos, as informações são armazenadas numa variável do tipo &lt;a href="http://www.e-iter.net/Knowledge/Indy9/007544.html"&gt;TIdMessage&lt;/a&gt;. No primeiro nível, são obtidos somente os dados de cabeçalho da mensagem - como o assunto, o remetente e os destinatários -, o que reduz o tráfego na rede. O trecho abaixo recupera o cabeçalho da primeira mensagem da caixa de entrada:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; msg : TidMessage;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;msg := TidMessage.Create(&lt;span style="color:navy;"&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
  &lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;_IdPOP3.RetrieveHeader (&lt;span style="color:blue;"&gt;1&lt;/span&gt;, msg);&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;msg.Free;&lt;/span&gt;
&lt;/div&gt;&lt;br/&gt;
O segundo nível permite recuperar a mensagem completa, incluindo todas as informações do nível anterior, bem como o corpo da mensagem e todos os anexos dela. Ao utilizar esse método, a caixa postal marca automaticamente a mensagem como lida:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; msg : TidMessage;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;
  &lt;span style="margin-left:1em;"&gt;msg := TidMessage.Create(&lt;span style="color:navy;"&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
  &lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;_IdPOP3.Retrieve (&lt;span style="color:blue;"&gt;1&lt;/span&gt;, msg);&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;msg.Free;&lt;/span&gt;
&lt;/div&gt;&lt;br/&gt;
Com as informações obtidas nesse nível, temos maior flexibilidade para customizar tratamentos para as mensagens. Por exemplo, podemos redirecionar a mensagem para outra pessoa de acordo com o conteúdo ou processar os anexos, salvando-os numa pasta do computador ou num banco de dados.&lt;br/&gt;
&lt;br/&gt;
Não podemos esquecer que o conteúdo de um email pode ser composto de diversas partes distintas, conforme mostrei no &lt;a href="http://balaiotecnologico.blogspot.com/2011/05/enviando-emails-com-delphi-parte-ii.html"&gt;post sobre envio de email com Delphi&lt;/a&gt;. Então, dependendo de como o email foi composto, recuperar o corpo da mensagem pode ser um simples acesso à propriedade &lt;b&gt;msg.Body.Text&lt;/b&gt; ou significará termos que percorrer a lista de partes para determinar qual é o texto contido. Se o texto no corpo está em branco, basta percorrer a lista de partes procurando por uma que seja do tipo texto (TIdText):&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; &lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;parte : TIdMessagePart;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;texto : TIdText;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;corpo : string;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;_IdPOP3.Retrieve(&lt;span style="color:blue;"&gt;1&lt;/span&gt;, msg);&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt; j := &lt;span style="color:blue;"&gt;0&lt;/span&gt; &lt;span style="color:navy;"&gt;&lt;b&gt;to&lt;/b&gt;&lt;/span&gt; msg.MessageParts.Count - &lt;span style="color:blue;"&gt;1&lt;/span&gt; &lt;span style="color:navy;"&gt;&lt;b&gt;do begin&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:2em;"&gt;parte := msg.MessageParts.Items[j];&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;&lt;span style="color:green;"&gt;{ Verifica se a parte é um texto }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (parte &lt;span style="color:navy;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt; TIdText) &lt;span style="color:navy;"&gt;&lt;b&gt;then begin&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:3em;"&gt;texto := parte &lt;span style="color:navy;"&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt; TIdText;&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:3em;"&gt;corpo := texto.Body.Text;&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:3em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;break&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;&lt;br/&gt;
O tipo do texto contido numa parte fica informado na propriedade &lt;b&gt;ContentType&lt;/b&gt;. Como é permitido ter mais que uma parte com texto, pode-se testar esse tipo para recuperar o texto que interessa. É comum enviar uma parte com texto HTML e outra com texto TEXT/PLAIN para que o programa leitor de email decida qual exibir, de acordo com a opção feita pelo usuário.&lt;br/&gt;
&lt;br/&gt;
Da mesma forma que recuperamos o texto lendo as partes, podemos salvar os anexos. Para isso, a parte deve ser do tipo &lt;a href="http://www.e-iter.net/Knowledge/Indy9/007204.html"&gt;TIdAttachment&lt;/a&gt;. Também podemos determinar o tipo do conteúdo do anexo lendo a propriedade &lt;b&gt;ContentType&lt;/b&gt; da parte em questão. Salvar o arquivo fica fácil :&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt; j := &lt;span style="color:blue;"&gt;0&lt;/span&gt; &lt;span style="color:navy;"&gt;&lt;b&gt;to&lt;/b&gt;&lt;/span&gt; msg.MessageParts.Count - &lt;span style="color:blue;"&gt;1&lt;/span&gt; &lt;span style="color:navy;"&gt;&lt;b&gt;do begin&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:1em;"&gt;parte := msg.MessageParts.Items[j];&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Verifica se a parte é um anexo }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (parte &lt;span style="color:navy;"&gt;&lt;b&gt;is&lt;/b&gt;&lt;/span&gt; TIdAttachment) &lt;span style="color:navy;"&gt;&lt;b&gt;then begin&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:2em;"&gt;anexo := parte &lt;span style="color:navy;"&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt; TIdAttachment;&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:2em;"&gt;anexo.SaveToFile(&lt;span style="color:maroon;"&gt;'c:\temp\'&lt;/span&gt; + anexo.FileName);&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;&lt;br/&gt;
Mas, como saber quais mensagens podem ser recuperadas ? A quantidade de mensagens existentes é conseguida através da função &lt;b&gt;CheckMessages&lt;/b&gt;; podemos recuperar qualquer uma delas usando um número inteiro entre 1 e essa quantidade. A lista é trazida em ordem cronológica, com as mensagens mais antigas da caixa de entrada possuindo os menores números de identificação.&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
    &lt;span style="color:navy;"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt; i := &lt;span style="color:blue;"&gt;1&lt;/span&gt; &lt;span style="color:navy;"&gt;&lt;b&gt;to&lt;/b&gt;&lt;/span&gt; _IdPOP3.CheckMessages &lt;span style="color:navy;"&gt;&lt;b&gt;do&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;msg := TidMessage.Create(&lt;span style="color:navy;"&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;_IdPOP3.RetrieveHeader (i, msg);&lt;/span&gt;&lt;br/&gt;
     &lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; DeveRecuperarMsg (msg.MsgId) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:2em;"&gt;TrataMsg (Msg);&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:1em;"&gt;msg.Free;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;&lt;br/&gt;
As mensagens lidas permanecem na caixa até que sejam removidas. O &lt;b&gt;POP3&lt;/b&gt; permite fazer essa remoção mas nem sempre isso é uma opção. Para esses casos, uma sugestão é controlar manualmente as mensagens. Elas possuem uma string de identificação chamada &lt;b&gt;MsgID&lt;/b&gt; que é única, como mostra o código acima. A ideia é recuperar apenas o cabeçalho da mensagem, testar se o MsgID atual já foi tratado antes e só então trazer a mensagem completa, se for necessário.&lt;br/&gt;
&lt;br/&gt;
Quando concluir as operações na caixa postal, finalize a conexão com o POP3 usando a função &lt;b&gt;Disconnect&lt;/b&gt;.&lt;br/&gt;
&lt;br/&gt;
Como se pode ver pelo exemplo retratado neste &lt;i&gt;post&lt;/i&gt;, o protocolo &lt;b&gt;POP3&lt;/b&gt; é bastante simples, limitando-se a poucas funcionalidades básicas. Se for preciso usar recursos mais avançados, tais como restringir as mensagens recuperadas usando filtros ou realizar operações envolvendo "pastas" na caixa postal, teremos que apelar a um protocolo mais completo, como o &lt;b&gt;IMAP4&lt;/b&gt;. Mostro em outra oportunidade como usá-lo.&lt;br/&gt;
&lt;br/&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://pt.wikipedia.org/wiki/Post_Office_Protocol"&gt;Post Office Protocol&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-1846463967238474755?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/uBCihDS1yXVC-ayiwDLrt7M9UOk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uBCihDS1yXVC-ayiwDLrt7M9UOk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/uBCihDS1yXVC-ayiwDLrt7M9UOk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uBCihDS1yXVC-ayiwDLrt7M9UOk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/u-BOVqknMVg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/1846463967238474755/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/08/recuperando-emails-de-uma-caixa-postal.html#comment-form" title="7 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/1846463967238474755?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/1846463967238474755?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/u-BOVqknMVg/recuperando-emails-de-uma-caixa-postal.html" title="Recuperando emails de uma caixa postal com Delphi" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>7</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/08/recuperando-emails-de-uma-caixa-postal.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcFQ307eCp7ImA9WhdREk8.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-5063567635620307608</id><published>2011-08-01T16:46:00.000-03:00</published><updated>2011-08-01T16:46:52.300-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-01T16:46:52.300-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Notícias" /><title>Adobe lança ferramenta para criação de conteúdo rico com HTML5</title><content type="html">Já faz algum tempo que a mídia especializada em TI vem prevendo dificuldades para a tecnologia Flash. Razões para isso não faltam. Primeiro, foi o surgimento do &lt;a href="http://en.wikipedia.org/wiki/HTML5#New_APIs"&gt;HTML5&lt;/a&gt;, cuja especificação inclui recursos que permitem desenvolver animações apenas com padrões abertos. Depois, &lt;a href="http://blogs.estadao.com.br/link/steve-jobs-rebate-ninguem-mais-vai-usar-flash/"&gt;as declarações de Steve Jobs&lt;/a&gt; criticando o excesso de bugs existentes no Flash, argumento usado para justificar a falta da tecnologia Flash no sistema usado pelos dispositivos móveis da Apple.&lt;br /&gt;
&lt;br /&gt;
A própria Adobe parece estar de precavendo contra uma possível debandada no uso de sua tecnologia. Hoje eles anunciaram o &lt;i&gt;preview&lt;/i&gt; de uma ferramenta onde as animações são construídas com padrões da internet - HTML5, CSS e JavaScript - ao invés do Flash. Com isso, procuram se manter no topo no nicho tecnológico em que conquistaram grande destaque. Ao que parece, se o Flash realmente naufragar, a Adobe ainda terá uma grande ferramenta para construção de animações. Caso ele sobreviva, nunca é demais dar ao desenvolvedor outras possibilidade de escolha, principalmente se há uma opção baseada em padrões abertos.&lt;br /&gt;
&lt;br /&gt;
A ferramenta, que chama-se &lt;b&gt;Edge&lt;/b&gt;, está disponível no site &lt;a href="http://labs.adobe.com/technologies/edge/"&gt;Adobe Edge&lt;/a&gt; como parte do laboratório da Adobe. O anúncio dela foi tema de um artigo na &lt;a href="http://www.infoworld.com"&gt;Infoworld.com&lt;/a&gt;, o qual reproduzo abaixo,  traduzido:&lt;br /&gt;
&lt;div style="background-color: #ebebf5; border: 1px solid silver; padding: 5px 10px 1em 5px; width: 96%;"&gt;
Plantando sementes que têm o potencial de derrubar sua própria franquia de sucesso em desenvolvimento de animações Flash, a Adobe lançou um preview de uma nova aplicação chamada &lt;b&gt;Adobe Edge&lt;/b&gt;, projetada para montar conteúdo web dinâmico usando HTML5 e outros padrões abertos relacionados, anunciou a empresa nesta segunda-feira.&lt;br /&gt;
&lt;br /&gt;
"Esta é uma ferramenta para animações e interatividade para &lt;i&gt;designers&lt;/i&gt; que queiram construir conteúdo web interativo usando padrões da Web", disse Devin Fernandez, gerente de produto da Adobe.&lt;br /&gt;
&lt;br /&gt;
Tradicionalmente, &lt;i&gt;Web designers&lt;/i&gt; têm usado o Adobe Flash, ou concorrentes como o Microsoft Silverlight, para acrescentar animações estilosas e conteúdo interativo a páginas Web, na forma de telas de abertura para o site, gráficos interativos, vídeos curtos ou propagandas. A Adobe estima que 99 porcento de todos os computadores desktop possuem o plug-in necessário para executar arquivos Flash.&lt;br /&gt;
&lt;br /&gt;
Nos últimos anos, no entanto, a W3C (World Wide Web Consortium) e outros órgãos de padronização vêm desenvolvendo um punhado de especificações que podem ser usadas na criação de conteúdo rico semelhante ao Flash. Os fabricantes de navegadores estão incorporando esses padrões - tais como HTML5, a tag Canvas, JavaScript e CSS (Cascading Style Sheets) - em seus navegadores, o que elimina a necessidade de um plug-in externo para executá-los.&lt;br /&gt;
&lt;br /&gt;
A Apple também não está ajudando a sorte da Adobe pois seu CEO, Steve Jobs, criticou o Flash no passado, afirmando que ele possui bugs demais e instando os desenvolvedores a usarem o HTML5 no lugar.&lt;br /&gt;
&lt;br /&gt;
"Muitos trabalhos que estavam previamente reservados para o Flash estão agora sendo feitos com padrões Web," admitiu Fernandez. "Nós vemos como uma enorme oportunidade para a companhia ajudar as pessoas a extrairem o melhor do HTML5."&lt;br /&gt;
&lt;br /&gt;
Esta ferramenta usa HTML5, CSS e Javascript para inserir conteúdo Web animado diretamente numa página HTML. Com uma abordagem similar à da ferramenta de criação do Flash, o Edge permite ao desenvolvedor alterar atributos de uma imagem ou de um elemento HTML ao longo de um intervalo de tempo, resultando numa página animada.&lt;br /&gt;
&lt;br /&gt;
"A Adobe tem mostrado que pode se adaptar muito bem a novas tendências. Isto mostra que eles podem se manter como principais vendedores de ferramentas, não importa qual a tecnologia que está embarcada," disse Al Hilwa, analista de desenvolvimento de aplicações do IDC. "Há poucas empresas sintonizadas com as necessidades e sensibilidades de um &lt;i&gt;designer&lt;/i&gt; como a Adobe está, e esta ferramenta realmente mostra isso. Ela traz o modelo de linha do tempo, que é familiar a muitos desenvolvedores Flash, para o mundo novo do HTML5 e JavaScript, enquanto mantém a integridade do código."&lt;br /&gt;
&lt;br /&gt;
A Adobe não tem expectativa de que o Edge vá suplantar o Flash inteiramente, ao menos não no futuro próximo. "A tecnologia Flash permanecerá um componente chave para casos de uso específicos, como vídeos de qualidade e jogos," disse Fernandez. "Nós definitivamente vemos HTML5 e Flash coexistindo, e, por isso, continuaremos a trabalhar em soluções para ambos na Adobe. Os usuários decidirão qual tecnologia eles usarão."&lt;br /&gt;
&lt;br /&gt;
A edição &lt;i&gt;preview&lt;/i&gt; está disponível como um download gratuito. Adobe espera liberar a versão comercial final em 2012, segundo Fernandez. Haverá versões tanto para Microsoft Windows quanto para Apple Macintosh.
&lt;/div&gt;
&lt;br /&gt;
A matéria original em inglês pode ser encontrada &lt;a href="http://images.infoworld.com/d/application-development/adobe-launches-html5-rich-media-editor-168561?source=rss_application_development"&gt;nesse link&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;

&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://images.infoworld.com/d/application-development/adobe-launches-html5-rich-media-editor-168561?source=rss_application_development"&gt;Adobe launches HTML5 rich media editor&lt;/a&gt;, &lt;a href="http://labs.adobe.com/technologies/edge/"&gt;Site do Adobe Edge&lt;/a&gt; 
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-5063567635620307608?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Z7Lg7tBk5qCHQw0oKFxBiddBc1g/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z7Lg7tBk5qCHQw0oKFxBiddBc1g/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Z7Lg7tBk5qCHQw0oKFxBiddBc1g/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z7Lg7tBk5qCHQw0oKFxBiddBc1g/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/Wy5ZfVr1pds" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/5063567635620307608/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/08/adobe-lanca-ferramenta-para-criacao-de.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/5063567635620307608?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/5063567635620307608?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/Wy5ZfVr1pds/adobe-lanca-ferramenta-para-criacao-de.html" title="Adobe lança ferramenta para criação de conteúdo rico com HTML5" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/08/adobe-lanca-ferramenta-para-criacao-de.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMMRXw5fSp7ImA9WhdSEk0.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-5062430319094882215</id><published>2011-07-20T19:21:00.000-03:00</published><updated>2011-07-20T19:21:24.225-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-20T19:21:24.225-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>Usando um Web Service no Visual Studio - parte II</title><content type="html">Escrevi um post em 2009 explicando alguns detalhes sobre o funcionamento de Web Services e mostrando &lt;a href="http://balaiotecnologico.blogspot.com/2009/10/usando-um-web-service-num-projeto-do.html"&gt;como usá-los em um projeto do Visual Studio&lt;/a&gt;. Aquele &lt;i&gt;post&lt;/i&gt; descrevia como usar o IDE para gerar automaticamente uma classe &lt;b&gt;proxy&lt;/b&gt;, necessária para fazermos a chamada das funções remotas disponibilizadas pelo serviço. Tal classe é chamada de "proxy" por ser projetada segundo o &lt;a href="http://balaiotecnologico.blogspot.com/2010/01/design-patterns-com-delphi-proxy-parte.html"&gt;design pattern que leva esse nome&lt;/a&gt;.&lt;br/&gt;
&lt;br/&gt;
Como se vê no post, gerar o proxy é um procedimento muito simples, assim como utilizá-lo para executar a função remota. Para a grande maioria das situações, usar o Web Service desse modo é suficiente. No entanto, há uma desvantagem na forma como isso é feito. Uma vez que o processo todo é automatizado e o trâmite da comunicação com o servidor fica escondido nas bibliotecas da plataforma .Net, não é possível customizar parte alguma da comunicação.&lt;br/&gt;
&lt;br/&gt;
Mas, porque seria necessário interceptar a comunicação e alterar alguma coisa ? Uma razão óbvia é depuração. Isso é, se acontecer um erro, é interessante saber quais foram os comandos enviados e os respectivos retornos fornecidos pelo servidor. Um &lt;a href="http://pt.wikipedia.org/wiki/Sniffing"&gt;sniffer&lt;/a&gt; não conseguiria fazer esse serviço caso o web service esteja num canal seguro (HTTPS) pois as informações são criptografadas.&lt;br/&gt;
&lt;br/&gt;
Uma outra razão seria customizar a serialização das informações, oportunidade para enxugar o texto trafegado, removendo-se partes sobressalentes. Ou, ainda, para adequar a formatação dos parâmetros da função que são trafegados. Do ponto de vista do proxy, a &lt;b&gt;serialização&lt;/b&gt; é o processo pelo qual o nome da função remota e os parâmetros que passamos para ela são transformados em texto e empacotados num XML antes de serem enviados para execução no servidor. Ao receber uma resposta do servidor, o proxy tem que aplicar o processo inverso no XML recebido, isto é, fazer a &lt;b&gt;desserialização&lt;/b&gt;, convertendo o conteúdo do XML em tipos de dados nativos da linguagem e associando-o ao valor de retorno da função. Lembre-se que o protocolo usado para comunicação com web services é o &lt;a href="http://en.wikipedia.org/wiki/SOAP"&gt;SOAP&lt;/a&gt;, que é baseado em XML. Portanto, um parâmetro com tipo de dado complexo pode exigir uma formatação especial pra funcionar.&lt;br/&gt;
&lt;br/&gt;
Já que o código gerado automaticamente pelo IDE do Visual Studio não permite interceptar a serialização, teremos que optar por um método alternativo. O SDK do .NET vem com uma ferramenta de linha de comando chamada &lt;a href="http://msdn.microsoft.com/en-us/library/7h3ystb6%28v=vs.80%29.aspx"&gt;WSDL.EXE&lt;/a&gt;. Basicamente, nela você informa o arquivo descritor do Web Service (WSDL) e ela gera a classe proxy apropriada. O quadro abaixo mostra um exemplo básico de como usar a ferramenta:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;span style="color:#0A0A0A;"&gt;wsdl /language:CS /n:"WNameSpace" WMeuServico.wsdl&lt;/span&gt;
&lt;/div&gt;
&lt;br/&gt;
Nesse exemplo, o &lt;b&gt;WSDL.EXE&lt;/b&gt; interpretará a descrição contida no arquivo &lt;i&gt;WMeuServico.wsdl&lt;/i&gt; e gerará um uma classe proxy em C# inserindo-a no namespace &lt;i&gt;WNameSpace&lt;/i&gt;. A diferença em relação ao proxy gerado diretamente pelo Visual Studio está na infraestrutura de classes envolvidas. No caso do &lt;b&gt;WSDL.EXE&lt;/b&gt;, o proxy é uma herança de &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soaphttpclientprotocol.aspx"&gt;SoapHttpClientProtocol&lt;/a&gt;. A execução dos métodos dessa classe pode ser extendida usando-se atributos que implementem as funções contidas em &lt;a href="http://msdn.microsoft.com/pt-br/library/system.web.services.protocols.soapextension.aspx"&gt;SoapExtension&lt;/a&gt;. Ou seja, cria-se uma herança de &lt;b&gt;SoapExtension&lt;/b&gt; que então é aplicada como um atributo da função existente no Web Service. Quando a função remota é chamada, a serialização passa a ser controlada pela nossa versão do &lt;b&gt;SoapExtension&lt;/b&gt;.&lt;br/&gt;
&lt;br/&gt;
O cerne dessa solução é o método &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapextension.processmessage.aspx"&gt;ProcessMessage&lt;/a&gt;. Ele recebe uma instância com a mensagem &lt;b&gt;SOAP&lt;/b&gt; atual, permitindo manipulá-la conforme a necessidade.&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;span style="color:blue;"&gt;public class&lt;/span&gt; TWTraceExtension : &lt;span style="color:#009963;"&gt;SoapExtension&lt;/span&gt;&lt;br/&gt;
{&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:gray;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:blue;"&gt;public override void&lt;/span&gt; ProcessMessage(&lt;span style="color:#009963;"&gt;SoapMessage&lt;/span&gt; message)&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;{&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:2em;"&gt;&lt;span style="color:blue;"&gt;switch&lt;/span&gt; (message.Stage)&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:2em;"&gt;{&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:2em;"&gt;&lt;span style="color:blue;"&gt;case&lt;/span&gt; &lt;span style="color:#009963;"&gt;SoapMessageStage&lt;/span&gt;.BeforeSerialize:&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:3em;"&gt;&lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:2em;"&gt;&lt;span style="color:blue;"&gt;case&lt;/span&gt; &lt;span style="color:#009963;"&gt;SoapMessageStage&lt;/span&gt;.AfterSerialize:&lt;/span&gt;&lt;br/&gt;
           &lt;span style="margin-left:3em;"&gt;StreamWriter w = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#009963;"&gt;StreamWriter&lt;/span&gt;(_LogFile);&lt;/span&gt;&lt;br/&gt;
           &lt;span style="margin-left:3em;"&gt;w.WriteLine (&lt;span style="color:maroon;"&gt;"=&gt; Serializado"&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
           &lt;span style="margin-left:3em;"&gt;w.Flush();&lt;/span&gt;&lt;br/&gt;
           &lt;span style="margin-left:3em;"&gt;message.Stream.Position = 0;&lt;/span&gt;&lt;br/&gt;
           &lt;span style="margin-left:3em;"&gt;Copy(message.Stream, fs);&lt;/span&gt;&lt;br/&gt;
           &lt;span style="margin-left:3em;"&gt;w.Close();&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:3em;"&gt;&lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:1em;"&gt;&lt;span style="color:blue;"&gt;case&lt;/span&gt; &lt;span style="color:#009963;"&gt;SoapMessageStage&lt;/span&gt;.BeforeDeserialize:&lt;/span&gt;&lt;br/&gt;
           &lt;span style="margin-left:3em;"&gt;StreamWriter w = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#009963;"&gt;StreamWriter&lt;/span&gt;(_LogFile);&lt;/span&gt;&lt;br/&gt;
           &lt;span style="margin-left:3em;"&gt;w.WriteLine (&lt;span style="color:maroon;"&gt;"=&gt; Desserializado"&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
           &lt;span style="margin-left:3em;"&gt;w.Flush();&lt;/span&gt;&lt;br/&gt;
           &lt;span style="margin-left:3em;"&gt;message.Stream.Position = 0;&lt;/span&gt;&lt;br/&gt;
           &lt;span style="margin-left:3em;"&gt;Copy(message.Stream, fs);&lt;/span&gt;&lt;br/&gt;
           &lt;span style="margin-left:3em;"&gt;w.Close();&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:3em;"&gt;&lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:2em;"&gt;&lt;span style="blue;"&gt;case&lt;/span&gt; &lt;span style="color:#009963;"&gt;SoapMessageStage&lt;/span&gt;.AfterDeserialize:&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:3em;"&gt;&lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:2em;"&gt;}&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;}&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="gray;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
}
&lt;/div&gt;
&lt;br/&gt;
Agora que temos a extensão do processo de serialização e desserialização, precisamos criar um atributo que seja aplicável ao método do Web Service. Fazemos isso criando uma extensão da classe de atributo &lt;b&gt;SoapExtensionAttribute&lt;/b&gt;, cujo objetivo principal é determinar qual classe deve ser usada para serializar. Veja um exemplo:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
  [&lt;span style="color:#009963;"&gt;AttributeUsage&lt;/span&gt;(&lt;span style="color:#009963;"&gt;AttributeTargets&lt;/span&gt;.Method)]&lt;br/&gt;
  &lt;span style="color:blue;"&gt;public class&lt;/span&gt; TWTraceExtensionAttribute : &lt;span style="color:#009963;"&gt;SoapExtensionAttribute&lt;/span&gt;&lt;br/&gt;
  {&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:gray;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
     &lt;span style="margin-left:1em;"&gt;&lt;span style="color:blue;"&gt;public override&lt;/span&gt; &lt;span style="color:#009963;"&gt;Type&lt;/span&gt; ExtensionType&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;{&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:2em;"&gt;&lt;span style="color:blue;"&gt;get&lt;/span&gt; { &lt;span style="blue;"&gt;return&lt;/span&gt; &lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(TWTraceExtension); }&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;}&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:gray;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
}
&lt;/div&gt;
&lt;br/&gt;
Veja que a propriedade &lt;b&gt;ExtensionType&lt;/b&gt; é sobrescrita para retornar informações sobre nossa classe de serialização. Um outro detalhe é que a declaração de nossa classe de atributo é ela própria configurada por um atributo indicativo do tipo de uso esperado para ela : ser atributo de métodos de outras classes.&lt;br/&gt;
&lt;br/&gt;
Por fim, devemos usar o novo atributo criado acima para configurar o método do Web Service que queremos consumir. Isso implica modificar o fonte gerado automaticamente pelo &lt;b&gt;WSDL&lt;/b&gt;. Então, a configuração terá que ser refeita toda vez que gerar o fonte. Veja um exemplo:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:gray;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:blue;"&gt;public partial class&lt;/span&gt; Service1 : System.Web.Services.Protocols.&lt;span style="color:#009963;"&gt;SoapHttpClientProtocol&lt;/span&gt;&lt;br/&gt;
{&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:gray;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;  
        &lt;b&gt;[&lt;span style="color:#009963;"&gt;TWTraceExtensionAttribute&lt;/span&gt;(Filename = &lt;span style="color:maroon;"&gt;"c:\\log.txt"&lt;/span&gt;)]&lt;/b&gt;&lt;br/&gt;
        &lt;span style="color:blue;"&gt;public string&lt;/span&gt; consultaNFe ([System.Xml.Serialization.&lt;span style="color:#009963;"&gt;XmlAnyElementAttribute&lt;/span&gt;()] &lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;System.Xml.&lt;span style="color:#009963;"&gt;XmlElement&lt;/span&gt; Any)&lt;/span&gt;&lt;br/&gt;
{&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:gray;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
        }
&lt;/div&gt;
&lt;br/&gt;
A mesma solução pode ser adotada para a classe servidora do Web Service, situação em que estaremos interceptando as mensagens que um Web Service desenvolvido por nós está trocando.&lt;br/&gt;
&lt;br/&gt;
Um exemplo completo de customização do &lt;b&gt;SoapExtension&lt;/b&gt; pode ser encontrado &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapextension.aspx"&gt;na documentação dessa classe no MSDN&lt;/a&gt;. No exemplo, as mensagens trafegadas são armazenadas num arquivo de log.&lt;br/&gt;
&lt;br/&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://balaiotecnologico.blogspot.com/2009/10/usando-um-web-service-num-projeto-do.html"&gt;Usando um Web Service no Visual Studio&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapextension.aspx"&gt;Classe SoapExtension&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/7h3ystb6%28v=vs.80%29.aspx"&gt;Ferramenta WSDL.EXE&lt;/a&gt;, &lt;a href="http://progtutorials.tripod.com/soapext.htm"&gt;SOAP Extension – How does it work?&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-5062430319094882215?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/H3yOpNXRfBYh1F01x-1vhQYODRI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/H3yOpNXRfBYh1F01x-1vhQYODRI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/H3yOpNXRfBYh1F01x-1vhQYODRI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/H3yOpNXRfBYh1F01x-1vhQYODRI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/HGzkcKrP9qU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/5062430319094882215/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/07/usando-um-web-service-no-visual-studio.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/5062430319094882215?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/5062430319094882215?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/HGzkcKrP9qU/usando-um-web-service-no-visual-studio.html" title="Usando um Web Service no Visual Studio - parte II" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/07/usando-um-web-service-no-visual-studio.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4BRH88cSp7ImA9WhdTEEs.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-1993739993294211154</id><published>2011-07-07T15:39:00.000-03:00</published><updated>2011-07-07T15:39:15.179-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-07T15:39:15.179-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Design Patterns" /><title>Design Patterns com Delphi: State - Parte II</title><content type="html">No &lt;a href="http://balaiotecnologico.blogspot.com/2011/06/design-patterns-com-delphi-state-parte.html"&gt;último post&lt;/a&gt;, apresentei o conceito do &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html"&gt;Design Pattern&lt;/a&gt; &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html#categorias"&gt;comportamental&lt;/a&gt; &lt;b&gt;State&lt;/b&gt;. Como exemplo de situação onde o padrão é aplicável, criei um controle simples de conta corrente no qual a conta tem comportamentos diferentes, reagindo ao nível do saldo que ela atualmente contém.&lt;br /&gt;
&lt;br /&gt;
Para ficar mais fácil visualizar, reproduzo abaixo o diagrama de classes que representa uma solução para a situação do exemplo.
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;width: 96%;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lgaf.webs.com/arqs/State.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;width:100%;" src="http://lgaf.webs.com/arqs/State.gif" alt="Diagrama UML para o padrão State" id="designPatternState20110629" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
O modo como uma conta tem que se comportar é ditado por uma classe abstrata simples, chamada de &lt;b&gt;TWEstadoConta&lt;/b&gt; no diagrama. Essa classe é apenas uma interface que introduz as funções e propriedades esperadas para a operação básica da conta em si. Os estados reais podem, então, ser implementados como heranças dessa interface, providenciando a diferenciação necessária.&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;TWEstadoConta = &lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;protected&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;_Saldo : Double;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;_PorcRendim : Double;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;_LimInf, _LimSup : Double;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;_Conta : TWConta;&lt;/span&gt;
&lt;span style="color:green;margin-left:2em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
      &lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:2em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; Depositar (AValor : Double);&lt;span style="color:navy;"&gt;&lt;b&gt;virtual&lt;/b&gt;&lt;/span&gt;;&lt;span style="color:navy;"&gt;&lt;b&gt;abstract&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; Sacar     (AValor : Double);&lt;span style="color:navy;"&gt;&lt;b&gt;virtual&lt;/b&gt;&lt;/span&gt;;&lt;span style="color:navy;"&gt;&lt;b&gt;abstract&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; AplicarRendimento;&lt;span style="color:navy;"&gt;&lt;b&gt;virtual&lt;/b&gt;&lt;/span&gt;;&lt;span style="color:navy;"&gt;&lt;b&gt;abstract&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
TWContaComum = &lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWEstadoConta)&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;protected&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;_TaxaServico : Double;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;Constructor&lt;/b&gt;&lt;/span&gt; Create (AConta : TWConta);&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; Depositar (AValor : Double);&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; Sacar     (AValor : Double);&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; AplicarRendimento;&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
  &lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
TWContaDiferenciada = &lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWContaComum)&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;protected&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;_TaxaJuros : Double;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;Constructor&lt;/b&gt;&lt;/span&gt; Create (AConta : TWConta);&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; Depositar (AValor : Double);&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; Sacar     (AValor : Double);&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; AplicarRendimento;&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
TWContaOuro = &lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWEstadoConta)&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;protected&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;Constructor&lt;/b&gt;&lt;/span&gt; Create (AConta : TWConta);&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; Depositar (AValor : Double);&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; Sacar     (AValor : Double);&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; AplicarRendimento;&lt;span style="color:navy;"&gt;&lt;b&gt;override&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
&lt;br /&gt;
As operações para depósito, saque e a que aplica rendimentos ao saldo da conta são abstratas na interface mas implementadas pela classe de cada estado possível. Veja, por exemplo, as diferenças da operação de saque:&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; TWContaComum.Sacar (AValor : Double);&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; lValorReal : Double;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ Conta comum, aplica a taxa de serviço }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lValorReal := AValor + _TaxaServico;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_Saldo := _Saldo - lValorReal;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; TWContaDiferenciada.Sacar (AValor : Double);&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; lJuros, lValorReal : Double;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ Na Conta diferenciada, aplica taxa de serviço, critica se extrapolar o limite de crédito e aplica uma taxa de juros se a conta ficar negativa }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lValorReal := AValor + _TaxaServico;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (_Saldo - lValorReal) &lt; _LimInf &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;raise&lt;/b&gt;&lt;/span&gt; Exception.Create(&lt;span style="color:maroon;"&gt;'Saque não pode ser efetivado. Conta sem saldo.'&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lJuros := &lt;span style="color:blue;"&gt;0.0&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (_Saldo - lValorReal) &lt; &lt;span style="color:blue;"&gt;0.0&lt;/span&gt; &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;lJuros := (lValorReal - _Saldo) * _TaxaJuros / &lt;span style="color:blue;"&gt;100.0&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_Saldo := _Saldo - lValorReal - lJuros;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; TWContaOuro.Sacar (AValor : Double);&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:2em;"&gt;{ Conta Ouro, não se preocupa com nada - apenas saca. }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_Saldo := _Saldo - AValor;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
&lt;br /&gt;
Os construtores das classes que representam estados têm que alimentar os valores das propriedades internas, caracterizando os respectivos estados. É isso que permitirá à classe da conta decidir qual estado deve estar ativo num determinado momento:&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;Constructor&lt;/b&gt;&lt;/span&gt; TWContaComum.Create (AConta : TWConta);&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;inherited&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_PorcRendim := &lt;span style="color:blue;"&gt;1.0&lt;/span&gt;; &lt;span style="color:green;"&gt;{ Rendimento padrão : 1%}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_TaxaServico := &lt;span style="color:blue;"&gt;5.00&lt;/span&gt;; &lt;span style="color:green;"&gt;{ Saques são cobrados }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ Valores de saldo que delimitam um estado }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_LimInf := &lt;span style="color:blue;"&gt;100.00&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_LimSup := &lt;span style="color:blue;"&gt;999.99&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;Constructor&lt;/b&gt;&lt;/span&gt; TWContaDiferenciada.Create (AConta : TWConta);&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;inherited&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_PorcRendim  :=  &lt;span style="color:blue;"&gt;0.0&lt;/span&gt;; &lt;span style="color:green;"&gt;{ Sem rendimento }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_TaxaJuros   := &lt;span style="color:blue;"&gt;1.00&lt;/span&gt;; &lt;span style="color:green;"&gt;{ Taxa de juros sobre saques qdo a conta fica sem saldo }&lt;/span&gt; &lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_TaxaServico := &lt;span style="color:blue;"&gt;10.00&lt;/span&gt;; &lt;span style="color:green;"&gt;{ Saques são cobrados }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ Valores de saldo que delimitam um estado }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_LimInf := &lt;span style="color:blue;"&gt;-100.00&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_LimSup :=   &lt;span style="color:blue;"&gt;99.99&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;Constructor&lt;/b&gt;&lt;/span&gt; TWContaOuro.Create (AConta : TWConta);&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;inherited&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  _PorcRendim := 2.00; &lt;span style="color:green;"&gt;{ Rendimento Ouro : 2% }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="color:green;margin-left:1em;"&gt;{ Valores de saldo que delimitam um estado }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_LimInf := &lt;span style="color:blue;"&gt;1000.00&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_LimSup := &lt;span style="color:blue;"&gt;99999.99&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
&lt;br /&gt;
A classe da Conta, então, deve guardar uma referência do estado atual para poder realizar as operações solicitadas. Portanto, ela age como uma ponte, transferindo para a classe de estado a responsabilidade de executar efetivamente a operação.
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;TWConta = &lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;_Estado : TWEstadoConta;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:2em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:2em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; Depositar (AValor : Double);&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; Sacar     (AValor : Double);&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; AplicarRendimento;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:2em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; ObtemSaldo : double;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; ObtemEstado : TWEstadoConta;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
Para que a implementação desse padrão funcione, é preciso trocar dinamicamente a instância de classe que representa o estado atual. E quando é necessário efetuar essa troca da instância de estado ? O bom senso diz que isso deve acontecer após qualquer operação que possa afetar o estado monitorado. No nosso caso, isso significa atuar em todas as operações que modifiquem o saldo da conta.&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; TWConta.VerificaStatus;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; lNovoEstado : TWEstadoConta;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:2em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Testa as variações de estado }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lNovoEstado := &lt;span style="color:navy;"&gt;&lt;b&gt;Nil&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (_Estado._Saldo &lt; _Estado._LimInf) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:green;"&gt;{ Rebaixa de COMUM para DIFERENCIADA }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (_Estado.InheritsFrom (TWContaComum)) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;lNovoEstado := TWContaDiferenciada.Create (Self);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:green;"&gt;{ Rebaixa de OURO para COMUM }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (_Estado.InheritsFrom (TWContaOuro)) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;lNovoEstado := TWContaComum.Create (Self);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (_Estado._Saldo &gt; _Estado._LimSup) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:green;"&gt;{ Eleva de COMUM para OURO }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (_Estado.InheritsFrom (TWContaComum)) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;lNovoEstado := TWContaOuro.Create (Self);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:green;"&gt;{ Rebaixa de OURO para COMUM }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (_Estado.InheritsFrom (TWContaOuro)) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;lNovoEstado := TWContaComum.Create (Self);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Efetiva a troca de estado }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (lNovoEstado &lt;&gt; &lt;span style="color:navy;"&gt;&lt;b&gt;Nil&lt;/b&gt;&lt;/span&gt;) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;SetEstado (lNovoEstado);&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; TWConta.Depositar (AValor : Double);&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_Estado.Depositar(Avalor);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;VerificaStatus ();&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; TWConta.Sacar (AValor : Double);
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_Estado.Sacar (AValor);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;VerificaStatus ();&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; TWConta.AplicarRendimento;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_Estado.AplicarRendimento ();&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;VerificaStatus ();&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
&lt;br /&gt;
Pelo quadro acima, vemos que quem faz a troca é a própria conta pois as classes de estado não conhecem o fluxo de mudança, isto é, nenhuma delas sabe qual é o estado seguinte para o qual a conta pode ser lançada. Isso facilita a inclusão de novos estados já que apenas um ponto precisa ser modificado para levá-lo em consideração.&lt;br /&gt;
&lt;br /&gt;
A recuperação de uma instância da classe de estado pode ser modelada para usar o &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html"&gt;Design Pattern&lt;/a&gt; &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html#categorias"&gt;criacional&lt;/a&gt; &lt;b&gt;Factory&lt;/b&gt; ou ainda o &lt;b&gt;Singleton&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Usar uma &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/design-patterns-com-delphi-factory.html"&gt;Factory&lt;/a&gt; como fizemos em &lt;b&gt;VerificaStatus&lt;/b&gt; pode acarretar problemas de desempenho se as trocas de estado ocorrerem com muita frequência. O mesmo é válido se for grande o volume de dados que caracterizam os estados. Neste caso, optar por um &lt;a href="http://balaiotecnologico.blogspot.com/2009/08/design-patterns-com-delphi-singleton.html"&gt;Singleton&lt;/a&gt; é recomendável, sem esquecer de que ele deve se restringir ao escopo da classe. Isto é, cada instancia da classe deve ter seu &lt;b&gt;Singleton&lt;/b&gt; particular; senão, o estado de uma instância poderá se confundir com o de outras que porventura existam ao mesmo tempo.&lt;br /&gt;
&lt;br /&gt;
O download do projeto Delphi com esse exemplo pode ser feito &lt;a href="http://lgaf.webs.com/arqs/State.7z"&gt;a partir desse link&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;

&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://balaiotecnologico.blogspot.com/search/label/Design%20Patterns"&gt;Posts sobre Design Patterns&lt;/a&gt;, &lt;a href="http://lgaf.webs.com/arqs/State.7z"&gt;Download do Exemplo para o padrão State&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-1993739993294211154?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/q_iGhTgIRrnMBi_QvxnGlwUnsno/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/q_iGhTgIRrnMBi_QvxnGlwUnsno/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/q_iGhTgIRrnMBi_QvxnGlwUnsno/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/q_iGhTgIRrnMBi_QvxnGlwUnsno/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/aHhKtOgaAh0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/1993739993294211154/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/07/design-patterns-com-delphi-state-parte.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/1993739993294211154?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/1993739993294211154?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/aHhKtOgaAh0/design-patterns-com-delphi-state-parte.html" title="Design Patterns com Delphi: State - Parte II" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/07/design-patterns-com-delphi-state-parte.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4ERnk_cSp7ImA9WhZaEUU.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-3591165740189726423</id><published>2011-06-27T11:11:00.000-03:00</published><updated>2011-06-27T11:11:47.749-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-27T11:11:47.749-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Conceitos" /><category scheme="http://www.blogger.com/atom/ns#" term="Design Patterns" /><title>Design Patterns com Delphi: State - Parte I</title><content type="html">Ao longo de sua existência, um objeto em um sistema computacional pode sofrer variações em seu estado interno. Isto é, cada operação realizada com ele ou cada propriedade ajustada altera o valor de variáveis internas (membros), introduzindo mudanças no seu estado. Se o objeto tiver que se comportar de forma diferente de acordo com seu estado interno, a implementação dele tende a se tornar cada vez mais complexa à medida que a quantidade de estados possíveis aumenta, dificultando a manutenção do sistema como um todo.&lt;br /&gt;
&lt;br /&gt;
O &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html"&gt;Design Pattern&lt;/a&gt; &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html#categorias"&gt;comportamental&lt;/a&gt; &lt;b&gt;State&lt;/b&gt; foi concebido para atender a situações como as descritas no parágrafo anterior, simplificando a manutenção do sistema. Como exemplo do cenário onde o padrão é aplicável, imagine um sistema que controle contas correntes. Dependendo do saldo total, a conta é classificada de uma maneira que determina a disponibilidade de certas operações. Também determina se os serviços disponíveis para a conta são cobrados, a taxa de remuneração que se aplicará ao saldo (se aplicável), taxa juros sobre empréstimos (se aplicável), etc.&lt;br /&gt;
&lt;br /&gt;
A base do conceito para implementarmos esse padrão é a existência de uma interface que torna públicas as operações disponíveis para a classe principal – a conta, no nosso exemplo. O estado interno é mantido por outra classe que tem o conhecimento de como se comportar adequadamente para esse estado específico. Quando a classe principal precisa realizar uma operação, ela delega a responsabilidade para a classe que mantém o estado. Podemos perceber, então, que cada conjunto diferente de comportamentos baseado no estado da classe principal será tratado por uma classe de estado diferente. O resultado desse arranjo é que a classe principal consegue comportar-se da forma planejada apenas trocando a instância interna da classe de estado, o que ocorre de forma transparente para quem usa a classe principal.&lt;br /&gt;
&lt;br /&gt;
Veja no diagrama UML abaixo a relação entre as classes previstas para nosso exemplo:&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;width: 96%;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lgaf.webs.com/arqs/State.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;width:100%;" src="http://lgaf.webs.com/arqs/State.gif" alt="Diagrama UML para o padrão State" id="designPatternState20110627" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Classes de objetos que podem alternar seu estado de acordo com uma lista previamente conhecida normalmente têm um &lt;a href="http://en.wikipedia.org/wiki/State_diagram"&gt;Diagrama de Estados&lt;/a&gt; associado a elas quando modelamos o projeto usando UML. Esse diagrama documenta as mudanças de estado permitidas para o objeto. Com base no saldo existente, a conta do exemplo pode ser classificada como Ouro (melhores taxas de rendimento, menor preço para serviços), Comum (as taxas e preços normais se aplicam) e Diferenciada (o saldo baixo ou negativo leva a menor rendimento, serviços mais caros e proibição de saques e empréstimos).&lt;br /&gt;
&lt;br /&gt;
Formalmente, as classes que participam da solução para o &lt;i&gt;pattern&lt;/i&gt; &lt;b&gt;State&lt;/b&gt; recebem os seguintes nomes:&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;&lt;b&gt;Context&lt;/b&gt; é a classe que publica as operações que estarão disponíveis para as demais partes do sistema, sendo, por isso, a classe principal da solução. Ela mantém uma referência para a classe que contém o estado atual e o comportamento associado a este estado. No diagrama acima, a classe &lt;b&gt;Context&lt;/b&gt; é a &lt;b&gt;TWConta&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;&lt;b&gt;State&lt;/b&gt; é uma interface que define quais as operações do &lt;b&gt;Context&lt;/b&gt; terão comportamento baseado num estado. Ela contém ainda as propriedades relevantes para determinar quando uma troca de estado deve acontecer. Esse papel é executado pela classe &lt;b&gt;TWEstadoConta&lt;/b&gt; no diagrama acima. Por ser uma interface, ela normalmente será abstrata, isto é, muitas das funções serão implementadas somente por suas heranças.&lt;br /&gt;
&lt;br /&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;&lt;b&gt;Concrete State&lt;/b&gt; são as classes que provêem o comportamento adequado para cada estado possível. Elas herdam da interface &lt;b&gt;State&lt;/b&gt;, promovendo a implementação necessária para cada operação introduzida por ela. No diagram há 3 classes nessa categoria: &lt;b&gt;TWContaComum&lt;/b&gt;, &lt;b&gt;TWContaOuro&lt;/b&gt; e &lt;b&gt;TWContaDiferenciada&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;img src="http://lgaf.webs.com/arqs/bullet.gif" style="border:0;margin-right:0.5em;vertical-align:middle;" /&gt;Um &lt;b&gt;Client&lt;/b&gt; é qualquer parte do sistema que solicite uma operação à classe &lt;b&gt;Context&lt;/b&gt;. Esse é o papel da classe &lt;b&gt;TWTelaOperConta&lt;/b&gt; no diagrama anterior.
&lt;/div&gt;
&lt;br /&gt;
O tipo de hierarquia proposta pelo &lt;b&gt;State&lt;/b&gt; é muito semelhante àquela adotada no &lt;a href="http://balaiotecnologico.blogspot.com/2009/07/implementando-design-patterns.html#categorias"&gt;padrão estrutural&lt;/a&gt; &lt;a href="http://balaiotecnologico.blogspot.com/2009/09/design-patterns-com-delphi-adapter.html"&gt;Adapter&lt;/a&gt;. A diferença é que o &lt;b&gt;Adapter&lt;/b&gt; serve para ocultar detalhes de implementação de objetos diferentes que têm a capacidade de executar tarefas similares, adaptando esses objetos a uma interface padronizada. Já o &lt;b&gt;State&lt;/b&gt; simplifica a diferenciação de comportamentos dentro de um mesmo objeto. Ou seja, o primeiro foca no aspecto estrutural e envolve várias classes enquanto o segundo foca o comportamento de um único objeto.&lt;br /&gt;
&lt;br /&gt;
No próximo post, mostro uma sugestão de como implementar em Delphi o exemplo usado aqui.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://balaiotecnologico.blogspot.com/search/label/Design%20Patterns"&gt;Posts sobre Design Patterns&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/State_diagram"&gt;Diagramas de Estado&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-3591165740189726423?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CtQ3msuxSVm-NB4NN8Tl8YwK01M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CtQ3msuxSVm-NB4NN8Tl8YwK01M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CtQ3msuxSVm-NB4NN8Tl8YwK01M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CtQ3msuxSVm-NB4NN8Tl8YwK01M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/zQhbMVc1Nu0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/3591165740189726423/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/06/design-patterns-com-delphi-state-parte.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/3591165740189726423?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/3591165740189726423?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/zQhbMVc1Nu0/design-patterns-com-delphi-state-parte.html" title="Design Patterns com Delphi: State - Parte I" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/06/design-patterns-com-delphi-state-parte.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QDRngyfyp7ImA9WhRVEU8.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-4919989781193880913</id><published>2011-06-16T18:08:00.001-03:00</published><updated>2012-01-09T14:09:37.697-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-09T14:09:37.697-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><title>Representando dados binários como texto em Delphi</title><content type="html">Estou desenvolvendo para a &lt;a href="http://www.abc71.com"&gt;ABC71&lt;/a&gt; um projeto para automatizar o processo de implantação do nosso ERP. Parte do projeto consiste em deixar nossos consultores criar passos num tipo de assistente, aproveitando o conhecimento de campo deles para montar cenários de implantação. Ao criar um passo, eles podem até mesmo carregar uma imagem para representá-lo. Tudo isso é salvo como um arquivo XML, o que traz um problema : imagens são arquivos binários e um XML contem apenas texto.&lt;br /&gt;
&lt;br /&gt;
Mesmo que eu usasse uma &lt;a href="http://www.w3schools.com/xml/xml_cdata.asp"&gt;seção CDATA&lt;/a&gt;, teria que aplicar alguma transformação no conteúdo binário para que ele pudesse ser lido corretamente - certos bytes representam caracteres especiais que não podem ser exibidos, tais como o 27 (&lt;i&gt;escape&lt;/i&gt;) e o 0 (zero sinaliza fim de uma &lt;i&gt;string&lt;/i&gt; em C/C++).&lt;br /&gt;
&lt;br /&gt;
Uma forma de converter o conteúdo binário num texto legível seria tomar cada byte e usar a representação hexadecimal dele. Por exemplo, ao invés do byte com valor 27, eu teria um texto com valor &lt;b&gt;1B&lt;/b&gt;. Um inconveniente salta aos olhos : como cada byte é representado por 2 caracteres, o conteúdo binário dobra de tamanho no processo de conversão !&lt;br /&gt;
&lt;br /&gt;
A melhor solução que encontrei para esse problema é usar a codificação chamada &lt;b&gt;Base64&lt;/b&gt;. Nesse algoritmo, uma sequência de bytes é processada para gerar um texto contendo apenas caracteres que podem ser exibidos, selecionados em uma lista fixa com 64 caracteres possíveis - daí o nome de &lt;b&gt;Base64&lt;/b&gt;. Não sei se a VCL inclui uma implementação desse algoritmo; a versão que usei está disponível para download no site &lt;a href="http://www.koders.com/delphi/fidE7154E13CF5685897559967F6F9BD0483330D256.aspx"&gt;Koders.com&lt;/a&gt;. O texto resultante dessa conversão ainda é maior do que o conteúdo original mas ao menos não dobra de tamanho.&lt;br /&gt;
&lt;br /&gt;
Trabalhar com a &lt;b&gt;Base64&lt;/b&gt; é relativamente simples. Há somente duas funções no fonte indicado: uma para codificar a informação binária (&lt;b&gt;B64Encode&lt;/b&gt;) e outra para obter de volta a informação originalmente codificada (&lt;b&gt;B64Decode&lt;/b&gt;). Como exemplo, o trecho de código abaixo carrega uma imagem a partir de um arquivo, codifica o conteúdo encontrado e retorna o resultado do processamento como uma &lt;i&gt;string&lt;/i&gt;. Por ser um texto, esse resultado pode ser facilmente utilizado em outras partes do programa. No meu caso, eu o incluí como valor de uma &lt;i&gt;tag&lt;/i&gt; num XML:
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; lConteudo : String;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;lSsAux : TStringStream;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;lStreamOrg : TFileStream;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Stream auxiliar para recuperar o conteúdo binário do arquivo }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;lSsAux := TStringStream.Create (&lt;span style="color:maroon;"&gt;''&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;lStreamOrg := TFileStream.Create (_ImgFilePath, fmOpenRead);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Copia o conteúdo do arquivo para o stream em memória }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;lSsAux.CopyFrom (lStreamOrg, &lt;span style="color:blue;"&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;lSsAux.Position = &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Prepara o conteúdo binário, codificando-o como um texto }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;lConteudo := lSsAux.DataString;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;lConteudo := B64Encode(lConteudo);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;lStreamOrg.Free();&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;lSsAux.Free();&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;Result := lConteudo;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
&lt;br /&gt;
Para obter o arquivo original de volta, basta decodificar o texto preparado pelo código anterior. O exemplo que segue traz um função que recebe esse texto, decodifica-o e grava o resultado num novo arquivo com o conteúdo original intocado:
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; TWAssitente.DecodeContentToFile (AConteudo: String);&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; lStreamDst : TFileStream;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;Buffer : PChar;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Cria o novo arquivo vazio }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;lStreamDst := TFileStream.Create (_ImgFilePath, fmCreate);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Decodifica o conteúdo }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;AConteudo := B64Decode (AConteudo);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Grava o conteúdo decodificado no arquivo }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;Buffer := PChar (AConteudo);&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;lStreamDst.Write (Buffer^, Length(AConteudo));&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;lStreamDst.Free ();&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
&lt;br /&gt;
Como é possível deduzir da discussão até aqui, a &lt;b&gt;Base64&lt;/b&gt; pode ser usada para preparar qualquer conteúdo binário e não só imagens. Isto inclui tanto arquivos (documentos, planilhas, executáveis, músicas, etc.) quanto dados contidos em &lt;i&gt;arrays&lt;/i&gt; e &lt;i&gt;streams&lt;/i&gt; na memória de seu programa. Até mesmo o resultado de assinaturas digitais podem passar por esse processo, como mostra o &lt;i&gt;post&lt;/i&gt; sobre a &lt;a href="http://balaiotecnologico.blogspot.com/2009/05/incluindo-assinatura-digital-no-xml.html"&gt;assinatura do XML de uma nota fiscal eletrônica&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Os cálculos do algoritmo da &lt;b&gt;Base64&lt;/b&gt; não são complexos. Caso queira analisá-lo (ou simplesmente utilizá-lo), o fonte completo pode ser acessado &lt;a href="http://www.koders.com/delphi/fidE7154E13CF5685897559967F6F9BD0483330D256.aspx"&gt;através desse link&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://www.koders.com/delphi/fidE7154E13CF5685897559967F6F9BD0483330D256.aspx"&gt;Fonte Base64.pas para Delphi/C++ Builder no Koders.com&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Base64"&gt;Base64 no Wikipedia&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-4919989781193880913?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/7OZnthpn_P2-CQHHbX75FAlZBZ4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7OZnthpn_P2-CQHHbX75FAlZBZ4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/7OZnthpn_P2-CQHHbX75FAlZBZ4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7OZnthpn_P2-CQHHbX75FAlZBZ4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/SpXe8cDxZXc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/4919989781193880913/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/06/trabalhando-com-base64-em-delphi.html#comment-form" title="12 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4919989781193880913?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4919989781193880913?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/SpXe8cDxZXc/trabalhando-com-base64-em-delphi.html" title="Representando dados binários como texto em Delphi" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>12</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/06/trabalhando-com-base64-em-delphi.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8MQn06eyp7ImA9WhZUFk4.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-7389728894874763623</id><published>2011-06-09T13:28:00.000-03:00</published><updated>2011-06-09T13:28:03.313-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-09T13:28:03.313-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Notícias" /><title>Há futuro para projetos em Delphi ?</title><content type="html">Algumas pessoas me enviaram email perguntando o que penso sobre o futuro do Delphi. A preocupação básica é a de que a linguagem vem perdendo terreno, enquanto cada vez mais projetos são levados a cabo com .NET, Java e principalmente com linguagens com forte apelo Web (PHP, Perl, Javascript), &lt;a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;conforme atesta a lista mantida pela TIOBE Software&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Acho  que essa é uma preocupação infundada. Em primeiro lugar, o &lt;a href="http://pt.wikipedia.org/wiki/Ambiente_de_Desenvolvimento_Integrado"&gt;IDE&lt;/a&gt; do Delphi vem ganhando novas versões de forma consistente, às quais têm sido incorporados novos recursos, sempre em sintonia com a evolução do mercado. Isso dá bastante tranquilidade de que a ferramenta não foi abandonada e que adotá-la (ou continuar com ela) não implicará em restrições ao uso de novas tecnologias.&lt;br /&gt;
&lt;br /&gt;
Um outro ponto é a quantidade de acessos a este blog quando o tema está relacionado ao Delphi. Ainda, pelos emails que recebo a partir do blog com comentários e dúvidas, vejo que a linguagem tem uma comunidade bastante grande e ativa aqui no Brasil. Mesmo em &lt;i&gt;sites&lt;/i&gt; fora do país eu encontro vasto material quando preciso pesquisar alguma coisa. Então, acredito que o uso do Delphi ainda continuará firme e forte.&lt;br /&gt; 
&lt;br /&gt;
Por fim, a &lt;a href="http://www.embarcadero.com/"&gt;Embarcadero&lt;/a&gt; havia comunicado em maio que haveriam mudanças nas parcerias deles por aqui. A promessa era ampliar os serviços através da homologação de novos parceiros. No entanto, notícia publicada hoje pela &lt;b&gt;ComputerWorld&lt;/b&gt; informa que eles darão um passo ainda maior : &lt;a href="http://computerworld.uol.com.br/negocios/2011/06/08/embarcadeiro-passa-a-atuar-no-brasil-com-escritorio-proprio/"&gt;abrirão escritório próprio no Brasil&lt;/a&gt;, mostrando claramente que pretendem dar continuidade no suporte à ferramenta.&lt;br /&gt;
&lt;br /&gt;
Abaixo, reproduzo essa notícia:&lt;br /&gt;
&lt;div style="background-color:rgb(235,235,245);border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
A empresa norte-americana Embarcadero, dona da ferramenta de desenvolvimento Delphi, está desembarcando no Brasil e passará a operar com time local. Inicialmente, a companhia terá um escritório próprio, mas já faz parte de seus planos a abertura de uma subsidiária.&lt;br /&gt;
&lt;br /&gt;
Até agora, as ferramentas Delphi e de desenvolvimento para banco de dados da companhia eram vendidos no Brasil pelo canal de distribuição da Micro Focus, que adquiriu a Borland há dois anos, dona desses produtos.&lt;br /&gt;
&lt;br /&gt;
Embora a Embarcadero tivesse comprado essa linha da Borland em 2008, a empresa não estava presente no País nem em outros mercados da América Latina com operação direta.&lt;br /&gt;
&lt;br /&gt;
Com a abertura de um escritório próprio no Brasil, a Embarcadero promete se aproximar mais de seus clientes e incrementar os negócios no País. Ao anunciar a inauguração da unidade local, o vice-presidente de vendas da empresa para a região das Américas, Allen Lovett, destacou que o mercado brasileiro foi considerado importante pela matriz pela sua economia crescente e por ser o maior da América Latina.&lt;br /&gt;
&lt;br /&gt;
“Temos uma base grande de desenvolvedores Delphi no Brasil e enxergamos muitas oportunidades aqui para crescermos”, diz Lovett. A operação local será comandada pelo executivo José Eugênio Braga, que foi diretor comercial e de marketing da Borland.&lt;br /&gt;
&lt;br /&gt;
Eugênio Braga será presidente da Embarcadero no Brasil e contará com apoio de um time de aproximadamente 15 pessoas, todas vindas da Borland e que já conheciam os produtos da marca.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Mais próxima dos desenvolvedores&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
De acordo com o presidente da Embarcadero no brasil, o País conta com uma comunidade de aproximadamente 100 mil desenvolvedores Delphi e já vendeu mais de 300 mil licenças da ferramenta. Entretanto, ele admite que houve uma queda na comercialização dos produtos da marca para sua base antiga. Mas ele garante que a empresa não perdeu mercado, pois 60% dos contratos são fechados com novos usuário.&lt;br /&gt;
&lt;br /&gt;
Lovett complementa que a decisão da Embarcadero de ter uma operação local é para tentar fidelizar sua base, oferecendo serviço, suporte e treinamento em português. Faz parte dos planos também aumentar o número de desenvolvedores em Delphi que estão saindo da universidade.&lt;br /&gt;
&lt;br /&gt;
Eugênio Braga lembra que na época da Borland havia um programa estruturado com universidades brasileiras para para treinar jovens em Delphi. Cerca de 300 universidades participavam da iniciativa. “Vamos investir no Brasil, oferecer treinamento, fazer campanhas e certificar nossos parceiros de negócios”, promete Lovett.&lt;br /&gt;
&lt;br /&gt;
A empresa também promete trazer para o Brasil uma terceira linha de produtos, que será lançada mundialmente no terceiro trimestre, com soluções para controlar licenças de software nas grandes companhias.&lt;br /&gt;
&lt;br /&gt;
Com a operação local, Lovetti espera aumentar a participação do mercado brasileiro na receita global da companhia, que hoje é de 10% e a meta é chegar em 2012 com uma contribuição de 15%. O valor do faturamento mundial da empresa não foi revelado.
&lt;/div&gt;
&lt;br /&gt;
Aqui na &lt;a href="http://www.abc71.com.br"&gt;ABC71&lt;/a&gt; usamos como linguagem principal o C++ Builder, ferramenta gêmea do Delphi em que a programação é feita em C++. Por conta de tudo que foi exposto aqui, não temos qualquer plano de trocar de ambiente num futuro próximo - até porque, nosso ERP tem mais de 5000 telas, processos e relatórios construídos com essa ferramenta.&lt;br /&gt;
&lt;br /&gt;
A única coisa que me preocupa realmente é o fato de que os compiladores do Delphi e do C++ Builder ainda não gerarem código nativo para 64 bits. É um recurso que prometem a bastante tempo mas sobre o qual não tenho visto mais notícias. &lt;a href="http://balaiotecnologico.blogspot.com/2009/04/aplicacoes-delphi-e-c-builder-64-bits.html"&gt;Veja aqui&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;

&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://computerworld.uol.com.br/negocios/2011/06/08/embarcadeiro-passa-a-atuar-no-brasil-com-escritorio-proprio/"&gt;Embarcadero passa a atuar no Brasil com escritório próprio&lt;/a&gt;, &lt;a href="http://www.embarcadero.com/"&gt;site oficial da Embarcadero&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-7389728894874763623?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/B51j_HxFQcPH9rwXpsmBbR6URho/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/B51j_HxFQcPH9rwXpsmBbR6URho/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/B51j_HxFQcPH9rwXpsmBbR6URho/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/B51j_HxFQcPH9rwXpsmBbR6URho/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/DVm_qJGNeQQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/7389728894874763623/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/06/ha-futuro-para-projetos-em-delphi.html#comment-form" title="4 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/7389728894874763623?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/7389728894874763623?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/DVm_qJGNeQQ/ha-futuro-para-projetos-em-delphi.html" title="Há futuro para projetos em Delphi ?" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/06/ha-futuro-para-projetos-em-delphi.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQCQ349eyp7ImA9WhZUEEg.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-2131017940847194299</id><published>2011-06-02T18:32:00.000-03:00</published><updated>2011-06-02T18:32:42.063-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-02T18:32:42.063-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Notícias" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows" /><title>Microsoft mostra recursos da próxima versão do Windows</title><content type="html">Nem bem acabou de lançar o Windows 7, a Microsoft já estava planejando a nova versão. A empresa havia feito antes algumas revelações sobre como seria o Windows 8 mas em primeiro de junho chegaram a mostrar coisas mais concretas a esse respeito. Ao que parece, a proposta é aproximar o Windows Phone daquele voltado para desktops, de modo que a interação com o usuário seria idêntica em um e outro.&lt;br /&gt;
&lt;br /&gt;
A aproximação ainda teria como objetivo preparar uma versão otimizada para &lt;i&gt;tablets&lt;/i&gt;, disponibilizando a mesma usabilidade nas três plataformas. Apesar da pressa pra não perder o bonde, essa versão específica para &lt;i&gt;tablets&lt;/i&gt; deverá ser entregue, na melhor das hipóteses, no começo de 2012. Mas, segundo o &lt;b&gt;Citigroup&lt;/b&gt;, a &lt;a href="http://www1.folha.uol.com.br/tec/921768-microsoft-nao-esta-atrasada-para-festa-dos-tablets-diz-citi.shtml"&gt;Microsoft não está atrasada para a festa dos tablets&lt;/a&gt; pois há uma base muito grande de programas feitos para seu sistema operacional. Como ela está trabalhando para garantir que esses programas rodem também nos &lt;i&gt;tablets&lt;/i&gt;, muitos dos que os usuários já estão acostumados a utilizar em seus &lt;i&gt;pc&lt;/i&gt;s estarão automaticamente disponíveis nos dispositivos com o novo Windows.&lt;br /&gt;
&lt;br /&gt;
Mesmo que seja um sistema operacional muito bem resolvido e abarrotado de recursos interesses - como parece ser o Windows Phone 7 - , somente o tempo dirá se eles estão ou não atrasados. Se demorarem muito, os usuários que hoje são fiéis a programas Windows já podem ter encontrado substitutos a altura nos sistemas de seus &lt;i&gt;tablets&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
O texto que vai abaixo é uma reprodução da matéria publicada pelo &lt;b&gt;IDG Now!&lt;/b&gt; a respeito da apresentação dos recursos previstos para o Windows 8. A reportagem original pode se acessada &lt;a href="http://idgnow.uol.com.br/computacao_pessoal/2011/06/01/microsoft-apresenta-o-windows-8/"&gt;aqui&lt;/a&gt;.
&lt;br /&gt;
&lt;div style="background-color:rgb(235,235,245);border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;O Windows 8 está a caminho, e será bem diferente do Windows que conhecemos hoje. Esta foi a mensagem que a Microsoft passou na noite desta quarta-feira (01/06) durante a conferência anual D: All Things Digital, fealizada próxima a Los Angeles, EUA.&lt;br /&gt;
&lt;br /&gt;
Na conferência a Microsoft apresentou uma versão preliminar do Windows 8, com uma interface radicalmente modificada. Em vez do tradicional desktop com janelas, barra de tarefas e Menu Iniciar, a interface se parece muito com a usada no Windows Phone 7, completa com "Tiles" otimizadas para uso com o toque.&lt;br /&gt;
&lt;br /&gt;
A Microsoft também postou um vídeo que mostra alguns dos novos recursos. A empresa diz que a interface foi projetada não apenas para laptops e desktops, mas para tablets também. A nova interface com Tiles, "quadrados" coloridos que exibem informações e servem de atalho para aplicativos, substitui o tradicional menu iniciar e os ícones no desktop, de acordo com a empresa.&lt;br /&gt;

&lt;p align="center"&gt;&lt;object height="300" width="450"&gt;&lt;param name="movie" value="http://www.youtube.com/v/p92QfWOw88I?version=3" /&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowScriptAccess" value="always" /&gt;&lt;embed width="450" height="300" id="kwiclick-temp-0" src="http://www.youtube.com/v/p92QfWOw88I?version=3" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

O Windows 8 irá rodar aplicativos Windows já existentes e terá suporte aos periféricos já existentes. No vídeo a Microsoft mostra aplicativos tradicionais, como o Office, rodando em uma interface desktop similar à do Windows 7, e é possível trocar entre a nova interface e o modo desktop ao toque de um botão.&lt;br /&gt;
&lt;br /&gt;
O sistema também terá uma versão do navegador Internet Explorer 10 otimizada para toque, muito similar à versão do Internet Explorer utilizada no Windows Phone 7. Para facilitar o uso do sistema em Tablets a Microsoft também incluiu um teclado virtual completo, com um modo "separado" que agrupa as teclas nas laterais da tela para facilitar a digitação com os dedões.&lt;br /&gt;
&lt;br /&gt;
Aplicativos desenvolvidos especialmente para o Windows 8 também serão diferentes, e usarão "o poder do HTML5, acessando recursos nativos do Windows através de JavaScript e HTML", diz a empresa. Ainda não está claro se isso significa que aplicativos para o Windows 8 serão exclusivamente baseados em  HTML5, JavaScript e outras tecnologias originadas na web ou se haverá a possibilidade de usar ferramentas de desenvolvimento mais tradicionais já oferecidas pela Microsoft e outras empresas.&lt;br /&gt;
&lt;br /&gt;
O que é interessante no Windows 8 é que ele é outro passo rumo à transformação dos computadores pessoais em aparelhos mais parecidos com tablets. A Apple também está deixando o Mac OS X mais similar ao iPad ao incorporar vários recursos do iOS ao Mac OS X 10.7 "Lion", embora o Windows pareça ir um passo adiante na fusão entre os tablets e os PCs.&lt;br /&gt;
&lt;br /&gt;
A própria Microsoft confirma o escopo das mudanças, dizendo que o Windows 8 é "uma recriação do Windows, do processador à interface. Um PC com o Windows 8 é na verdade uma nova categoria de aparelho, que pode ir de telas pequenas sensíveis ao toque até os grandes monitores de um desktop, com ou sem um teclado e mouse".&lt;br /&gt;
&lt;br /&gt;
Provavelmente haverá resistência a estas mudanças e teremos que esperar para ver como tudo funciona na prática. Mas o rumo está traçado.
&lt;/div&gt;

&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
&lt;a href="http://idgnow.uol.com.br/computacao_pessoal/2011/06/01/microsoft-apresenta-o-windows-8/"&gt;Windows 8 lembra o Windows Phone 7, no desktop&lt;/a&gt;, &lt;a href="http://www1.folha.uol.com.br/tec/921768-microsoft-nao-esta-atrasada-para-festa-dos-tablets-diz-citi.shtml"&gt;Microsoft não está atrasada para a festa dos tablets&lt;/a&gt; 
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-2131017940847194299?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/9mZnBw42umnCgru16oeLg7Lg9xU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9mZnBw42umnCgru16oeLg7Lg9xU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/9mZnBw42umnCgru16oeLg7Lg9xU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9mZnBw42umnCgru16oeLg7Lg9xU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/I8ViFHDVioY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/2131017940847194299/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/06/microsoft-mostra-recursos-da-proxima.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/2131017940847194299?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/2131017940847194299?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/I8ViFHDVioY/microsoft-mostra-recursos-da-proxima.html" title="Microsoft mostra recursos da próxima versão do Windows" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/06/microsoft-mostra-recursos-da-proxima.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08GR3g4fyp7ImA9WhZVFE4.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-7453760034205541512</id><published>2011-05-26T14:43:00.001-03:00</published><updated>2011-05-26T14:43:46.637-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-26T14:43:46.637-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Conceitos" /><title>Desmistificando o uso de ponteiros</title><content type="html">Uma das grandes vantagens de construir programas em linguagens como C e C++ é que elas são muito próximas do funcionamento de baixo nível dos computadores, o que costuma deixar a performance desses programas superior àquela conseguida com outras linguagens. Essa característica provavelmente explica a posição delas no &lt;a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;ranking de linguagens mais usadas&lt;/a&gt;: respectivamente a 2a e 3a (em maio/2011).&lt;br /&gt;
&lt;br /&gt;
A força das duas linguagens, no entanto, é também seu calcanhar de Aquiles. Muitos programadores temem C/C++ justamente por causa dessa proximidade com a linguagem de máquina, personificada no uso de um recurso-símbolo : os ponteiros. Alguns fatores contribuem para esse temor mas acredito que o principal é a falta de conhecimento sobre a sua real utilidade e funcionamento.&lt;br /&gt;
&lt;br /&gt;
Então, pra começar, o que são exatamente os "ponteiros" e pra que servem ? Um ponteiro é uma variável cujo conteúdo é um endereço na memória do computador. Em outras palavras, é uma posição de memória que "aponta" para outra posição de memória. Com um diagrama fica mais fácil visualizar o conceito:&lt;br /&gt;
&lt;div style="font-family: Courier New; font-size: 9pt; width: 96%;"&gt;&lt;a href="http://lgaf.webs.com/arqs/ponteiro.gif" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="Ponteiro" border="0" id="ponteiro20110525" src="http://lgaf.webs.com/arqs/ponteiro.gif" style="cursor: pointer; display: block; margin: 0px auto 10px; text-align: center; width: 100%;" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
No quadro acima, &lt;b&gt;nome&lt;/b&gt; é uma variável do tipo "ponteiro para char". Isto é, o conteúdo dela indica um local na memória do computador que será usado para armazenar caracteres. O que está acontecendo no programa retratado é uma alocação dinâmica de memória, onde o sistema operacional faz para nós a reserva de uma posição da memória e coloca o endereço reservado na nossa variável. Podemos, então, usar esse ponteiro para acessar o conteúdo da memória reservada.&lt;br /&gt;
&lt;br /&gt;
Os ponteiros, portanto, flexibilizam o desenho de uma aplicação, permitindo a ela alocar memória dinamicamente para tratar situações nas quais não sabemos de antemão com quantos elementos teremos que lidar. Isso também permite adiar a alocação até que os elementos sejam efetivamente necessários, reduzindo o consumo de memória. Ainda, no caso de classes, a solução para o tratamento de heranças é uma implementação fortemente calcada em ponteiros.&lt;br /&gt;
&lt;br /&gt;Uma outra característica dos ponteiros é que eles facilitam o fluxo das informações dentro do programa; sem eles, passar estruturas grandes como parâmetro exigiria a movimentação de grande quantidade de &lt;i&gt;bytes&lt;/i&gt; enquanto com eles é necessário trafegar apenas os bytes que carregam o endereço de memória (a quantidade exata depende do tipo de arquitetura do sistema mas em Win32 são 4 bytes).&lt;br /&gt;
&lt;br /&gt;
Isso tudo levanta, então, outras questões: quando usar exclusivamente o ponteiro no meu código, quando e como acessar o conteúdo e que sintaxe usar para diferenciar ambos os casos ? &lt;br /&gt;
&lt;br /&gt;
Na figura no início do &lt;i&gt;post&lt;/i&gt; aparece o uso mais comum dos ponteiros, que é manter referência a alguma memória alocada dinamicamente. Obviamente, armazenar o endereço alocado é imprescindível para que possamos acessar o seu conteúdo e também para devolver a memória ao sistema operacional quando não formos mais usá-la.&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;typedef&lt;/b&gt;&lt;/span&gt; struct {&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;bool  Assigned;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;long  Id;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;  char  Nome[&lt;span style="color:blue;"&gt;51&lt;/span&gt;];&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;double Saldo;&lt;/span&gt;&lt;br /&gt;
} TWPessoa;&lt;br /&gt;
&lt;br /&gt;
TWPessoa *lPessoa = &lt;span style="color:navy;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; TWPessoa;&lt;br /&gt;
&lt;span style="color:green;"&gt;/* ... */&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;delete&lt;/b&gt;&lt;/span&gt; lPessoa;&lt;br /&gt;
lPessoa = &lt;b&gt;NULL&lt;/b&gt;;
&lt;/div&gt;
&lt;br /&gt;
O valor &lt;b&gt;NULL&lt;/b&gt; é um ponteiro especial para indicar que uma variável não está apontando para lugar algum, isto é, que a variável não está alocada.&lt;br /&gt;
&lt;br /&gt;
Como regra, se o nome da variável aparece sozinho no código, sem decorações (como pontos, setas ou asteriscos) então estamos trabalhando com a variável ponteiro. Nesta situação, o que temos é o endereço de memória para onde nossa variável aponta. É o que está acontecendo no quadro anterior, onde a memória para a estrutura é alocada e o endereço que o sistema operacional reservou para ela é jogado em nossa variável.&lt;br /&gt;
&lt;br /&gt;
A passagem de um ponteiro por parâmetro é outro uso corriqueiro. Formalmente, isso é conhecido como "passagem por referência", o que significa que apenas o endereço é trafegado. É por essa razão que as alterações feitas ao conteúdo de um parâmetro passado por referência são enxergadas também fora da função: ambos os lados apontam exatamente o mesmo endereço na memória.&lt;br /&gt;
&lt;br /&gt;
Quando há alguma decoração anexada à variável no código, então estamos nos referindo ao conteúdo apontado por essa variável. Em C/C++, há várias sintaxes diferentes para acessar o conteúdo apontado, como mostra o trecho abaixo:&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;&lt;span style="color:green;"&gt;/* As 3 linhas abaixo fazem exatamente a mesma coisa :&lt;br /&gt;
     Vai até a posição de memória "apontada" por lPessoa;&lt;br /&gt;
     No local reservado para a variável Assigned, coloque o valor true.
     */&lt;/span&gt;&lt;br /&gt;
  lPessoa-&gt;Assigned = &lt;span style="color:navy;"&gt;true&lt;/span&gt;;&lt;br /&gt;
  &lt;br /&gt;
  lPessoa[&lt;span style="color:blue;"&gt;0&lt;/span&gt;].Assigned = &lt;span style="color:navy;"&gt;true&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
  (*lPessoa).Assigned = &lt;span style="color:navy;"&gt;true&lt;/span&gt;;
&lt;/div&gt;
&lt;br /&gt;
O C/C++ ainda tem um sintaxe para que você possa recuperar o endereço de uma variável de alocação estática, independentemente se é um tipo atômico (int, double, char, etc.) ou um tipo criado pelo usuário (struct, class). Poder fazer essa recuperação é útil, por exemplo, para evitar trafegar o dado estático. Novamente, aqui você só trafegaria os bytes relativos ao ponteiro:&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;
TWPessoa lPessoaEstatica;&lt;br /&gt;
ResetaPessoa (&amp;lPessoaEstatica);
&lt;/div&gt;
&lt;br /&gt;
Pelo rumo dessa discussão, percebemos que qualquer que seja a linguagem utilizada por você, com certeza ela utiliza ponteiros internamente - mesmo que de forma disfarçada - já que eles são a base para o acesso à memória do computador. Assim, conhecer e utilizar bem esse recurso é um excelente começo para construir bons programas em qualquer linguagem.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="background-color: #ffffdc; border: 1px solid silver; padding: 10px 5px 10px 5px; text-align: justify; width: 96%;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border: 0; vertical-align: middle;" /&gt;&lt;span style="font-weight: bold; margin: 0pt 0pt 8px 5px;"&gt;Mais Informações&lt;/span&gt;
&lt;a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;Ranking de linguagens mais usadas&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Pointer_%28computing%29"&gt;Pointers (Computing)&lt;/a&gt;, &lt;a href="http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/pointertypes_xml.html"&gt;Pointers and Pointer Types in Delphi&lt;/a&gt;

&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-7453760034205541512?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Ycr4Z-KVVwtBBkVD2wnJjkwnTcE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ycr4Z-KVVwtBBkVD2wnJjkwnTcE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Ycr4Z-KVVwtBBkVD2wnJjkwnTcE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ycr4Z-KVVwtBBkVD2wnJjkwnTcE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/EcaVCMM2BEI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/7453760034205541512/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/05/desmistificando-o-uso-de-ponteiros.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/7453760034205541512?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/7453760034205541512?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/EcaVCMM2BEI/desmistificando-o-uso-de-ponteiros.html" title="Desmistificando o uso de ponteiros" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/05/desmistificando-o-uso-de-ponteiros.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAERnkzeSp7ImA9WhZWGE8.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-6742728203459325634</id><published>2011-05-19T14:38:00.000-03:00</published><updated>2011-05-19T14:38:27.781-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-19T14:38:27.781-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Indy" /><title>Enviando emails com Delphi - Parte III</title><content type="html">Vida de programador é difícil... No início de 2010, o Google fez uma alteração no sistema online de email deles, o &lt;b&gt;GMail&lt;/b&gt;, para substituir o método de segurança &lt;b&gt;SSL&lt;/b&gt; então vigente no serviço pela sua versão mais nova, chamada &lt;a href="http://en.wikipedia.org/wiki/Transport_Layer_Security"&gt;TLS&lt;/a&gt;.&lt;br/&gt;
&lt;br/&gt;
Por causa dessa modificação simples, muitos programas que antes conseguiam enviar email tranquilamente através do &lt;b&gt;GMail&lt;/b&gt; falharam. Para piorar, a &lt;a href="http://www.indyproject.org/index.en.aspx"&gt;versão 9 do Indy&lt;/a&gt; não implementa nativamente o tratamento do TLS - isso só aconteceu a partir da versão 10. Ou seja, programas &lt;b&gt;Delphi&lt;/b&gt; ou &lt;b&gt;C++ Builder&lt;/b&gt; construídos com o &lt;b&gt;Indy 9&lt;/b&gt; não tinham uma solução fácil à mão para essa questão.&lt;br/&gt;
&lt;br/&gt;
Na versão 10 do Indy, a solução é extremamente simples : basta configurar a propriedade &lt;b&gt;UseTLS&lt;/b&gt; da instância de &lt;b&gt;IdSMTP&lt;/b&gt; e manter as demais configurações:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;
IdSMTP1.UseTLS := utUseExplicitTLS;
&lt;/div&gt;&lt;br/&gt;
Manter as demais configurações significa que o servidor deve continuar sendo &lt;b&gt;smtp.gmail.com&lt;/b&gt;, a porta &lt;b&gt;587&lt;/b&gt;, com autenticação de usuário e senha. Também é obrigatório atribuir um &lt;i&gt;handler&lt;/i&gt; para tratar a comunicação SSL/TLS. Para mais informações sobre isso e outros aspectos das configurações básicas, veja &lt;a href="http://balaiotecnologico.blogspot.com/2011/04/enviando-emails-com-delphi.html"&gt;este post&lt;/a&gt;.&lt;br/&gt;
&lt;br/&gt;
Embora não seja um processo tão direto, é possível trabalhar com &lt;b&gt;TLS&lt;/b&gt; em Indy 9. Basicamente, é preciso enviar ao servidor de email um comando &lt;a href="http://en.wikipedia.org/wiki/STARTTLS"&gt;STARTTLS&lt;/a&gt; logo após o &lt;b&gt;SMTP&lt;/b&gt; ter se conectado. O trecho abaixo é um código genérico que testa configurações internas para determinar se a conexão é segura. Em caso positivo, um &lt;i&gt;handler&lt;/i&gt; é destacado para fazer o tratamento da conexão. Neste ponto, o SMTP já foi preparado com as configurações básicas necessárias.&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 96%;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (TipoSeguranca = SEGURANCA_SSL) &lt;span style="color:navy;"&gt;&lt;b&gt;Or&lt;/b&gt;&lt;/span&gt; (TipoSeguranca = SEGURANCA_TLS) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br/&gt; 
  &lt;span style="margin-left:1em;"&gt;IdSMTP.IOHandler := IdSSLIOHandlerSocket;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (TipoSeguranca = SEGURANCA_TLS) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;IdSSLIOHandlerSocket.SSLOptions.Method := sslvTLSv1;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;IdSSLIOHandlerSocket.PassThrough := &lt;b&gt;true&lt;/b&gt;;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:green;"&gt;{ Tenta conectar no servidor com 1 minuto de timeout }&lt;/span&gt;&lt;br/&gt;
IdSMTP.Connect (&lt;span style="color:blue;"&gt;60000&lt;/span&gt;);&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:green;"&gt;{ Emula o comportamento do TLS }&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (TipoSeguranca = SEGURANCA_TLS) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;IdSMTP.SendCmd(&lt;span style="color:maroon;"&gt;'STARTTLS'&lt;/span&gt;, &lt;span style="color:;"&gt;220&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;IdSSLIOHandlerSocket.PassThrough := &lt;b&gt;false&lt;/b&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (Autentica &lt;span style="color:navy;"&gt;&lt;b&gt;And&lt;/b&gt;&lt;/span&gt; (&lt;span style="color:navy;"&gt;&lt;b&gt;not&lt;/b&gt;&lt;/span&gt; IdSMTP.Authenticate () ) &lt;span style="color:navy;"&gt;&lt;b&gt;then&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;Raise&lt;/b&gt;&lt;/span&gt; Exception.Create (&lt;span style="color:maroon;"&gt;'Falha na autenticação do usuário'&lt;/span&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;br/&gt;
Ao detectar que a conexão segura exige &lt;b&gt;TLS&lt;/b&gt;, alguns ajustes precisam ser feitos. Primeiro, mudo o método de segurança do &lt;i&gt;handler&lt;/i&gt; para que adote o padrão para &lt;b&gt;TLS&lt;/b&gt;. Depois, instruo o &lt;i&gt;handler&lt;/i&gt; a codificar os comandos trocados entre ele e o servidor. Só então, podemos estabelecer a conexão.&lt;br/&gt;
&lt;br/&gt;
Uma vez que a conexão está estabelecida, enviamos ao servidor o comando &lt;a href="http://en.wikipedia.org/wiki/STARTTLS"&gt;STARTTLS&lt;/a&gt; para ativar a comunicação segura na mesma porta. Por causa disso, o &lt;b&gt;PassThrough&lt;/b&gt; que forçamos antes da conexão já pode ser desligado.&lt;br/&gt;
&lt;br/&gt;
Autenticar manualmente o usuário e a senha é um preciosismo pois o método &lt;b&gt;Send&lt;/b&gt; para envio da mensagem o fará por nós. Aqui no exemplo foi feita a autenticação explícita pra mostrar que é possível interceptar um erro de usuário/senha inválido antes de se tentar enviar a mensagem.&lt;br/&gt;
&lt;br/&gt;
Agora, é só preparar uma instância do &lt;b&gt;idMessage&lt;/b&gt; com os dados da mensagem (destinatários, assunto, corpo da mensagem, etc.) e enviá-la com o SMTP.&lt;br/&gt;
&lt;br/&gt;
As considerações tecidas neste &lt;i&gt;post&lt;/i&gt; também são válidas para quem usa o &lt;b&gt;Hotmail&lt;/b&gt; como serviço para envio de email em suas aplicações. Há apenas duas diferenças importantes : o servidor de email, claro, é outro (&lt;b&gt;smtp.live.com&lt;/b&gt;); também a forma de se especificar o usuário do serviço difere. No &lt;b&gt;GMail&lt;/b&gt;, deve ser usado como nome do usuário somente o texto que vem antes do arroba (&lt;b&gt;@&lt;/b&gt;) do endereço de email, enquanto no &lt;b&gt;Hotmail&lt;/b&gt; o nome do usuário é o endereço completo.&lt;br/&gt;
&lt;br/&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 96%;background-color:rgb(255,255,220);text-align:justify;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border:0;vertical-align:middle;" /&gt;&lt;span style="font-weight:bold;margin:0 0 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;
Enviando emails com Delphi - &lt;a href="http://balaiotecnologico.blogspot.com/2011/04/enviando-emails-com-delphi.html"&gt;Parte I&lt;/a&gt; e &lt;a href="http://balaiotecnologico.blogspot.com/2011/05/enviando-emails-com-delphi-parte-ii.html"&gt;Parte II&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/STARTTLS"&gt;STARTTLS&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-6742728203459325634?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/NPdxj5XZ1NRW-4i7GJacO-DjJqs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NPdxj5XZ1NRW-4i7GJacO-DjJqs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/NPdxj5XZ1NRW-4i7GJacO-DjJqs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NPdxj5XZ1NRW-4i7GJacO-DjJqs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/2G6DAMF6vDI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/6742728203459325634/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/05/enviando-emails-com-delphi-parte-iii.html#comment-form" title="2 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/6742728203459325634?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/6742728203459325634?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/2G6DAMF6vDI/enviando-emails-com-delphi-parte-iii.html" title="Enviando emails com Delphi - Parte III" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/05/enviando-emails-com-delphi-parte-iii.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MESHs_cSp7ImA9WhdaFEo.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-5269714320297785655</id><published>2011-05-09T18:42:00.000-03:00</published><updated>2011-10-24T16:03:29.549-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-24T16:03:29.549-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Indy" /><title>Enviando emails com Delphi - Parte II</title><content type="html">Há alguns dias, escrevi um &lt;i&gt;post&lt;/i&gt; sobre o &lt;a href="http://balaiotecnologico.blogspot.com/2011/04/enviando-emails-com-delphi.html"&gt;envio de emails com Delphi&lt;/a&gt;, mostrando a configuração básica dos componentes &lt;a href="http://www.indyproject.org/index.en.aspx"&gt;Indy&lt;/a&gt; para &lt;a href="http://pt.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol"&gt;SMTP&lt;/a&gt; e também as funções que devem ser chamadas para completar o processo. No exemplo, a mensagem incluída no email era um texto simples, sem qualquer tipo de formatação.&lt;br /&gt;
&lt;br /&gt;
No começo, os programas leitores de email só conseguiam trabalhar com mensagens assim, onde apenas texto era trocado. É um comportamento básico mas que ainda tem sua utilidade, principalmente quando há questões de segurança envolvidas. Com a evolução da internet, entretanto, praticamente todos os leitores de email conseguem exibir mensagens com formatação rica. Usando &lt;a href="http://pt.wikipedia.org/wiki/HTML"&gt;HTML&lt;/a&gt; podemos compor emails com &lt;i&gt;layouts&lt;/i&gt; complexos, usando cores e tipos de fontes diferentes, além da inclusão de imagens, links, tabelas, animações, entre outros. Uma grande vantagem desse formato é que ele já é utilizado para construir os sites da internet. Ou seja, &lt;b&gt;HMTL&lt;/b&gt; é uma ferramenta bastante conhecida e amplamente suportada.&lt;br /&gt;
&lt;br /&gt;
Do ponto de vista do envio de email, o que há de diferente em relação ao que foi apresentado no &lt;a href="http://balaiotecnologico.blogspot.com/2011/04/enviando-emails-com-delphi.html"&gt;outro post&lt;/a&gt; ? Basicamente, apenas dois detalhes. O primeiro é uma propriedade da mensagem que determina o tipo de conteúdo que a mensagem está trafegando. Essa característica é chamada &lt;a href="http://en.wikipedia.org/wiki/MIME"&gt;MIME&lt;/a&gt; (&lt;b&gt;Multipurpose Internet Mail Extensions&lt;/b&gt;, ou Extensões Multipropósito para Correio na Internet). O padrão para essa propriedade no corpo de um email é o valor &lt;span style="color:maroon;"&gt;text/plain&lt;/span&gt;, que significa que a mensagem é composta por um texto simples. Como queremos montá-la como um &lt;b&gt;HTML&lt;/b&gt;, temos que avisá-la disso:
&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;IdMessage1.ContentType := &lt;span style="color:maroon;"&gt;'text/html'&lt;/span&gt;;&lt;br /&gt;
IdMessage1.CharSet := &lt;span style="color:maroon;"&gt;'ISO-8859-1'&lt;/span&gt;;
&lt;/div&gt;
&lt;br /&gt;
Veja que eu também modifiquei o &lt;b&gt;charset&lt;/b&gt; da mensagem. Esta propriedade indica qual é o conjunto de caracteres que a mensagem está usando. Como o português usa acentuação, é preferível trocar o padrão americano pelo conjunto latino (&lt;span style="color:maroon;"&gt;'ISO-8859-1'&lt;/span&gt;).&lt;br /&gt;
&lt;br /&gt;
O outro detalhe é que o corpo da mensagem agora tem que respeitar o &lt;b&gt;MIME&lt;/b&gt; configurado. Quero dizer com isso que teremos que montar um &lt;b&gt;HTML&lt;/b&gt; para a mensagem:&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;
IdMessage1.Body.Text := &lt;span style="color:maroon;"&gt;'&amp;lt;html&gt;&amp;lt;head&gt;'&lt;/span&gt; +&lt;br /&gt; 
   &lt;span style="color:maroon;margin-left:2em;"&gt;'&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"&gt;'&lt;/span&gt; + &lt;br /&gt;
   &lt;span style="color:maroon;margin-left:2em;"&gt;'&amp;lt;/head&gt;&amp;lt;body&gt;'&lt;/span&gt; + &lt;br /&gt;
   &lt;span style="color:maroon;margin-left:2em;"&gt;'&amp;lt;p&gt;Essa mensagem é um &amp;lt;b&gt;Teste&amp;lt;/b&gt; de email HTML.&amp;lt;/p&gt;'&lt;/span&gt; + &lt;br /&gt;
   &lt;span style="color:maroon;margin-left:2em;"&gt;'&amp;lt;/body&gt;&amp;lt;/html&gt;'&lt;/span&gt;;
&lt;/div&gt;&lt;br /&gt;
Embora pareça redundante, é importante informar de novo no cabeçalho do HTML quem é o MIME e o charset. Os leitores de email utilizam as informações desse cabeçalho para renderizar a mensagem recebida via &lt;b&gt;SMTP&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
E se quisermos incluir uma imagem em nosso &lt;b&gt;HTML&lt;/b&gt; ? Algumas pessoas publicam a imagem na internet e referenciam o link dela no HTML da mensagem. Mas essa solução exige que o destinatário esteja conectado para poder buscar a imagem, coisa que nem sempre é verdade. Numa empresa, por exemplo, as mensagens são recebidas de forma centralizada por um servidor de email, dispensando a necessidade de ter internet local. Muitas delas adotam ainda restrições ao acesso à internet.&lt;br /&gt;
&lt;br /&gt;
Uma maneira melhor de se fazer isso é enviar a imagem junto com o HTML. Ao invés de preencher o campo &lt;b&gt;Body&lt;/b&gt; da mensagem, teremos que decompô-la em seus constituintes básicos para podermos identificar de forma separada o &lt;b&gt;MIME&lt;/b&gt; de cada um. Isto é, o corpo da mensagem é um HTML enquanto a imagem é um arquivo binário com MIME próprio. O conjunto todo terá um &lt;b&gt;MIME&lt;/b&gt; especial (&lt;span style="color:maroon;"&gt;multipart/mixed&lt;/span&gt;) que sinaliza que a mensagem está montada como múltiplas partes independentes.&lt;br /&gt;
&lt;br /&gt;
Cada parte deverá ser anexada à mensagem através da propriedade &lt;i&gt;MessageParts&lt;/i&gt;. Para o corpo, usamos o tipo &lt;b&gt;TIdText&lt;/b&gt;. Para a imagem, o tipo tradicional para anexos (&lt;b&gt;TIdAttachmentFile&lt;/b&gt;).&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:2em;"&gt;text : TIdText;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:2em;"&gt;at : TIdAttachmentFile&lt;/span&gt;;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;IdMessage1.MessageParts.Clear();&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;IdMessage1.ContentType := &lt;span style="color:maroon;"&gt;'multipart/mixed'&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;text := TIdText.Create (IdMessage1-&gt;MessageParts, &lt;span style="color:navy;"&gt;&lt;b&gt;Nil&lt;/b&gt;&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;text.ContentType := &lt;span style="color:maroon;"&gt;'text/html'&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;text.CharSet := &lt;span style="color:maroon;"&gt;'ISO-8859-1'&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;text.Body.Text := PreparaHTML();&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;at := TIdAttachmentFile.Create (IdMessage1-&gt;MessageParts,&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:4em;"&gt;&lt;span style="color:maroon;"&gt;'C:\\Inetpub\\wwwroot\\winxp.gif'&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;at.ContentType := &lt;span style="color:maroon;"&gt;'image/gif'&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;at.FileName := &lt;span style="color:maroon;"&gt;'winxp.gif'&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;IdSMTP1.Connect();&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;IdSMTP1.Send(IdMessage1);&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ ... }&lt;/span&gt;
&lt;/div&gt;&lt;br /&gt;
O HTML pode, então, fazer referência diretamente ao nome do arquivo anexado, sem precisar estipular um endereço na internet. A única coisa é que o nome do arquivo deve ser exatamente igual àquele informado na propriedade &lt;i&gt;FileName&lt;/i&gt; do anexo:&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; TForm1.PreparaHTML : String;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;begin&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:1em;"&gt;Result := Result + &lt;span style="color:maroon;"&gt;'&amp;lt;img style="margin:1px 1px 1px 0px;" src="winxp.gif" /&gt;'&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:green;margin-left:1em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;
&lt;/div&gt;
&lt;br /&gt;
Em tese, não há restrição a quantos recursos externos podem ser agregados ao email usando esse tipo de construção. Também não se restringe à inclusão de imagens, podendo ser usado para incorporar animações, scripts, folhas de estilo, etc. - desde que tenham os respectivos &lt;b&gt;MIME&lt;/b&gt;s devidamente configurados.&lt;br /&gt;
&lt;br /&gt;
Estou com a versão 10 do Indy que vem com o Delphi XE mas acredito que os recursos mostrados aqui estejam disponíveis em versões anteriores também.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="background-color: #ffffdc; border: 1px solid silver; padding: 10px 5px 10px 5px; text-align: justify; width: 96%;"&gt;&lt;img src="http://www.blogger.com/img/triangle_ltr.gif" style="border: 0; vertical-align: middle;" /&gt;&lt;span style="font-weight: bold; margin: 0pt 0pt 8px 5px;"&gt;Mais Informações&lt;/span&gt;&lt;br /&gt;&lt;a href="http://balaiotecnologico.blogspot.com/2011/04/enviando-emails-com-delphi.html"&gt;Enviando emails com Delphi&lt;/a&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:96%;padding:5px 5px 5px 5px;background-color:rgb(230,230,250);margin-top:5px;"&gt;
&lt;b&gt;Email:&lt;/b&gt; &lt;a href="mailto:&amp;#x62;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#x65;&amp;#x63;&amp;#110;&amp;#x6f;&amp;#x6c;&amp;#111;&amp;#x67;&amp;#x69;&amp;#x63;&amp;#111;&amp;#64;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#109;?subject=&amp;#67;&amp;#x6f;&amp;#110;&amp;#x74;&amp;#x61;&amp;#116;&amp;#x6f;&amp;#32;&amp;#115;&amp;#111;&amp;#98;&amp;#114;&amp;#x65;&amp;#x20;&amp;#112;&amp;#111;&amp;#x73;&amp;#116;"&gt;balaiotecnologico@gmail.com&lt;/a&gt;
&lt;/div&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2614552592180424653-5269714320297785655?l=balaiotecnologico.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LOfttCdZJ9EA-IAY4yhGGU5aaXE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LOfttCdZJ9EA-IAY4yhGGU5aaXE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LOfttCdZJ9EA-IAY4yhGGU5aaXE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LOfttCdZJ9EA-IAY4yhGGU5aaXE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/NQT93GAmp-E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/5269714320297785655/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2011/05/enviando-emails-com-delphi-parte-ii.html#comment-form" title="4 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/5269714320297785655?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/5269714320297785655?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/NQT93GAmp-E/enviando-emails-com-delphi-parte-ii.html" title="Enviando emails com Delphi - Parte II" /><author><name>Luís Gustavo Fabbro</name><uri>http://www.blogger.com/profile/14255804912190729594</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="21" height="32" src="http://2.bp.blogspot.com/--7_TQkbNKlE/ToXPJJ0GT4I/AAAAAAAAAXI/G_lxHMhTyp4/s220/eu.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/05/enviando-emails-com-delphi-parte-ii.html</feedburner:origLink></entry></feed>

