<?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:blogger="http://schemas.google.com/blogger/2008" 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;D0QBRHk9cCp7ImA9WhBaE00.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653</id><updated>2013-05-23T07:35:55.768-03:00</updated><category term="C#" /><category term="CAPICOM" /><category term="Notícias" /><category term="Script" /><category term="Internet" /><category term="Artigos" /><category term="SQL" /><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>253</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;AkcHQXwzcSp7ImA9WhBVFk4.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-4096136269810460765</id><published>2013-04-22T10:40:00.002-03:00</published><updated>2013-04-22T10:40:30.289-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-22T10:40:30.289-03:00</app:edited><title>Estruturas de Dados com Delphi - parte II : Pilhas</title><content type="html">No meu &lt;a href="http://balaiotecnologico.blogspot.com.br/2013/03/estruturas-de-dados-com-delphi-parte-i.html"&gt;último post&lt;/a&gt;, comecei a falar sobre estruturas de dados e como o Delphi lida com as estruturas mais comuns, como as &lt;a href="http://balaiotecnologico.blogspot.com.br/2013/03/estruturas-de-dados-com-delphi-parte-i.html"&gt;filas&lt;/a&gt;. Neste post, eu mostro o conceito de outra das estruturas padronizadas que o Delphi trata de forma inerente : &lt;a href="http://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29"&gt;pilhas&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
A diferença central entre filas e pilhas está na ordem em que os elementos são retirados da estrutura. No caso das filas, o primeiro elemento inserido será o primeiro a ser retirado, mecanismo conhecido como FIFO (First In, First Out). Para as pilhas, o último elemento inserido é retirado primeiro; isto é, pilhas implementam o LIFO (Last In, First Out). Para compreender esse conceito, imagine que você guarde os pratos de sua casa empilhados no armário. Sempre que você precisa de um prato, retira o que está no topo da pilha. Quando vai guardá-los, os pratos são postos no topo da pilha novamente, disponíveis para o próximo uso.&lt;br /&gt;
&lt;br /&gt;
Uma situação computacional prática onde o uso de pilhas se adequa é o cálculo do custo de um produto fabricado. Por exemplo, para calcular o custo de fabricação de um computador, temos que calcular o custo da CPU, do monitor e do teclado. No entanto, obter o custo da CPU requer que se calcule antes o custo da placa-mãe, transistores, capacitores, etc. A placa-mãe também é composta por outros itens, e assim sucessivamente.&lt;br /&gt;
&lt;br /&gt;
Nessa estrutura, podemos somar o custo individual de cada componente até encontrar um que também seja composto. O item composto é incluído no topo da pilha enquanto se calcula seu custo. Tal processo deve ser feito recursivamente até que haja apenas itens simples. Nesse momento, o custo do último item adicionado à pilha está determinado e ele pode ser removido da pilha, prosseguindo o cálculo com o item seguinte.&lt;br /&gt;
&lt;br /&gt;
Para implementarmos com as classes nativas do Delphi uma solução para essa situação, considere as classes abaixo:
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 5px 5px;width: 98%;"&gt;
  TWProduto = &lt;span style="font-weight:bold;color:navy;"&gt;class&lt;/span&gt;&lt;br /&gt;
  &lt;span style="font-weight:bold;color:navy;"&gt;public&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;Codigo: String;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;Custo : Double;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;Componentes: TList&lt;TWProduto&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;Constructor&lt;/span&gt; Create(ACodigo:String;ACusto: Double);&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;Destructor&lt;/span&gt; Destroy;&lt;span style="font-weight:bold;color:navy;"&gt;override&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="font-weight:bold;color:navy;"&gt;End&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
  TWContexto=&lt;span style="font-weight:bold;color:navy;"&gt;class&lt;/span&gt;&lt;br /&gt;
  &lt;span style="font-weight:bold;color:navy;"&gt;public&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;produto: TWProduto;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;indice : integer;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;custo  : double;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;Constructor&lt;/span&gt; Create(AProduto: TWProduto);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="font-weight:bold;color:navy;"&gt;end&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;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;Constructor&lt;/span&gt; TWProduto.Create(ACodigo:String;ACusto: Double);&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;begin&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Codigo := ACodigo;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Custo  := ACusto;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Componentes:= TList&lt;TWProduto&gt;.Create;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;end&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;Destructor&lt;/span&gt; TWProduto.Destroy;&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;begin&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;Componentes.Free;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;inherited&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;end&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;Constructor&lt;/span&gt; TWContexto.Create(AProduto: TWProduto);&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;begin&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;produto := AProduto;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;indice := &lt;span style="color:blue;"&gt;0&lt;/span&gt;;   &lt;span style="color:green;"&gt;{ iniciar cálculo nesse índice }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;custo  := &lt;span style="color:blue;"&gt;0.0&lt;/span&gt;; &lt;span style="color:green;"&gt;{ custo inicial do produto }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
A primeira classe (&lt;b&gt;TWProduto&lt;/b&gt;) representa um produto que pode ser composto de outros produtos, incluindo outros produtos compostos. Já a classe &lt;b&gt;TWContexto&lt;/b&gt; serve para controlar o cálculo do custo de um único produto composto. Além do próprio produto, ela armazena o índice do último componente considerado pelos cálculos bem como o custo obtido até o momento.&lt;br /&gt;
&lt;br /&gt;
No quadro a seguir, eu simulo manualmente a montagem simplificada de um computador. O resultado é um exemplo de estruturação complexa usando a classe de produto descrita acima e cujo custo poderá ser calculado com uma rotina usando pilha:
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 5px 5px;width: 98%;"&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;function&lt;/span&gt; TForm1.MontaComputador : TWProduto;&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;var&lt;/span&gt; computador, compon, subcompon: TWProduto;&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;begin&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;computador := TWProduto.Create(&lt;span style="color:maroon;"&gt;'Computador'&lt;/span&gt;, &lt;span style="color:blue;"&gt;0.0&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;compon := TWProduto.Create(&lt;span style="color:maroon;"&gt;'Teclado'&lt;/span&gt;, &lt;span style="color:blue;"&gt;20.0&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;computador.Componentes.Add(compon);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;compon := TWProduto.Create(&lt;span style="color:maroon;"&gt;'Monitor'&lt;/span&gt;, &lt;span style="color:blue;"&gt;235.0&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;computador.Componentes.Add(compon);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ A CPU é um produto composto }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;compon := TWProduto.Create(&lt;span style="color:maroon;"&gt;'CPU'&lt;/span&gt;, &lt;span style="color:blue;"&gt;0.0&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;subcompon := TWProduto.Create(&lt;span style="color:maroon;"&gt;'Placa-mãe'&lt;/span&gt;, &lt;span style="color:blue;"&gt;250.0&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;compon.Componentes.Add(subcompon);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;subcompon := TWProduto.Create(&lt;span style="color:maroon;"&gt;'Cooler'&lt;/span&gt;, &lt;span style="color:blue;"&gt;32.0&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;compon.Componentes.Add(subcompon);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;computador.Componentes.Add(compon);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Result := Computador;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
A rotina abaixo usa pilha para controlar o cálculo do custo de um produto - no caso, o computador estruturado no quadro anterior. Em Delphi, a classe &lt;a href="http://docwiki.embarcadero.com/Libraries/XE2/en/System.Generics.Collections.TStack"&gt;TStack&lt;/a&gt; implementa as operações necessárias para se trabalhar com uma pilha.
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 5px 5px;width: 98%;"&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;procedure&lt;/span&gt; TForm1.btnCalcularCustoClick(Sender: TObject);&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;var&lt;/span&gt; i : integer;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;interromper : boolean;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;Pilha: TStack&lt;TWContexto&gt;;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;contexto, ctxAux : TWContexto;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;computador : TWProduto;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;begin&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;computador := MontaComputador;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;contexto := TWContexto.Create (computador);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Inicia a pilha com o produto original no contexto : o computador }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Pilha:= TStack&lt;TWContexto&gt;.Create;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Pilha.Push(contexto);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;while&lt;/span&gt; (pilha.Count &gt; &lt;span style="color:blue;"&gt;0&lt;/span&gt;) &lt;span style="font-weight:bold;color:navy;"&gt;do begin&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:green;"&gt;{ Obtém o contexto no topo, sem removê-lo }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;contexto := pilha.Peek;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;compon := contexto.produto;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;i := contexto.indice;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:green;"&gt;{ Percorre os componentes desse produto, somando o custo de cada um para obter o custo do total do produto em si }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;interromper := false;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;while&lt;/span&gt; (i &lt; compon.Componentes.Count) &lt;span style="font-weight:bold;color:navy;"&gt;And&lt;/span&gt; (&lt;span style="font-weight:bold;color:navy;"&gt;not&lt;/span&gt; interromper) &lt;span style="font-weight:bold;color:navy;"&gt;do begin&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;subcompon := compon.Componentes.Items[i];&lt;/span&gt;&lt;br /&gt;
      &lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;&lt;span style="color:green;"&gt;{ Esse produto é composto ? }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;interromper := (subcompon.Componentes.Count &gt; &lt;span style="color:blue;"&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;if&lt;/span&gt; (interromper) &lt;span style="font-weight:bold;color:navy;"&gt;then begin&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:4em;"&gt;&lt;span style="color:green;"&gt;{ Inclui o subcomponente composto no topo da pilha pra calcular seu custo }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:4em;"&gt;ctxAux := TWContexto.Create (subcompon);&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:4em;"&gt;Pilha.Push(ctxAux);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
        &lt;span style="margin-left:4em;"&gt;&lt;span style="color:green;"&gt;{ Quando desempilhar esse produto, inicie no componente seguinte }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:4em;"&gt;contexto.indice := i + &lt;span style="color:blue;"&gt;1&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:4em;"&gt;contexto.custo := contexto.custo + subcompon.Custo;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;Inc (i);&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;end&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;{ Conseguiu totalizar o custo do produto; então, remove-o do topo da pilha }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;if not&lt;/span&gt; interromper &lt;span style="font-weight:bold;color:navy;"&gt;then begin&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;Pilha.Pop;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;compon.Custo := contexto.custo;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;contexto.Free;&lt;/span&gt;&lt;br /&gt;
      &lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;&lt;span style="color:green;"&gt;{ Adiciona o custo calculado ao custo do produto do qual esse componente é parte }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;if&lt;/span&gt; pilha.Count &gt; &lt;span style="color:blue;"&gt;0&lt;/span&gt; &lt;span style="font-weight:bold;color:navy;"&gt;then begin&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:4em;"&gt;contexto := pilha.Peek;&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:4em;"&gt;contexto.custo := contexto.custo + compon.Custo;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;end&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;{ Apresenta o custo obtido }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lblCusto.Caption := FormatFloat (&lt;span style="color:maroon;"&gt;'#,##0.00'&lt;/span&gt;, computador.Custo);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Pilha.Free;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;computador.Free;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
Assim como no caso da fila &lt;a href="http://balaiotecnologico.blogspot.com.br/2013/03/estruturas-de-dados-com-delphi-parte-i.html"&gt;tratado no outro post&lt;/a&gt;, o &lt;b&gt;constructor&lt;/b&gt; da pilha exige a especificação do tipo de dado com o qual a pilha será capaz de trabalhar. No exemnplo, a classe &lt;b&gt;TWContexto&lt;/b&gt; é informada para que possamos controlar os produtos que já foram considerados no cálculo do custo.&lt;br /&gt;
&lt;br /&gt;
As funções mais importantes na pilha são a que acrescenta e a que remove um elemento. Para inserir um novo elemento no topo da pilha, use o método &lt;a href="http://docwiki.embarcadero.com/Libraries/XE2/en/System.Generics.Collections.TStack.Push"&gt;Push&lt;/a&gt; e para extraí-lo use &lt;a href="http://docwiki.embarcadero.com/Libraries/XE2/en/System.Generics.Collections.TStack.Pop"&gt;Pop&lt;/a&gt;, como mostrado no código acima.&lt;br /&gt;
&lt;br /&gt;
É possível ainda obter o elemento que está no topo da pilha sem, no entanto, extraí-lo. Para isso, há o método &lt;a href="http://docwiki.embarcadero.com/Libraries/XE2/en/System.Generics.Collections.TStack.Peek"&gt;Peek&lt;/a&gt;, também utilizado no exemplo.&lt;br /&gt;
&lt;br /&gt;
Embora não tenha sido necessário aqui, o &lt;a href="http://docwiki.embarcadero.com/Libraries/XE2/en/System.Generics.Collections.TStack"&gt;TStack&lt;/a&gt; permite interceptar a adição e remoção de elementos através do evento &lt;a href="http://docwiki.embarcadero.com/Libraries/XE2/en/System.Generics.Collections.TStack.OnNotify"&gt;OnNotify&lt;/a&gt;. Ele é frequentemente utilizado para liberar a memória associada aos elementos da pilha.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 98%;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.br/2013/03/estruturas-de-dados-com-delphi-parte-i.html"&gt;Estruturas de Dados com Delphi - parte I : Filas&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Data_structure"&gt;Estruturas de Dados no Wikipedia&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29"&gt;Pilhas&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/e0b21Y7I6ZE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/4096136269810460765/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2013/04/estruturas-de-dados-com-delphi-parte-ii.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4096136269810460765?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4096136269810460765?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/e0b21Y7I6ZE/estruturas-de-dados-com-delphi-parte-ii.html" title="Estruturas de Dados com Delphi - parte II : Pilhas" /><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/2013/04/estruturas-de-dados-com-delphi-parte-ii.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0EMRHc-fyp7ImA9WhBXE00.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-5466436367691869171</id><published>2013-03-26T11:54:00.001-03:00</published><updated>2013-03-26T11:54:45.957-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-26T11:54:45.957-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Conceitos" /><title>Estruturas de Dados com Delphi - parte I : Filas</title><content type="html">Em maior ou menor grau, o trabalho de um programador de computadores envolve lidar com meios de organizar os dados internos de seus programas. Uma organização bem planejada é imprescindível para a implementação de algorítmos eficientes, o que afeta tanto a performance da aplicação quanto sua facilidade de manutenção. As formas de se organizar os dados em um programa são chamadas de &lt;a href="http://en.wikipedia.org/wiki/Data_structure"&gt;Estruturas de Dados&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Pela sua importância, a maioria das linguagens de programação oferecem bibliotecas com implementações genéricas pré fabricadas para as formas tradicionais de organização de dados, tais como &lt;a href="http://en.wikipedia.org/wiki/List_%28abstract_data_type%29"&gt;listas&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Stack_%28data_structure%29"&gt;pilhas&lt;/a&gt; e &lt;a href="http://en.wikipedia.org/wiki/Queue_%28data_structure%29"&gt;filas&lt;/a&gt;. No caso do Delphi, esses e outros mecanismos estão disponíveis na &lt;i&gt;unit&lt;/i&gt; &lt;a href="http://docwiki.embarcadero.com/Libraries/XE2/en/System.Generics.Collections"&gt;System.Generics.Collections&lt;/a&gt;. Neste post, começo a mostrar as principais estruturas existentes nessa biblioteca, complementando a explicação com exemplos práticos em Delphi.&lt;br /&gt;
&lt;br /&gt;
Em primeiro lugar, precisamos compreender como funciona cada uma das estruturas para podermos decidir qual a mais apropriada para cada situação.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, as &lt;b&gt;filas&lt;/b&gt; são desenhadas para o cenário onde precisamos tratar uma sequência de valores exatamente na mesma ordem em que esses valores vão surgindo. É o conceito da fila do caixa em uma loja: cada cliente é atendido sequencialmente de acordo com sua posição na fila; novos clientes entram no final da fila para serem atendidos. Em programação, esse conceito pode ser aplicado ao tratamento de requisições enviadas para execução num sistema. O quadro abaixo traz a declaração básica de uma classe Delphi representando uma requisição executável:&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 5px 5px;width: 98%;"&gt;
  TWRequis = &lt;span style="color:navy;font-weight:bold;"&gt;class&lt;/span&gt;&lt;br /&gt;
  &lt;span style="color:navy;font-weight:bold;"&gt;public&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;procedure&lt;/span&gt; Execute;&lt;span style="color:navy;font-weight:bold;"&gt;virtual&lt;/span&gt;;&lt;span style="color:navy;font-weight:bold;"&gt;abstract&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;function&lt;/span&gt; Terminou : Boolean;&lt;span style="color:navy;font-weight:bold;"&gt;virtual&lt;/span&gt;;&lt;span style="color:navy;font-weight:bold;"&gt;abstract&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="color:navy;font-weight:bold;"&gt;End&lt;/span&gt;;
&lt;/div&gt;
As &lt;b&gt;Collecions&lt;/b&gt; definidas pelo Delphi são estruturas de dados genéricas, mais ou menos como as &lt;a href="http://pt.wikipedia.org/wiki/Standard_Template_Library"&gt;STL&lt;/a&gt; do C++. Isso significa que, quando declaramos uma instância dessas estruturas, devemos informar o tipo de dado que essa &lt;b&gt;Collection&lt;/b&gt; em particular vai tratar. Para deixar mais claro, veja a declaração da classe que controlará a execução de requisições em nosso exemplo de fila:&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 5px 5px;width: 98%;"&gt;
  TWVerifRequis = &lt;span style="color:navy;font-weight:bold;"&gt;class&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;font-weight:bold;"&gt;public&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;Fila: TQueue&amp;lt;TWRequis&gt;;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;procedure&lt;/span&gt; DoOnNotify (Sender: TObject; const Item: TWRequis; Action: TCollectionNotification);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;constructor&lt;/span&gt; Create;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;destructor&lt;/span&gt; Destroy;&lt;span style="color:navy;font-weight:bold;"&gt;override&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;procedure&lt;/span&gt; InsereRequis(ATipo: integer);&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;procedure&lt;/span&gt; Start;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
No exemplo, declarei a fila associada à classe de requisição. Se for necessário, também é permitido associar a tipos atômicos (como integer e string) ou a estruturas (&lt;b&gt;record&lt;/b&gt;). Agora, vamos dar uma olhada no construtor da classe:
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 5px 5px;width: 98%;"&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;constructor&lt;/span&gt; TWVerifRequis.Create;&lt;br /&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;begin&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Fila := TQueue&amp;lt;TWRequis&gt;.Create();&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Fila.OnNotify := DoOnNotify;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
Veja que também ao criar uma instância da fila (o &lt;b&gt;TQueue&lt;/b&gt;) devemos especificar o tipo de dado com o qual ela está apta a trabalhar. Um outro detalhe é o evento &lt;b&gt;OnNotify&lt;/b&gt;; interceptá-lo nos permite reagir a alterações na fila, tais como saber que um novo registro foi incluído ou acabou de ser removido. Em ambos os casos, podemos atualizar o status da fila para o usuário, avisando-o quantos registros restam e qual requisição está sendo processada. Repare ainda que a assinatura do evento reflete o tipo de dado que nossa fila trata, restringindo a resposta do &lt;b&gt;OnNotify&lt;/b&gt; a este tipo específico:
&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 5px 5px;width: 98%;"&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;procedure&lt;/span&gt; TWVerifRequis.DoOnNotify (Sender: TObject;const Item: TWRequis; Action: TCollectionNotification);&lt;br /&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;begin&lt;/span&gt;&lt;br /&gt;
  &lt;span style="color:green;margin-left:1em;"&gt;{ A requisição que está no início da fila foi removida; então, ela deve ser executada }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;if&lt;/span&gt; Action = cnRemoved &lt;span style="color:navy;font-weight:bold;"&gt;then begin&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="color:green;margin-left:2em;"&gt;{ Atualiza o status, notificando o usuário sobre que requisição está em processamento }&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;NotificaRequisAtual(Item);&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;Item.Execute;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;Item.Free;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;br /&gt;
  &lt;span style="color:green;margin-left:1em;"&gt;{ Atualiza o status, notificando o usuário sobre quantas requisições restam na fila p/ executar }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;NotificaQtd (Fila.Count);&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
As funções mais importantes para essa estrutura de dado são a que acrescenta e a que remove um elemento da fila. Para incluir um novo item ao fim da fila, use o método &lt;a href="http://docwiki.embarcadero.com/Libraries/XE2/en/System.Generics.Collections.TQueue.Enqueue"&gt;Enqueue&lt;/a&gt; e para remover o elemento que está no início da fila, use &lt;a href="http://docwiki.embarcadero.com/Libraries/XE2/en/System.Generics.Collections.TQueue.Dequeue"&gt;Dequeue&lt;/a&gt;, como mostra o exemplo a seguir:
&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 5px 5px;width: 98%;"&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;procedure&lt;/span&gt; TWVerifRequis.InsereRequis(ATipo: integer);&lt;br /&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;var&lt;/span&gt; lRequis : TWRequis;&lt;br /&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;begin&lt;/span&gt;&lt;br /&gt;
  &lt;span style="color:green;margin-left:1em;"&gt;{ Invoca a factory para criar a requisição correta de acordo com o tipo informado }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lRequis := CriaNovaRequisicao(ATipo);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="color:green;margin-left:1em;"&gt;{ Acrescenta ao fim da lista a nova requsição criada }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;Fila.Enqueue(lRequis);&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;procedure&lt;/span&gt; TWVerifRequis.Start;&lt;br /&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;var&lt;/span&gt; lRequis : TWRequis;&lt;br /&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;begin&lt;/span&gt;&lt;br /&gt;
  &lt;span style="color:green;margin-left:1em;"&gt;{ Enquanto não foi solicitado o término da execução, continua monitorando a fila }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;while Not&lt;/span&gt; Terminou() &lt;span style="color:navy;font-weight:bold;"&gt;do begin&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="color:green;margin-left:2em;"&gt;{ Se há elemento na lista, remove-o aqui. Isso dispara o evento OnNotify, permitindo a execução dessa requisição }&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;if&lt;/span&gt; (Fila.Count &gt; &lt;span style="color:blue;"&gt;0&lt;/span&gt;) &lt;span style="color:navy;font-weight:bold;"&gt;then&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;lRequis := Fila.Dequeue&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:3em;"&gt;Sleep(&lt;span style="color:blue;"&gt;1000&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
A requisição poderia ter sido executada imediatamente após a chamada ao &lt;b&gt;Dequeue&lt;/b&gt;, ao invés de dentro do evento &lt;b&gt;OnNotify&lt;/b&gt;. Ambas são soluções aceitáveis e, portanto, optar por uma ou outra abordagem é uma questão de gosto.&lt;br/&gt;
&lt;br/&gt;
Uma última consideração: se, por alguma razão, for preciso descobrir quem é o próximo item da fila sem, no entanto, removê-lo, use o método &lt;b&gt;Extract&lt;/b&gt;. Uma aplicação disso é mostrar no status informações sobre a requisição que está aguardando para ser executada.&lt;br/&gt;
&lt;br/&gt;
Esse exemplo foi construído com o Delphi XE2; não encontrei informação a respeito da presença da biblioteca &lt;a href="http://docwiki.embarcadero.com/Libraries/XE2/en/System.Generics.Collections"&gt;Collection&lt;/a&gt; em versões anteriores ou em qual versão ela foi introduzida. No próximo post, falo sobre pilhas (ou &lt;b&gt;stacks&lt;/b&gt;) e suas aplicações.
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 98%;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/Data_structure"&gt;Estruturas de Dados no Wikipedia&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/List_of_data_structures"&gt;Tipos de Estruturas de Dados&lt;/a&gt;,
&lt;a href="http://docwiki.embarcadero.com/Libraries/XE2/en/System.Generics.Collections"&gt;Documentação do System.Generics.Collections&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/hPSqsN9XJSc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/5466436367691869171/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2013/03/estruturas-de-dados-com-delphi-parte-i.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/5466436367691869171?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/5466436367691869171?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/hPSqsN9XJSc/estruturas-de-dados-com-delphi-parte-i.html" title="Estruturas de Dados com Delphi - parte I : Filas" /><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/2013/03/estruturas-de-dados-com-delphi-parte-i.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcGQHw6fip7ImA9WhNUFkk.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-8517585686740313750</id><published>2013-01-02T18:46:00.000-02:00</published><updated>2013-01-08T09:53:41.216-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-08T09:53:41.216-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Notícias" /><title>Mudanças no envio de e-mails entram em vigor em 1o de Janeiro de 2013</title><content type="html">Com o intuito de reduzir o número de spams e melhorar a segurança no envio de e-mails, o &lt;b&gt;CGI&lt;/b&gt; (&lt;a href="http://www.cgi.br/"&gt;Comitê Gestor da Internet no Brasil&lt;/a&gt;) vem recomendando alterações na forma de se enviar e-mails no país. Em acordo com a Anatel, a Associação Brasileira de Internet e o Sindicato Nacional das Empresas de Telefonia e de Serviço Móvel Celular e Pessoal, algumas alterações já foram implantadas.&lt;br /&gt;
&lt;br /&gt;
Como parte desse acordo, a partir de 1º de Janeiro de 2013 os provedores externos de e-mail deverão desligar o envio de mensagens através da porta 25, substituindo-a pela porta 587. De forma simplificada, uma porta é um canal por onde um computador se comunica com outros computadores (ou com periféricos). São exemplos de provedores externos UOL, BOL, Terra, Zipmail, Speedy, Vivo, GMail e Hotmail. E-mails enviados via modem 3G também estão sujeitos à esta mudança.&lt;br /&gt;
&lt;br /&gt;
A mudança afetará tanto o envio de e-mails através de programas tradicionais de mercado - como o Outlook - quanto aqueles programas que você mesmo tenha construído. É preciso verificar com o provedor do serviço de email utilizado se ele acatará as recomendações, adotando a porta 587 (ou outra) para envio das mensagens; em caso afirmativo, você terá que revisar as configurações dos seus aplicativos para evitar que funcionalidades dependentes do envio de e-mail deixem de operar corretamente.&lt;br /&gt;
&lt;br /&gt;
Empresas que usam servidor de e-mail próprio (como o Exchange) não precisam fazer a conversão, embora isso seja recomendado. Para adotar as recomendações nesse cenário, o TI de sua empresa precisará antes rever as configurações do servidor de e-mail, permitindo que ele envie as mensagens através da porta 587 e exija a autenticação do usuário que deseja fazer o envio.&lt;br /&gt;
&lt;br /&gt;
Reproduzo abaixo &lt;a href="http://tecnologia.uol.com.br/noticias/redacao/2012/12/20/envio-de-e-mails-com-configuracao-antiga-sera-encerrado-em-2013-saiba-corrigir.htm"&gt;matéria a esse respeito&lt;/a&gt; publicada no UOL:
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 5px 10px 1em 5px;width:98%;background-color:#e9e9fb"&gt;
Internautas que utilizam configurações antigas em programas de leitura e envio de e-mails, como o Outlook, Windows Mail, Apple Mail ou aqueles instalados no celular, podem não conseguir enviar mensagens a partir de 2013. O Comitê Gestor da Internet no Brasil (CGI) pretende reduzir o volume de spam gerado no país e, por esta razão, solicitou o fim de envios de mensagens sem autenticação, ou seja, sem que o usuário tenha de fornecer login e senha, em todo o território nacional.&lt;br /&gt;
&lt;br /&gt;
A restrição será aplicada para os programas configurados para enviar mensagens (SMTP) pela "porta 25" do computador. Quem usa programas configurados com a "porta 587" ou acessa seus e-mails pelo site do provedor (webmail) não será afetado.&lt;br /&gt;
&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://imguol.com/2012/12/20/porta-25-1356045089348_600x850.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;width:100%;" src="http://imguol.com/2012/12/20/porta-25-1356045089348_600x850.jpg" alt="Mudança no envio de e-mails" id="alterEnvioEmail20130102" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;

Para que o envio de mensagens não seja interrompido, é preciso alterar configurações do programa de e-mail, modificando a porta de envio 25 para o valor 587, associado ao padrão SMTPS (protocolo seguro para envio de mensagens).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Gerência da Porta 25&lt;/b&gt;
&lt;br /&gt;
O encerramento da porta 25 é uma recomendação do CGI para por fim a um método de envio de mensagens não solicitadas, os ‘spams’, que se aproveita de conexões não autenticadas.&lt;br /&gt;
&lt;br /&gt;
A mudança foi sugerida em acordo com a Anatel, a Associação Brasileira de Internet (Abranet, que reúne provedores e outras prestadoras de serviço na rede) e o Sindicato Nacional das Empresas de Telefonia e de Serviço Móvel Celular e Pessoal (SindiTelebrasil).&lt;br /&gt;
&lt;br /&gt;
Segundo Eduardo Nager, presidente da Abranet, os provedores estão preparados para a mudança há muito tempo, recomendando a utilização de conexões seguras e configurações atualizadas. Para Nager, a grande mudança em 1º de janeiro se dará na parte de acesso físico, a cargo das operadoras de telecomunicações.&lt;br /&gt;
&lt;br /&gt;
Eduardo Levy, diretor executivo do SindiTelebrasil, informou que o prazo para fechamento da porta 25 é o dia 31 de dezembro, acordado entre as suas filiadas, que incluem Oi, Telefônica, GVT e Embratel, além da TIM.  As operadoras Oi - responsável por Oi Velox e Oi Velox 3G - e Telefonica - que vende os serviços Vivo Speedy e Vivo 3G - informaram que já seguem as recomendações do CGI.&lt;br /&gt;
&lt;br /&gt;
Apesar de o fechamento ficar a cargo das operadoras, a notifição aos usuários ficou sob responsabilidade dos provedores de e-mails. Os usuários dos e-mails UOL e BOL recebem comunicados regulares sobre as novas configurações desde 2010.&lt;br /&gt;
&lt;br /&gt;
Além de reduzir o volume de spam enviado pelo Brasil (atualmente o sétimo país no ranking de origem de spams, segundo a empresa de segurança Sophos, e quinto, de acordo com levantamento da Kaspersky Labs), a utilização de conexões seguras pelas portas 587 ou 465 desafoga a conexão dos usuários afetados, seus provedores de acesso e dos serviços de e-mail.&lt;br /&gt;
&lt;br /&gt;
Mais do que isso, a medida ajuda a aumentar a confiabilidade dos serviços de e-mails, ajuda nos esforços para criação de filtros cada vez melhores e pode tirar sites brasileiros de listas internacionais para bloqueio de mensagens indesejadas, segundo Nager.&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;

&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 98%;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://tecnologia.uol.com.br/noticias/redacao/2012/12/20/envio-de-e-mails-com-configuracao-antiga-sera-encerrado-em-2013-saiba-corrigir.htm"&gt;Envio de e-mails com configuração antiga será encerrado em 2013; saiba corrigir&lt;/a&gt;, &lt;a href="http://www.antispam.br/porta25/tire-suas-duvidas/folheto-cgibr-porta25.pdf"&gt;Repostas às perguntas mais frequentes&lt;/a&gt;, &lt;a href="http://www.cgi.br/"&gt;Comitê Gestor da Internet no Brasil&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/D9q33TQ7Hjs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/8517585686740313750/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2013/01/mudancas-no-envio-de-e-mails-entram-em.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/8517585686740313750?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/8517585686740313750?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/D9q33TQ7Hjs/mudancas-no-envio-de-e-mails-entram-em.html" title="Mudanças no envio de e-mails entram em vigor em 1o de Janeiro de 2013" /><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/2013/01/mudancas-no-envio-de-e-mails-entram-em.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcCSHYzcSp7ImA9WhNVEE0.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-3682464566013962913</id><published>2012-12-19T11:56:00.000-02:00</published><updated>2012-12-20T09:47:49.889-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-12-20T09:47:49.889-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Script" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML" /><title>Personalizando a apresentação de mapas com o Google Maps</title><content type="html">Na maioria das vezes, as informações apresentadas num mapa produzido através da &lt;a href="http://balaiotecnologico.blogspot.com.br/2010/08/usando-versao-3-da-api-do-google-maps.html"&gt;API do Google Maps&lt;/a&gt; são suficientes para que o usuário rapidamente consiga ver um endereço e seu entorno ou a rota a ser seguida para ir de um ponto a outro. Em certas situações, no entanto, pode ser necessário adicionar ao mapa outras informações para melhor transmitir a ideia correta que se deseja.&lt;br /&gt;
&lt;br /&gt;
Esse tipo de necessidade foi exemplificado quando falei sobre o uso de marcações num mapa para apontar locais de interesse nas proximidades de um determinado endereço. O exemplo pode ser encontrado &lt;a href="http://balaiotecnologico.blogspot.com.br/2012/10/trabalhando-com-marcacoes-em-mapas-com.html"&gt;neste link&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
A &lt;b&gt;API&lt;/b&gt; do Google Maps nos permite acrescentar informações extras aos mapas através do conceito de camadas que são sobrepostas ao mapa, chamadas de &lt;b&gt;overlays&lt;/b&gt;. Para isso, a &lt;b&gt;API&lt;/b&gt; disponibiliza um conjunto de classes &lt;i&gt;javascript&lt;/i&gt;. Além da já citada &lt;a href="https://developers.google.com/maps/documentation/javascript/reference?hl=pt-BR#Marker"&gt;Marker&lt;/a&gt;, há classes para traçar linhas, delimitar áreas circulares ou retangulares e até mesmo para projetar uma imagem personalizada sobre uma área do mapa.&lt;br /&gt;
&lt;br /&gt;
O &lt;b&gt;overlay&lt;/b&gt; mais simples é o &lt;a href="https://developers.google.com/maps/documentation/javascript/reference?hl=pt-BR#Polyline"&gt;Polyline&lt;/a&gt;, usado para traçar linhas por sobre o mapa. O quadro abaixo traz código javascript que une com uma linha reta 2 pontos do mapa: a sede da &lt;a href="http://www.abc71.com.br"&gt;ABC71&lt;/a&gt; e a praça da Sé, em São Paulo:
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 5px 5px;width: 98%;"&gt;
  &lt;b&gt;var&lt;/b&gt; mapOptions = {zoom: &lt;span style="color:blue;"&gt;10&lt;/span&gt;,mapTypeId: google.maps.MapTypeId.ROADMAP};&lt;br /&gt;
  map = &lt;b&gt;new&lt;/b&gt; google.maps.Map(document.getElementById(&lt;span style="color:maroon;"&gt;'map_canvas'&lt;/span&gt;), mapOptions);&lt;br /&gt;
  geocoder = &lt;b&gt;new&lt;/b&gt; google.maps.Geocoder();&lt;br /&gt;
&lt;br /&gt;
  &lt;b&gt;var&lt;/b&gt; endDe = &lt;b&gt;new&lt;/b&gt; google.maps.LatLng(&lt;span style="color:blue;"&gt;-23.566146&lt;/span&gt;,&lt;span style="color:blue;"&gt;-46.652579&lt;/span&gt;);&lt;br /&gt;
  &lt;b&gt;var&lt;/b&gt; endAte  = &lt;b&gt;new&lt;/b&gt; google.maps.LatLng(&lt;span style="color:blue;"&gt;-23.550563&lt;/span&gt;,&lt;span style="color:blue;"&gt;-46.633101&lt;/span&gt;);&lt;br /&gt;
  &lt;b&gt;var&lt;/b&gt; request = { location: endDe, region: &lt;span style="color:maroon;"&gt;'BR'&lt;/span&gt;};&lt;br /&gt;
    &lt;br /&gt;
  geocoder.geocode (request, function(response, status) {&lt;br /&gt;
         &lt;span style="margin-left:1em;"&gt;&lt;b&gt;if&lt;/b&gt; (status == google.maps.GeocoderStatus.OK) {&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:2em;"&gt;map.fitBounds (&lt;b&gt;new&lt;/b&gt; google.maps.LatLngBounds(endDe, endAte));&lt;/span&gt;&lt;br /&gt;
     &lt;span style="margin-left:2em;"&gt;&lt;span style="color:green;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
     &lt;span style="margin-left:2em;"&gt;&lt;b&gt;var&lt;/b&gt; pontos = &lt;b&gt;new&lt;/b&gt; google.maps.MVCArray ();&lt;/span&gt;&lt;br /&gt;
     &lt;span style="margin-left:2em;"&gt;pontos.push (endDe);&lt;/span&gt;&lt;br /&gt;
     &lt;span style="margin-left:2em;"&gt;pontos.push (endAte);&lt;/span&gt;&lt;br /&gt;
           &lt;br /&gt;
     &lt;span style="margin-left:2em;"&gt;&lt;b&gt;var&lt;/b&gt; rect = &lt;b&gt;new&lt;/b&gt; google.maps.Polyline ({&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:3em;"&gt;path: pontos,&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:3em;"&gt;map:map,&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:3em;"&gt;strokeWeight: &lt;span style="color:blue;"&gt;5&lt;/span&gt;,&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:3em;"&gt;strokeColor: &lt;span style="color:maroon;"&gt;'blue'&lt;/span&gt;,&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:3em;"&gt;visible: true&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;/div&gt;
Após as &lt;a href="http://balaiotecnologico.blogspot.com.br/2010/08/usando-versao-3-da-api-do-google-maps.html"&gt;inicializações de praxe&lt;/a&gt; para o ambiente do &lt;b&gt;Maps&lt;/b&gt;, o código solicita a geocodificação do endereço da &lt;b&gt;ABC71&lt;/b&gt; (na verdade, sua latitude/longitude).&lt;br /&gt;
Em resposta à conclusão da geocodificação, isto é, assim que o mapa com o endereço solicitado está pronto, eu crio uma lista &lt;a href="https://developers.google.com/maps/documentation/javascript/reference?hl=pt-BR#MVCArray"&gt;MVCArray&lt;/a&gt; e adiciono a ela os dois pontos que definem a reta desejada.&lt;br /&gt;
&lt;br /&gt;
Em seguida, instancio a classe &lt;b&gt;Polyline&lt;/b&gt; propriamente dita, fornecendo-lhe a lista de pontos. Também indico o mapa onde a linha será traçada (&lt;b&gt;map&lt;/b&gt;), a espessura da linha em pixels (&lt;b&gt;strokeWeight&lt;/b&gt;) e a cor dela (&lt;b&gt;strokeColor&lt;/b&gt;). As cores podem ser informadas tanto pelo &lt;a href="http://www.w3schools.com/html/html_colornames.asp"&gt;nome HTML&lt;/a&gt; quanto pela notação RGB hexadecimal.&lt;br /&gt;
&lt;br /&gt;
Posso, por exemplo, demarcar um bairro inteiro com esse recurso? Sim, mas você terá que montar a lista de pontos o mais completa possível para que o desenho resultante tenha uma precisão adequada. O &lt;b&gt;Polyline&lt;/b&gt; produz linhas abertas; para traçar linhas fechadas com uma quantidade arbitrária de pontos use a classe &lt;a href="https://developers.google.com/maps/documentation/javascript/reference?hl=pt-BR#Polygon"&gt;Polygon&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
A função &lt;b&gt;fitBounds&lt;/b&gt;, usada no início da resposta, apenas aplica um nível de zoom apropriado para garantir que ambos os endereços sejam exibidos num único quadro, sem que o usuário precise interagir com ele.&lt;br /&gt;
&lt;br /&gt;
O código analisado produz o mapa a seguir:
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 5px 10px 5px 5px;width: 98%;"&gt;&lt;center&gt;&lt;iframe width='100%' height='480px' frameborder='0' src='http://lgaf.webs.com/arqs/mapaLine.html'&gt;&lt;/iframe&gt;&lt;/center&gt;&lt;/div&gt;
Imagine agora o caso de uma pizzaria que queira divulgar num mapa o raio de ação onde ela faz entregas. O overlay produzido pela classe &lt;a href="https://developers.google.com/maps/documentation/javascript/reference?hl=pt-BR#Circle"&gt;Circle&lt;/a&gt; permite dar destaque a uma área circular, dado um centro e um raio em metros. Veja o exemplo:
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 5px 5px;width: 98%;"&gt;
  &lt;b&gt;var&lt;/b&gt; endDe = &lt;b&gt;new&lt;/b&gt; google.maps.LatLng(&lt;span style="color:blue;"&gt;-23.566146&lt;/span&gt;,&lt;span style="color:blue;"&gt;-46.652579&lt;/span&gt;);&lt;br /&gt;
  &lt;b&gt;var&lt;/b&gt; request = { location: endDe, region: &lt;span style="color:maroon;"&gt;'BR'&lt;/span&gt;};&lt;br /&gt;
    &lt;br /&gt;
  geocoder.geocode (request, function(response, status) {&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;&lt;b&gt;if&lt;/b&gt; (status == google.maps.GeocoderStatus.OK) {&lt;/span&gt;&lt;br /&gt;
     &lt;span style="margin-left:2em;"&gt;map.setCenter(endDe);&lt;/span&gt;&lt;br /&gt;
     &lt;span style="margin-left:2em;"&gt;&lt;span style="color:green;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
       &lt;span style="margin-left:2em;"&gt;&lt;b&gt;var&lt;/b&gt; circleOpts = ({&lt;/span&gt;&lt;br /&gt;
            &lt;span style="margin-left:3em;"&gt;map: map,&lt;/span&gt;&lt;br /&gt;
            &lt;span style="margin-left:3em;"&gt;center: endDe,&lt;/span&gt;&lt;br /&gt;
            &lt;span style="margin-left:3em;"&gt;editable: false,&lt;/span&gt;&lt;br /&gt;
            &lt;span style="margin-left:3em;"&gt;fillColor: &lt;span style="color:maroon;"&gt;'yellow'&lt;/span&gt;,&lt;/span&gt;&lt;br /&gt;
            &lt;span style="margin-left:3em;"&gt;fillOpacity: &lt;span style="color:blue;"&gt;0.4&lt;/span&gt;,&lt;/span&gt;&lt;br /&gt;
            &lt;span style="margin-left:3em;"&gt;radius: &lt;span style="color:blue;"&gt;3500&lt;/span&gt;,&lt;/span&gt;&lt;br /&gt;
            &lt;span style="margin-left:3em;"&gt;strokeColor: &lt;span style="color:maroon;"&gt;'#0099ff'&lt;/span&gt;,&lt;/span&gt;&lt;br /&gt;
            &lt;span style="margin-left:3em;"&gt;strokeWeight: &lt;span style="color:blue;"&gt;4&lt;/span&gt;,&lt;/span&gt;&lt;br /&gt;
            &lt;span style="margin-left:3em;"&gt;visible: true&lt;/span&gt;
          &lt;span style="margin-left:2em;"&gt;});&lt;/span&gt;&lt;br /&gt;
       &lt;span style="margin-left:2em;"&gt;&lt;b&gt;var&lt;/b&gt; circle = &lt;b&gt;new&lt;/b&gt; google.maps.Circle (circleOpts);&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:1em;"&gt;}&lt;/span&gt;&lt;br /&gt;
   });
&lt;/div&gt;
Como no caso da linha, para o círculo também valem as propriedades que indicam o mapa, a cor do traço e sua espessura. Mas, ao invés de uma lista de pontos, informamos apenas o centro; no código anterior, usei o próprio endereço da &lt;a href="http://www.abc71.com.br"&gt;ABC71&lt;/a&gt; para isso. A definição do círculo fica completa com a propriedade &lt;b&gt;radius&lt;/b&gt; - o raio, fornecido em metros; no exemplo, o raio terá 3500 metros (ou 3,5 Km).&lt;br /&gt;
&lt;br /&gt;
Outra configuração disponível diz respeito ao preenchimento da área delimitada pelo círculo. A propriedade &lt;b&gt;fillColor&lt;/b&gt; determina a cor do preenchimento enquanto a &lt;b&gt;fillOpacity&lt;/b&gt; controla o grau de transparência, sendo que o valor 1 significa totalmente opaco (o mapa sob o círculo não é visto) e o valor 0 suspende o preenchimento.&lt;br /&gt;
&lt;br /&gt;
A propriedade &lt;b&gt;editable&lt;/b&gt;, quando ativa, permite ao usuário redimensionar o círculo. Eu a desliguei pois ela não faz sentido no contexto do exemplo. O resultado é o mapa exibido no quadro abaixo:
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 5px 10px 5px 5px;width: 98%;"&gt;&lt;center&gt;&lt;iframe width='100%' height='480px' frameborder='0' src='http://lgaf.webs.com/arqs/mapaLayer.html'&gt;&lt;/iframe&gt;&lt;/center&gt;&lt;/div&gt;
&lt;br /&gt;
Os mesmos conceitos valem para a classe &lt;a href="https://developers.google.com/maps/documentation/javascript/reference?hl=pt-BR#Rectangle"&gt;Rectangle&lt;/a&gt;. Além disso, é permitido trabalhar com vários &lt;b&gt;overlays&lt;/b&gt; num mesmo mapa, se for necessário. Os exemplos publicados nesse post podem ser acessados respectivamente nos seguintes links : &lt;a href="http://lgaf.webs.com/arqs/mapaLine.html"&gt;Overlay com Linha&lt;/a&gt; e &lt;a href="http://lgaf.webs.com/arqs/mapaLine.html"&gt;Overlay com Círculo&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 98%;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.br/2010/08/usando-versao-3-da-api-do-google-maps.html"&gt;Usando a versão 3 da API do Google Maps&lt;/a&gt;,
&lt;a href="https://developers.google.com/maps/documentation/javascript/overlays"&gt;Overlays no Google Developers&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/3sO9P0EDdY0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/3682464566013962913/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/12/incluindo-camadas-personalizadas-em.html#comment-form" title="2 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/3682464566013962913?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/3682464566013962913?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/3sO9P0EDdY0/incluindo-camadas-personalizadas-em.html" title="Personalizando a apresentação de mapas com o Google Maps" /><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/2012/12/incluindo-camadas-personalizadas-em.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIERnY9fip7ImA9WhNQFkQ.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-2583951886123113973</id><published>2012-11-23T16:48:00.001-02:00</published><updated>2012-11-23T16:48:27.866-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-11-23T16:48:27.866-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><title>Integrando o Outlook em aplicações Delphi - Parte II</title><content type="html">No &lt;a href="http://balaiotecnologico.blogspot.com.br/2012/11/integrando-o-outlook-em-aplicacoes.html"&gt;último post&lt;/a&gt;, eu mostrei os conceitos básicos envolvidos na integração do Outlook com aplicações Delphi. O exemplo apresentado lá abordou a manipulação dos contatos cadastrados no Outlook bem como a criação de novos contatos. Neste post eu abordo o aspecto mais utilizado da ferramenta, que é lidar com envio e recebimento de emails.&lt;br/&gt;
&lt;br/&gt;
Enviar um email com o Outlook de dentro de um programa Delphi é uma operação relativamente simples. Assim como no caso dos contatos, o ponto de partida é objeto &lt;a href="http://msdn.microsoft.com/en-us/library/ff863377.aspx"&gt; Outlook.Application&lt;/a&gt;. Aqui, no entanto, não é necessário trabalhar com &lt;a href="http://msdn.microsoft.com/en-us/library/ff869368.aspx"&gt;Namespaces&lt;/a&gt;. Basta criar uma instância de &lt;a href="http://msdn.microsoft.com/en-us/library/ff861332%28v=office.14%29.aspx"&gt;MailItem&lt;/a&gt; (este é o tipo de objeto do Outlook que representa uma nova mensagem), fornecer-lhe informações relevantes para o envio e, então, efetivamente enviá-la. O código a seguir exemplifica esses passos:
&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px  5px 5px;width: 98%;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;procedure&lt;/span&gt; TForm1.btnEnviarClick(Sender: TObject);&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;var&lt;/span&gt; OutlookApp: TOutlookApplication;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;email : MailItem;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;begin&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;OutlookApp := TOutlookApplication.Create(&lt;span style="color:navy;font-weight:bold;"&gt;Nil&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
  &lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;email := OutlookApp.CreateItem(olMailItem) &lt;span style="color:navy;font-weight:bold;"&gt;As&lt;/span&gt; MailItem;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;email.Subject := &lt;span style="color:maroon;"&gt;'Envio automático'&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;email.BodyFormat := olFormatHTML;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;email.HTMLBody := &lt;span style="color:maroon;"&gt;'Este email é um &amp;lt;b&gt;teste&amp;lt;/b&gt; para envio &amp;lt;b&gt;&amp;ltspan style="color:maroon;"&gt;automático&amp;lt;/span&gt;&amp;lt;/b&gt;.'&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;email.Importance := olImportanceNormal;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;email.Recipients.Add(&lt;span style="color:maroon;"&gt;'&amp;#98;&amp;#x61;&amp;#108;&amp;#x61;&amp;#105;&amp;#111;&amp;#x74;&amp;#101;&amp;#99;&amp;#110;&amp;#x6f;&amp;#108;&amp;#x6f;&amp;#103;&amp;#105;&amp;#x63;&amp;#111;&amp;#64;&amp;#x67;&amp;#x6d;&amp;#97;&amp;#105;&amp;#108;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#109;'&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;if&lt;/span&gt; (email.Recipients.ResolveAll) &lt;span style="color:navy;font-weight:bold;"&gt;then&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;email.Send&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;else begin&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;Application.MessageBox(&lt;span style="color:maroon;"&gt;'Um ou mais destinatários não puderam ser resolvidos.'#13&lt;/span&gt;+&lt;/span&gt;&lt;br/&gt;
                           &lt;span style="margin-left:4em;"&gt;&lt;span style="color:maroon;"&gt;'Reveja a informação e tente novamente.'&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
                          &lt;span style="margin-left:4em;"&gt;, &lt;span style="color:maroon;"&gt;'Alerta'&lt;/span&gt;, MB_ICONWARNING);&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;email.Display(true);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
  &lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;OutlookApp.Disconnect;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;OutlookApp.Free;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
Veja que a criação da instância da mensagem é feita diretamente no objeto que representa a aplicação Outlook. A função &lt;a href="http://msdn.microsoft.com/en-us/library/ff869635%28v=office.14%29.aspx"&gt;CreateItem&lt;/a&gt; usada para esse fim é genérica e permite criar qualquer item dentro do Outlook. Assim, o valor &lt;a href="http://msdn.microsoft.com/en-us/library/ff869291%28v=office.14%29.aspx"&gt;olMailItem&lt;/a&gt; passado como parâmetro garante que o que está sendo criado é uma nova mensagem. &lt;br/&gt;
&lt;br/&gt;
Após a criação, eu formato a mensagem fornecendo valores para propriedades relevantes como o assunto (&lt;b&gt;Subject&lt;/b&gt;), a prioridade da mensagem (&lt;b&gt;Importance&lt;/b&gt;), o texto dela (&lt;b&gt;Body&lt;/b&gt; ou &lt;b&gt;HTMLBody&lt;/b&gt;, dependendo do formato escolhido) e os destinários que a receberão (&lt;b&gt;Recipients&lt;/b&gt;).&lt;br/&gt;
&lt;br/&gt;
Opcionalmente, o método &lt;a href="http://msdn.microsoft.com/en-us/library/ff867165%28v=office.14%29.aspx"&gt;ResolveAll&lt;/a&gt; da lista de destinatários é chamado  para verificar se os endereços incluídos são válidos. Em caso negativo, a própria tela de envio de email do Outlook é apresentada para que o usuário faça as correções necessárias antes de enviar o email manualmente.&lt;br/&gt;
&lt;br/&gt;
Uma vez que a verificação foi feita com sucesso, a função &lt;a href="http://msdn.microsoft.com/en-us/library/ff866779%28v=office.14%29.aspx"&gt;Send&lt;/a&gt; é chamada para efetivar o envio. Por padrão, uma cópia da mensagem é armazenada na pasta &lt;b&gt;Sent Items&lt;/b&gt;. Se não quiser guardar a cópia, use a propriedade &lt;a href="http://msdn.microsoft.com/en-us/library/ff868585%28v=office.14%29.aspx"&gt;DeleteAfterSubmit&lt;/a&gt;, ajustando-a para &lt;b&gt;true&lt;/b&gt;. É possível também indicar outra pasta para guardar a cópia, modificando-se o valor da propriedade &lt;a href="http://msdn.microsoft.com/en-us/library/ff868473%28v=office.14%29.aspx"&gt;SaveSentMessageFolder&lt;/a&gt;.&lt;br/&gt;
&lt;br/&gt;
Repare que não informei quem é o remetente da mensagem. Normalmente, o Outlook é configurado para fazer logon automaticamente. O remetente, então, é sempre o usuário que fez o logon, não importando se isso foi feito automaticamente ou de forma explícita no código, via função &lt;a href="http://msdn.microsoft.com/en-us/library/ff861594.aspx"&gt;Logon&lt;/a&gt;.&lt;br/&gt;
&lt;br/&gt;
Para finalizar, desconecto do Outlook e a libero a memória usada por ele.&lt;br/&gt;
&lt;br/&gt;
Neste exemplo, passei o valor &lt;b&gt;olFormatHTML&lt;/b&gt; na propriedade &lt;b&gt;BodyFormat&lt;/b&gt; para permitir a inserção de código HTML diretamente em &lt;b&gt;HTMLBody&lt;/b&gt;, o que flexibiliza a formatação da mensagem.&lt;br/&gt;
&lt;br/&gt;
Embora eu não tenha tratado no código, é possível também incluir anexos no email. Um &lt;b&gt;MailItem&lt;/b&gt; possui a propriedade &lt;a href="http://msdn.microsoft.com/en-us/library/ff866435%28v=office.14%29.aspx"&gt;Attachments&lt;/a&gt; para conter a lista de anexos. Antes do envio, podemos adicionar um ou mais anexos:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px  5px 5px;width: 98%;"&gt;
email.Attachments.Add(&lt;span style="color:maroon;"&gt;'c:\ERP\abc71.jpg&lt;/span&gt;', EmptyParam, EmptyParam, EmptyParam);
&lt;/div&gt;
O primeiro parâmetro é o caminho completo do arquivo a ser anexado. Os demais parâmetros são opcionais; passei &lt;b&gt;EmptyParam&lt;/b&gt; a eles para que a função assuma os valores padronizados.&lt;br/&gt;
&lt;br/&gt;
Para encerrar esse tópico, falo de um problema recorrente pra quem automatiza envio de email com o Outlook: a inclusão da assinatura padrão do usuário no corpo da mensagem. Da forma como foi exposto até aqui, apenas o texto incluído em &lt;b&gt;HTMLBody&lt;/b&gt; será enviado, sem qualquer decoração extra que o usuário tenha configurado - como a assinatura ou um papel de carta. Isso acontece porque esses recursos não são inerentes ao &lt;b&gt;MailItem&lt;/b&gt; mas sim ao editor associado a ele. Para acionar o editor, precisamos apenas invocar o método &lt;a href="http://msdn.microsoft.com/en-us/library/ff868098%28v=office.14%29.aspx"&gt;GetInspector&lt;/a&gt;. Um inspector é o responsável pela edição do item atual e, ao invocar o método, todo o ambiente para edição é criado, incluindo a formatação padrão para o item - neste caso, um email.&lt;br/&gt;
&lt;br/&gt;
Isso preencherá o &lt;b&gt;HTMLBody&lt;/b&gt; com um HTML completo, englobando a assinatura e outras formatações. Então, teremos que localizar a tag BODY desse HTML para acrescentar nosso texto personalizado no local correto sem perder a formatação padrão. O quadro abaixo mostra como obter esse efeito:
&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px  5px 5px;width: 98%;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;var&lt;/span&gt; &lt;span style="color:green;"&gt;{ ... } &lt;/span&gt;&lt;br/&gt;
   &lt;span style="margin-left:3em;"&gt;email : MailItem;&lt;/span&gt;&lt;br/&gt;
   &lt;span style="margin-left:3em;"&gt;insp : Inspector;&lt;/span&gt;&lt;br/&gt;
   &lt;span style="margin-left:3em;"&gt;idx: integer;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;begin&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;insp := email.GetInspector;&lt;/span&gt;&lt;br/&gt;
  &lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;idx := Pos (&lt;span style="color:maroon;"&gt;'&amp;lt;body'&lt;/span&gt;, email.HTMLBody);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;idx := PosEx (&lt;span style="color:maroon;"&gt;'&amp;gt;'&lt;/span&gt;, email.HTMLBody, idx);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;email.HTMLBody := MidStr (email.HTMLBody, &lt;span style="color:blue;"&gt;1&lt;/span&gt;, idx) +&lt;/span&gt;&lt;br/&gt;
                    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:maroon;"&gt;'Este email é um &amp;lt;b&gt;teste&amp;lt;/b&gt; para envio &amp;lt;b&gt;&amp;lt;span style="color:maroon;"&gt;automático&amp;lt;/span&gt;&amp;lt;/b&gt;.'&lt;/span&gt; +&lt;/span&gt;&lt;br/&gt;
                    &lt;span style="margin-left:2em;"&gt;MidStr (email.HTMLBody, idx+&lt;span style="color:blue;"&gt;1&lt;/span&gt;, Length(email.HTMLBody));&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;if&lt;/span&gt; (email.Recipients.ResolveAll) &lt;span style="color:navy;font-weight:bold;"&gt;then&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;email.Send;&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;
Nessa abordagem, apesar de o editor ser criado e sua configuração padrão ser respeitada, ele não é exibido para usuário. Se for necessário, chame o &lt;a href="http://msdn.microsoft.com/en-us/library/ff861853%28v=office.14%29.aspx"&gt;Display&lt;/a&gt; do &lt;b&gt;MailItem&lt;/b&gt; para exibí-lo.&lt;br/&gt;
&lt;br/&gt;
Comentei no post anterior mas não custa lembrar: todas as operações descritas neste aqui exigem que o Outlook esteja instalado no computador que for executá-las.&lt;br/&gt;
&lt;br/&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 98%;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.br/2012/11/integrando-o-outlook-em-aplicacoes.html"&gt;Integrando o Outlook em aplicações Delphi - Parte I&lt;/a&gt;,
&lt;a href="http://msdn.microsoft.com/en-us/library/ff870566.aspx"&gt;Outlook Object Model Reference&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/XB4iPxXDXe8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/2583951886123113973/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/11/integrando-o-outlook-em-aplicacoes_23.html#comment-form" title="12 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/2583951886123113973?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/2583951886123113973?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/XB4iPxXDXe8/integrando-o-outlook-em-aplicacoes_23.html" title="Integrando o Outlook em aplicações 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>12</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2012/11/integrando-o-outlook-em-aplicacoes_23.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8ERnk6fip7ImA9WhNREk4.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-8618859243948203316</id><published>2012-11-06T18:46:00.002-02:00</published><updated>2012-11-06T18:46:47.716-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-11-06T18:46:47.716-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><title>Integrando o Outlook em aplicações Delphi - Parte I</title><content type="html">Embora eu não tenha números exatos, o &lt;a href="http://en.wikipedia.org/wiki/Microsoft_Outlook"&gt;Outlook&lt;/a&gt; é o programa de email mais utilizado em desktops. Parte desse sucesso se deve à ampla adoção da ferramenta no ambiente corporativo, já que ela também centraliza funções de calendário, acompanhamento de tarefas e agenda de contatos, permitindo compartilhar facilmente as informações.&lt;br/&gt;
&lt;br/&gt;
Um outro aspecto positivo é que o &lt;b&gt;Outlook&lt;/b&gt; é componentizado, o que abre caminho para criação de extensões e integrações com outros sistemas. Neste post, mostro como utilizar os recursos &lt;a href="http://en.wikipedia.org/wiki/Component_Object_Model"&gt;COM&lt;/a&gt; do &lt;b&gt;Outlook&lt;/b&gt; para integrá-lo a uma aplicação Delphi.&lt;br/&gt;
&lt;br/&gt;
Do mesmo modo que as outras aplicações do Microsoft Office (como o Excel), todos os recursos disponíveis do Outlook devem se acessados a partir de um objeto centralizador que representa a própria aplicação. Neste caso, precisamos obter uma instância de &lt;a href="http://msdn.microsoft.com/en-us/library/ff863377.aspx"&gt;Outlook.Application&lt;/a&gt;, mapeada pelo Delphi na &lt;i&gt;unit&lt;/i&gt; &lt;b&gt;OutlookXP&lt;/b&gt;, junto com as demais interfaces existentes para se trabalhar com a ferramenta.&lt;br/&gt;
&lt;br/&gt;
O quadro abaixo mostra um exemplo dos passos básicos necessários para interagir com o Outlook. O código apresentado percorre os contatos registrados na pasta local do Outlook, listando informações de cada um deles numa tabela:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px  5px 5px;width: 98%;"&gt;
&lt;span style="color:navy;weight;"&gt;procedure&lt;/span&gt; TForm1.btnListarContatosClick(Sender: TObject);&lt;br/&gt;
&lt;span style="color:navy;weight;"&gt;var&lt;/span&gt; i : integer;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;OutlookApp: TOutlookApplication;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;ns : NameSpace;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;pasta: MAPIFolder;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;contato : _ContactItem;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;weight;"&gt;begin&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;StringGrid1.RowCount := &lt;span style="color:blue;"&gt;2&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;OutlookApp := TOutlookApplication.Create(&lt;span style="color:navy;weight;"&gt;Nil&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
  &lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;ns := OutlookApp.GetNamespace(&lt;span style="color:maroon;"&gt;'MAPI'&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;pasta := ns.GetDefaultFolder(olFolderContacts);&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;weight;"&gt;for&lt;/span&gt; i := &lt;span style="color:blue;"&gt;1&lt;/span&gt; &lt;span style="color:navy;weight;"&gt;to&lt;/span&gt; pasta.Items.Count &lt;span style="color:navy;weight;"&gt;do&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;weight;"&gt;begin&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;weight;"&gt;if&lt;/span&gt; (i &gt; &lt;span style="color:blue;"&gt;1&lt;/span&gt;) &lt;span style="color:navy;weight;"&gt;then&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:3em;"&gt;StringGrid1.RowCount := StringGrid1.RowCount + &lt;span style="color:blue;"&gt;1&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
      &lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;contato := pasta.Items.Item(i) &lt;span style="color:navy;weight;"&gt;As&lt;/span&gt; _ContactItem;&lt;/span&gt;&lt;br/&gt;
    &lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;StringGrid1.Cells [&lt;span style="color:blue;"&gt;1&lt;/span&gt;,i] := contato.FullName;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;StringGrid1.Cells [&lt;span style="color:blue;"&gt;2&lt;/span&gt;,i] := contato.Email1Address;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;StringGrid1.Cells [&lt;span style="color:blue;"&gt;3&lt;/span&gt;,i] := contato.EntryID;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;StringGrid1.Cells [&lt;span style="color:blue;"&gt;4&lt;/span&gt;,i] := contato.CompanyName;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;StringGrid1.Cells [&lt;span style="color:blue;"&gt;5&lt;/span&gt;,i] := contato.BusinessAddress;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;weight;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;OutlookApp.Disconnect;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;OutlookApp.Free;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;weight;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
Vamos destrinchar esse código. Após criar uma instância para acessar a aplicação (classe &lt;b&gt;TOutlookApplication&lt;/b&gt;), o trecho recupera um tipo de objeto denominado &lt;a href="http://msdn.microsoft.com/en-us/library/ff869368.aspx"&gt;Namespace&lt;/a&gt;. Atualmente, apenas o namespace &lt;a href="http://en.wikipedia.org/wiki/Messaging_Application_Programming_Interface"&gt;MAPI&lt;/a&gt; (API de Mensagens do Windows) está disponível, concentrando todos os registros, isto é, os emails, contatos, tarefas e entradas do calendário. Um &lt;b&gt;Namespace&lt;/b&gt; é organizado em pastas dispostas hierarquicamente, podendo haver pastas dentro de pastas para armazenar os itens.&lt;br/&gt;
&lt;br/&gt;
Há algumas formas de acessar as pastas do &lt;b&gt;Outlook&lt;/b&gt;. A propriedade &lt;a href="http://msdn.microsoft.com/en-us/library/ff868379.aspx"&gt;Folders&lt;/a&gt; do &lt;b&gt;Namespace&lt;/b&gt; lista todas as pastas, incluindo as compartilhadas com outros usuários no servidor. As subpastas eventualmente existentes são acessíveis por meio de propriedade &lt;b&gt;Folders&lt;/b&gt; própria. E como saber que tipo de item uma pasta contém? Em princípio, pode-se consultar a propriedade &lt;a href="http://msdn.microsoft.com/en-us/library/ff865360.aspx"&gt;DefaultItemType&lt;/a&gt; para se ter uma ideia. Mas, certas pastas (como a DeletedItems) podem conter itens de &lt;a href="http://msdn.microsoft.com/en-us/library/ff869291.aspx"&gt;tipos&lt;/a&gt; diferentes misturados. Neste caso, recomenda-se checar a propriedade &lt;b&gt;Class&lt;/b&gt; do item ou fazer um &lt;i&gt;cast dinâmico&lt;/i&gt; para o tipo desejado e ver se a conversão foi bem sucedida.&lt;br/&gt;
&lt;br/&gt;
Outra forma de acesso é requerer ao &lt;b&gt;Namespace&lt;/b&gt; a pasta padrão para um determinado tipo de item, como no código mostrado acima. Lá, uso &lt;a href="http://msdn.microsoft.com/en-us/library/ff866724.aspx"&gt;GetDefaultFolder&lt;/a&gt; para recuperar exclusivamente a pasta que armazena meus contatos. Por fim, se eu possuir a identificação única da pasta (seu &lt;b&gt;entryID&lt;/b&gt;, posso recuperá-la diretamente com a função &lt;a href="http://msdn.microsoft.com/en-us/library/ff869893.aspx"&gt;GetItemFromID&lt;/a&gt; do Namespace.&lt;br/&gt;
&lt;br/&gt;
Voltando ao código, agora tenho uma instância da pasta de contatos para trabalhar. Como toda pasta, esta possui uma lista &lt;b&gt;Items&lt;/b&gt; que dá acesso ao conteúdo específico - no exemplo, os contatos cadastrados. Então, percorro a lista para prencher a tabela com as informações desejadas de cada um dos contatos.&lt;br/&gt;
&lt;br/&gt;
Para concluir, desconecto minha instância do &lt;b&gt;Outlook&lt;/b&gt; e removo-a da memória para liberar os recursos utilizados.&lt;br/&gt;
&lt;br/&gt;
Note que não foi preciso informar usuário e senha para fazer logon. Isso acontece porque o Outlook pode ser configurado para se conectar automaticamente com o mesmo usuário do Windows. Se for preciso, pode-se logar manualmente usando a função &lt;a href="http://msdn.microsoft.com/en-us/library/ff861594.aspx"&gt;Logon&lt;/a&gt; do &lt;b&gt;Namespace&lt;/b&gt;.&lt;br/&gt;
&lt;br/&gt;
Aproveitando os mesmos conceitos, podemos criar automaticamente um novo contato, conforme mostra o trecho de código a seguir:
&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px  5px 5px;width: 98%;"&gt;
contato := pasta.Items.Add(olContactItem) &lt;span style="color:navy;weight;"&gt;As&lt;/span&gt; _ContactItem;&lt;br/&gt;
contato.FirstName := &lt;span style="color:maroon;"&gt;'Balaio'&lt;/span&gt;;&lt;br/&gt;
contato.LastName := &lt;span style="color:maroon;"&gt;'Tecnológico'&lt;/span&gt;;&lt;br/&gt;
contato.CompanyName := &lt;span style="color:maroon;"&gt;'ABC71 Soluções Em Informática'&lt;/span&gt;;&lt;br/&gt;
contato.Save;&lt;br/&gt;
contato.Display(&lt;span style="color:blue;"&gt;1&lt;/span&gt;);
&lt;/div&gt;
Como se vê, a criação é bastante simples. Primeiro, chamo o método &lt;a href="http://msdn.microsoft.com/en-us/library/ff861028.aspx"&gt;Add&lt;/a&gt; da lista de itens da pasta, fornecendo-lhe o tipo de item que deve ser criado - um item de contato, neste caso. Após prover algumas informações básicas do contato, salvo o registro. A última linha não é imprescindível; ela apenas exibe no próprio &lt;b&gt;Outlook&lt;/b&gt; o contato recém-criado para que o usuário possa complementar as informações, se desejar.&lt;br/&gt;
&lt;br/&gt;
De forma similar, conseguimos trabalhar com tarefas e compromissos no calendário. Também é possível fazer o envio de email aproveitando a infraestrutra já configurada do Outlook, operação que mostro no próximo &lt;i&gt;post&lt;/i&gt;.&lt;br/&gt;
&lt;br/&gt;
Obviamente, todos os recursos apresentados aqui exigem que haja uma cópia do Outlook instalado no computador local para funcionar.&lt;br/&gt;
&lt;br/&gt;

&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 98%;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/ff870566.aspx"&gt;Outlook Object Model Reference&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/aa189757%28v=office.10%29.aspx"&gt;Working with Microsoft Outlook Objects&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/iDvvRnJyNFQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/8618859243948203316/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/11/integrando-o-outlook-em-aplicacoes.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/8618859243948203316?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/8618859243948203316?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/iDvvRnJyNFQ/integrando-o-outlook-em-aplicacoes.html" title="Integrando o Outlook em aplicações Delphi - 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/2012/11/integrando-o-outlook-em-aplicacoes.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cER3c9eyp7ImA9WhJaEk0.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-4955671161591147026</id><published>2012-10-02T14:49:00.002-03:00</published><updated>2012-10-02T15:03:26.963-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-02T15:03:26.963-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Script" /><category scheme="http://www.blogger.com/atom/ns#" term="Internet" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML" /><title>Trabalhando com marcações em mapas com a versão 3 da API do Google Maps</title><content type="html">Além dos tradicionais recursos de exibir o mapa para um determinado endereço ou traçar rotas entre endereços fornecidos, a API do Google Maps disponibliza um outro recurso bastante interessante que permite incluir num mapa marcações customizadas. Com isso, você pode marcar pontos de interesse de acordo com as necessidades de sua aplicação. Um exemplo de aplicabilidade desse conceito seria indicar num mapa a localização de estabelecimentos comerciais nas proximidades de um endereço, tais como Caixas 24 Horas, Supermercados, escolas de inglês ou outro qualquer. Obviamente, isso demandará saber de antemão a posição de cada um dos locais passíveis de serem marcados no mapa.&lt;br /&gt;
&lt;br /&gt;
O processo de marcação em si é bastante simples. Após termos ajustado a parametrização inicial do ambiente do Maps e requisitado a exibição de um endereço (veja post &lt;a href="http://balaiotecnologico.blogspot.com.br/2010/08/usando-versao-3-da-api-do-google-maps.html"&gt;Usando a versão 3 da API do Google Maps&lt;/a&gt;), basta criar uma instância da classe &lt;a href="https://developers.google.com/maps/documentation/javascript/reference?hl=pt-BR#Marker"&gt;google.maps.Marker&lt;/a&gt;, como no quadro abaixo:
&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 5px 5px; width: 98%;"&gt;&lt;b&gt;function&lt;/b&gt; mostraEnderecoABC71 () {&lt;br /&gt;
   &lt;span style="margin-left:1em;"&gt;&lt;b&gt;var&lt;/b&gt; lRequest = { address: &lt;span style="color:maroon;"&gt;'Alameda Santos, 1000, São Paulo - SP, 01418-902'&lt;/span&gt;, region: &lt;span style="color:maroon;"&gt;'BR'&lt;/span&gt;};&lt;/span&gt;&lt;br /&gt;
   &lt;span style="margin-left:1em;"&gt;geocoder.geocode( lRequest, trataLocais);&lt;/span&gt;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;function&lt;/b&gt; trataLocais (results, status){&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;b&gt;if&lt;/b&gt; (status == google.maps.GeocoderStatus.OK)&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;map.setCenter(results[0].geometry.location);&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;b&gt;var&lt;/b&gt; marker = &lt;b&gt;new&lt;/b&gt; google.maps.Marker(&lt;/span&gt;&lt;br /&gt;
                  &lt;span style="margin-left:4em;"&gt;{map: map, &lt;/span&gt;&lt;br /&gt;
                   &lt;span style="margin-left:4em;"&gt;position: results[0].geometry.location, &lt;/span&gt;&lt;br /&gt;
                   &lt;span style="margin-left:4em;"&gt;animation: google.maps.Animation.DROP, &lt;/span&gt;&lt;br /&gt;
                   &lt;span style="margin-left:4em;"&gt;icon: &lt;span style="color:maroon;"&gt;'http://maps.google.com/mapfiles/kml/pal3/icon18.png'&lt;/span&gt;,&lt;/span&gt;&lt;br /&gt;
                   &lt;span style="margin-left:4em;"&gt;shadow: &lt;span style="color:maroon;"&gt;'http://maps.google.com/mapfiles/kml/pal3/icon18s.png'&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:4em;"&gt;&lt;span style="color:green;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;}&lt;/span&gt;&lt;br /&gt;
}
&lt;/div&gt;
&lt;br /&gt;
A função &lt;b&gt;trataLocais&lt;/b&gt; reproduzida acima é o &lt;i&gt;callback&lt;/i&gt; passado para o Geocoder junto com a requisição do endereço a ser apresentado no mapa. No exemplo, a marcação é inserida no próprio endereço requisitado, razão pela qual foi usado o retorno da API &lt;b&gt;results[0].geometry.location&lt;/b&gt; como local para fixar a marcação.&lt;br /&gt;
&lt;br /&gt;
Dos parâmetros para criar o marcador, apenas 2 são obrigatórios : o &lt;b&gt;map&lt;/b&gt; (representando a instância de &lt;a href="https://developers.google.com/maps/documentation/javascript/reference?hl=pt-BR#Map"&gt;Map&lt;/a&gt; que gerencia a apresentação do mapa na página) e o &lt;b&gt;position&lt;/b&gt; (um par &lt;a href="https://developers.google.com/maps/documentation/javascript/reference?hl=pt-BR#LatLng"&gt;latitude/longitude&lt;/a&gt; onde o marcador deverá ser fixado). Os demais parâmetros são auxiliares, úteis para melhorar a apresentação. No exemplo, forneço outros 3 parâmetros : &lt;b&gt;animation&lt;/b&gt; (uma &lt;a href="https://developers.google.com/maps/documentation/javascript/reference?hl=pt-BR#Animation"&gt;animação&lt;/a&gt; dinâmica usada para cravar o marcador no mapa; o padrão é o marcador simplesmente aparecer), &lt;b&gt;icon&lt;/b&gt; (uma URL apontando a imagem que será usada como marcador; o padrão é &lt;img src="http://maps.google.com/mapfiles/ms/micons/red-dot.png" style='vertical-align:middle;border:0' /&gt;) e &lt;b&gt;shadow&lt;/b&gt; (URL com a imagem que representa uma sombra do marcador). Há uma lista com imagens padronizadas e suas respectivas sombras &lt;a href="https://sites.google.com/site/gmapsdevelopment/"&gt;neste link&lt;/a&gt; mas pode-se trabalhar com qualquer URL personalisada que se queira.&lt;br /&gt;
&lt;br /&gt;
O mapa abaixo usa esses conceitos pra incluir algumas marcações nas proximidades da sede da &lt;a href="http://www.abc71.com.br"&gt;ABC71&lt;/a&gt; em São Paulo:
&lt;br /&gt;
&lt;div style="border:1px solid silver;"&gt;&lt;center&gt;&lt;iframe width='99%' height='460px' frameborder='0' src='http://lgaf.webs.com/arqs/marcas.html'&gt;&lt;/iframe&gt;&lt;/center&gt;&lt;/div&gt;
&lt;br /&gt;
A API prevê ainda a possibilidade de se abrir uma janela para apresentar outros detalhes a respeito de um ponto no mapa. A flexibilidade desse tipo de recurso é grande já que é permitido incluir código HTML para formatar as informações que são apresentadas - embora isso não seja obrigatório.&lt;br /&gt;
&lt;br /&gt;
Do ponto de vista da programação, criar uma janela com informações adicionais sobre um ponto também é simples. Consiste em instanciar a classe &lt;a href="https://developers.google.com/maps/documentation/javascript/reference?hl=pt-BR#InfoWindow"&gt;google.maps.InfoWindow&lt;/a&gt;, providenciando um conteúdo para essa janela. Uma vez instanciada, podemos solicitar que a janela seja aberta num ponto específico do mapa. Complementando a função &lt;b&gt;trataLocais&lt;/b&gt; :&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 9pt; padding: 5px 10px 5px 5px; width: 98%;"&gt;
&lt;b&gt;function&lt;/b&gt; trataLocais (results, status){&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;b&gt;if&lt;/b&gt; (status == google.maps.GeocoderStatus.OK)&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;{&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:4em;"&gt;&lt;span style="color:green;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;

    &lt;span style="margin-left:2em;"&gt;google.maps.event.addListener(marker, &lt;span style="color:maroon;"&gt;'click'&lt;/span&gt;,&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:2.5em;"&gt;&lt;b&gt;function&lt;/b&gt; () {&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:3em;"&gt;&lt;b&gt;var&lt;/b&gt; infowindow = &lt;b&gt;new&lt;/b&gt; google.maps.InfoWindow(&lt;/span&gt;&lt;br /&gt;
          &lt;span style="margin-left:3em;"&gt;{&lt;/span&gt;&lt;br /&gt;
            &lt;span style="margin-left:3.5em;"&gt;content: &lt;span style="color:maroon;"&gt;'&amp;lt;div style="text-align:justify;"&gt;&amp;lt;b&gt;Ponto de Interesse&amp;lt;/b&gt;&amp;lt;br/&gt;&amp;lt;br/&gt;ABC71 Soluções em Informática.&amp;lt;/div&gt;'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
          &lt;span style="margin-left:3em;"&gt;});&lt;/span&gt;&lt;br /&gt;
        &lt;span style="margin-left:3em;"&gt;infowindow.open(map, marker);&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;/div&gt;
No código javascript do quadro anterior, a abertura da janela de informação é vinculada a um evento de "clique" no marcador. Isto é, ela só aparece se o usuário clicar no marcador em questão. Veja que o conteúdo (&lt;b&gt;content&lt;/b&gt;) da janela foi formatado com tags HTML, possibilitando adequar a apresentação ao propósito de sua aplicação. A função &lt;b&gt;open&lt;/b&gt; - que exibe a janela - aceita como parâmetros o mapa que estamos usando e o marcador que servirá de referência para a exibição da janela.&lt;br /&gt;
&lt;br /&gt;
No mapa que aparece nesse &lt;i&gt;post&lt;/i&gt;, os marcadores podem ser clicados, ação que  cria uma janela simples com outras informações sobre o ponto marcado.&lt;br /&gt;
&lt;br /&gt;
O arquivo HTML &lt;a href='http://lgaf.webs.com/arqs/marcas.html'&gt;encontrado neste endereço&lt;/a&gt; traz o exemplo completo mostrado aqui no post. Ele simula a recepção em formato XML de informações sobre locais que devem ser marcados no mapa. Para isso, o exemplo utiliza também recursos da biblioteca &lt;a href="http://jquery.com/"&gt;JQuery&lt;/a&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: 98%;"&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.br/2010/08/usando-versao-3-da-api-do-google-maps.html"&gt;Usando a versão 3 da API do Google Maps&lt;/a&gt;, &lt;a href="http://balaiotecnologico.blogspot.com.br/2012/01/informacoes-sobre-rotas-com-versao-3-da.html"&gt;Informações sobre rotas com a versão 3 da API do Google Maps&lt;/a&gt;
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/sLnU-FZWukM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/4955671161591147026/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/10/trabalhando-com-marcacoes-em-mapas-com.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4955671161591147026?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4955671161591147026?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/sLnU-FZWukM/trabalhando-com-marcacoes-em-mapas-com.html" title="Trabalhando com marcações em mapas com a versão 3 da API do Google Maps" /><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/10/trabalhando-com-marcacoes-em-mapas-com.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8EQno5eCp7ImA9WhJbF0o.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-4108507852823576073</id><published>2012-09-27T17:42:00.001-03:00</published><updated>2012-09-27T17:46:43.420-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-09-27T17:46:43.420-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Notícias" /><title>ABC71 busca parceiros de tecnologia para comercializar ERP na nuvem</title><content type="html">A &lt;a href=""&gt;ABC71&lt;/a&gt;, empresa de desenvolvimento de softwares de gestão empresarial, acaba de lançar uma versão em &lt;i&gt;cloud computing&lt;/i&gt; de seu ERP Omega. A solução - batizada de &lt;a href="http://www.erppronto.com.br/"&gt;ERP Pronto&lt;/a&gt; - funciona na internet, dispensando seus clientes de preocupações com infraestrutura de hardware e software para a instalação. Basicamente, é preciso apenas ter um navegador compatível e a disponibilidade de uma conexão com a internet. Ficam a cargo da fornecedora do software os demais aspectos, tais como a preparação de um servidor, configurações gerais, controles de segurança, instalação e gerenciamento do banco de dados (incluindo backup sistemático dos dados lançados pelos usuários), etc.&lt;br/&gt;
&lt;br/&gt;
A empresa preparou o site &lt;a href="http://www.erppronto.com.br/"&gt;ERP Pronto&lt;/a&gt; para apresentar os principais benefícios do novo produto. Nele é possível encontrar detalhes sobre as diversas operações que o software é capaz de gerenciar, cobrindo  faturamento, finanças, estoques, NF-e Federal, SPED, entre outros. O site também aborda dúvidas comumente levantadas, além de apresentar vídeos demonstrando algumas das operações do sistema.&lt;br/&gt;
&lt;br/&gt;
Agora, a &lt;a href="http://www.abc71.com.br/"&gt;ABC71&lt;/a&gt; está buscando firmar parcerias com novos canais de venda para levar a solução aos potenciais clientes, mesmo aqueles que se encontram longe dos chamados "grandes centros". O texto abaixo foi preparado com o objetivo de auxiliar nessa busca, dando outras características do produto, o modo de aquisição e os preços praticados para um cenário típico de pequenas empresas, que é o foco do produto.
&lt;br/&gt;
&lt;div style="border:1px solid silver;padding: 5px 10px 1em 5px;width:98%;background-color:#e9e9fb"&gt;
&lt;b&gt;ABC71 busca parceiros de tecnologia para comercializar o ERP Pronto&lt;/b&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;i&gt;Consultorias especializadas em TI podem representar a solução e aumentar a rentabilidade&lt;/i&gt;&lt;br/&gt;
&lt;br/&gt;
A ABC71 – empresa nacional especializada no desenvolvimento de softwares de gestão empresarial – está investindo em sua rede de canais para ampliar as vendas do ERP Pronto.&lt;br/&gt;
&lt;br/&gt;
O ERP PRONTO é um sistema de gestão completo baseado em Cloud Computing e voltado para pequenas e médias empresas. O software pode ser utilizado pelos  mais variados segmentos da economia e está preparado para atender às principais necessidades de gestão dos negócios das PMEs (pequenas e médias empresas), atende às áreas comercial, financeira, estoque, contábil e fiscal, incluindo o SPED (Sistema Público de Escrituração Digital) e a NF-e (Nota Fiscal Eletrônica).&lt;br/&gt;
&lt;br/&gt;
O ERP Pronto é comercializado na modalidade SaaS (software como serviço), dispensando a contratação de licença de uso e investimentos em infraestrutura de TI. Funciona como uma conta telefônica onde só se paga pelo o que se usa. O pacote inicial do ERP Pronto está disponível a partir de R$ 510,00 por mês para que até três usuários possam utilizá-la simultaneamente.&lt;br/&gt;
&lt;br/&gt;
Para chegar às PMEs, pulverizadas pelo país, e atingir a meta de vendas em torno de três mil clientes até 2015, a ABC71 procura empresas especializadas em TI que queiram aumentar a rentabilidade.&lt;br/&gt;
&lt;br/&gt;
Entre os canais já credenciados estão: TCi Sistemas, RM Benasse, KLX, Freestore,  Publisoft, Lesoft e Viera e Souza Assessoria Contábil.&lt;br/&gt;
&lt;br/&gt;
Entre clientes que já utilizam a solução destacam-se: a Fazenda Novo Horizonte, produtora de grãos do Mato Grosso; a Foccus, distribuidora de ferramentas de corte; e a Invento, importadora de artigos de decoração.&lt;br/&gt;
&lt;br/&gt;
Para se tornar parceiro da ABC71 basta entrar em contato pelo telefone (11) 2179-3190 ou pelo e-mail &lt;a href='mailto&amp;#58;er%&amp;#55;0p&amp;#114;%6F&amp;#110;t&amp;#111;&amp;#64;%65rppr&amp;#111;%6&amp;#69;t%&amp;#54;&amp;#70;&amp;#46;c%6&amp;#70;%&amp;#54;D&amp;#46;b&amp;#114;'&gt;e&amp;#114;ppronto&amp;#64;&amp;#101;rp&amp;#112;ro&amp;#110;to&amp;#46;c&amp;#111;m&amp;#46;br&lt;/a&gt;.
&lt;/div&gt;
&lt;br/&gt;
&lt;br/&gt;

&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 98%;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.erppronto.com.br/"&gt;Site do ERP Pronto&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/c_u6R-keIrI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/4108507852823576073/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/09/abc71-busca-parceiros-de-tecnologia.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4108507852823576073?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4108507852823576073?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/c_u6R-keIrI/abc71-busca-parceiros-de-tecnologia.html" title="ABC71 busca parceiros de tecnologia para comercializar ERP na nuvem" /><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/09/abc71-busca-parceiros-de-tecnologia.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4BQns_eSp7ImA9WhJVEko.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-7251512372803724958</id><published>2012-08-28T19:03:00.000-03:00</published><updated>2012-08-29T17:09:13.541-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-08-29T17:09:13.541-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><title>Avaliando a performance de queries no SQL Server</title><content type="html">Muito da aceitação de um programa de computador por seus usuários pode ser atribuído à praticidade de sua interface gráfica e até mesmo a aparência que ela tenha. No entanto, a aceitação rapidamente se reverte se o programa apresentar problemas de performance. Com bastante frequência, a degradação de performance num programa está associado a queries mal projetadas submetidas a um banco de dados pelo programa.&lt;br/&gt;
&lt;br/&gt;
Quando digo "mal projetada", eu me refiro a certas características das queries adotadas pelo programa, tais como não utilizar os índices apropriados das tabelas ou manter tabelas sem índice, fazer ligações ineficientes com outras tabelas, trazer registros demais que não serão utilizados ou ainda executar uma mesma query mais vezes do que o necessário.&lt;br/&gt;
&lt;br/&gt;
A partir da sua versão 2005, o SQL Server mantém em tabelas virtuais uma série de informações a respeito das queries que foram executadas pelo banco de dados. Essas informações ficam armazenadas em memória e são descartadas quando o serviço do banco é desligado. No entanto, são informações bastante úteis para auxiliar na localização de problemas de performance gerados pelas queries mal planejadas.&lt;br/&gt;
&lt;br/&gt;
Um usuário que queira consultar as informações disponibilizadas nessas tabelas virutais precisa ter atribuida a permissão &lt;a href="http://msdn.microsoft.com/en-us/library/ms186717.aspx"&gt;VIEW SERVER STATE&lt;/a&gt;. Isso pode ser feito visualmente, através das propriedades do servidor no &lt;b&gt;Management Studio&lt;/b&gt; ou via comando SQL, utilizando-se o &lt;a href="http://msdn.microsoft.com/en-us/library/ms186717.aspx"&gt;GRANT&lt;/a&gt;.&lt;br/&gt;
&lt;br/&gt;
Uma das &lt;i&gt;views&lt;/i&gt; mais interessantes nesse contexto é a &lt;a href="http://msdn.microsoft.com/en-us/library/ms189741.aspx"&gt;sys.dm_exec_query_stats&lt;/a&gt;, responsável pelas estatísticas de execução de queries. Ela traz, dentre outras informações, a quantidade de vezes que uma query foi executada, o tempo gasto nessas execuções, quantas linhas foram retornadas, a quantidade de leituras e gravações feitas durante a execução. Ela dá acesso também ao texto da query e ao plano de execução montado pelo SQL. O exemplo no quadro abaixo lista em ordem decrescente as queries que mais consumiram CPU:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;

&lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; qs.total_worker_time / qs.execution_count &lt;span style="color:blue;"&gt;As&lt;/span&gt; &lt;span style="color:red;"&gt;'Uso Médio da CPU'&lt;/span&gt;,&lt;br/&gt;
       &lt;span style="margin-left:4em;"&gt;qs.total_worker_time &lt;span style="color:blue;"&gt;As&lt;/span&gt; &lt;span style="color:red;"&gt;'Uso Total da CPU'&lt;/span&gt;,&lt;/span&gt;&lt;br/&gt;
       &lt;span style="margin-left:4em;"&gt;qs.execution_count &lt;span style="color:blue;"&gt;As&lt;/span&gt; &lt;span style="color:red;"&gt;'Qtde de Execuções'&lt;/span&gt;,&lt;/span&gt;&lt;br/&gt;
       &lt;span style="margin-left:4em;"&gt;qt.text &lt;span style="color:blue;"&gt;As&lt;/span&gt; &lt;span style="color:red;"&gt;'Query'&lt;/span&gt;,&lt;/span&gt;&lt;br/&gt;
       &lt;span style="margin-left:4em;"&gt;&lt;span style="color:fuchsia;"&gt;DB_NAME&lt;/span&gt;(qt.dbid) &lt;span style="color:blue;"&gt;As&lt;/span&gt; &lt;span style="color:red;"&gt;'Nome do Banco'&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:blue;"&gt;FROM&lt;/span&gt; &lt;span style="color:green;"&gt;sys.dm_exec_query_stats&lt;/span&gt; qs&lt;br/&gt;
&lt;span style="color:gray;"&gt;CROSS APPLY&lt;/span&gt; &lt;span style="color:green;"&gt;sys.dm_exec_sql_text&lt;/span&gt;(qs.sql_handle) &lt;span style="color:blue;"&gt;As&lt;/span&gt; qt&lt;br/&gt;
&lt;span style="color:blue;"&gt;ORDER BY&lt;/span&gt; 1 &lt;span style="color:blue;"&gt;DESC&lt;/span&gt;

&lt;/div&gt;
&lt;br/&gt;
Veja que a quantidade de vezes que uma query executou não é determinante para que ela tenha consumido mais CPU na média. Consulta semelhante pode ser montada para obter as queries que mais foram executadas (pra avaliar se todas as execuções são mesmo necessárias) ou a quantidade de linhas retornada (pra avaliar se não é possível restringir mais os registros, acrescentando outras comparações à cláusula WHERE). Os tempos listados estão em microsegundos; para convertê-lo em segundos, divida o valor por 1 milhão. É possível ainda levantar a quantidade de gravações feitas por uma query e avaliar se tantas alterações são mesmo necessárias&lt;br/&gt;
&lt;br/&gt;
Outro detalhe a ser destacado no quadro anterior é que o texto da query não está na mesma &lt;i&gt;view&lt;/i&gt;. Para obtê-lo, é necessário pegar o código contido no campo &lt;b&gt;sql_handle&lt;/b&gt; e repassá-lo à função &lt;a href="http://msdn.microsoft.com/en-us/library/ms181929.aspx"&gt;sys.dm_exec_sql_text&lt;/a&gt;.&lt;br/&gt;
&lt;br/&gt;
Outra &lt;i&gt;view&lt;/i&gt; bastante útil é a &lt;a href="http://msdn.microsoft.com/en-us/library/ms345434.aspx"&gt;sys.dm_db_missing_index_details&lt;/a&gt;. Como o próprio nome diz, ela armazena detalhes sobre o uso de queries cujas execuções não estão otimizadas por que não foi possível encontrar na tabela um índice apropriado. Baseado nas informações retornadas por ela, podemos introduzir novos índices e melhorar a performance das consultas envolvendo as tabelas em questão. O quadro abaixo mostra um exemplo de consulta a essa &lt;i&gt;view&lt;/i&gt;, listando as colunas encontradas na cláusula WHERE da query com problema, a tabela envolvida e a quantidade de vezes que a query problemática foi disparada:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;

&lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; equality_columns, inequality_columns, statement, &lt;span style="color:fuchsia;"&gt;count&lt;/span&gt;(*) &lt;span style="color:blue;"&gt;As&lt;/span&gt; &lt;span style="color:red;"&gt;'Qtde Exec'&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:blue;"&gt;FROM&lt;/span&gt; &lt;span style="color:green;"&gt;sys.dm_db_missing_index_details&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;DB_NAME&lt;/span&gt;(database_id) = &lt;span style="color:red;"&gt;'ABC71DS94'&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:blue;"&gt;GROUP BY&lt;/span&gt; equality_columns, inequality_columns, statement&lt;br/&gt;
&lt;span style="color:blue;"&gt;ORDER BY&lt;/span&gt; statement

&lt;/div&gt;
&lt;br/&gt;
A coluna &lt;i&gt;statement&lt;/i&gt; traz o nome da tabela que está sem índice apropriado. A &lt;i&gt;equality_columns&lt;/i&gt; lista as colunas usadas em comparações de igualdade no WHERE - algo como NOME_DO_CAMPO = VALOR. Em &lt;i&gt;inequality_columns&lt;/i&gt; aparecem as colunas usadas em outros tipos de comparação do WHERE. Veja que é possível filtrar as informações por banco de dados instalado, permitindo avaliar os índices para cada banco isoladamente.&lt;br/&gt;
&lt;br/&gt;
A lista de informações que podemos obter no &lt;b&gt;DMV&lt;/b&gt; (Dynamic Management Views) inclui ainda os motivos de espera para uma query ser executada, dados de espelhamento e replicação, tamanho do banco de dados e suas partições, etc. A lista completa das informações disponíveis por esse meio pode ser encontrada em &lt;a href="http://msdn.microsoft.com/en-us/library/ms188754.aspx"&gt;Dynamic Management Views and Functions&lt;/a&gt; no MSDN online.&lt;br/&gt;
&lt;br/&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 98%;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/magazine/cc135978.aspx"&gt;Uncover Hidden Data to Optimize Application Performance&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/ms188754.aspx"&gt;Dynamic Management Views and Functions (Transact-SQL)&lt;/a&gt; 
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/xtZjcZo6wqE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/7251512372803724958/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/08/avaliando-performance-de-queries-no-sql.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/7251512372803724958?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/7251512372803724958?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/xtZjcZo6wqE/avaliando-performance-de-queries-no-sql.html" title="Avaliando a performance de queries no SQL Server" /><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/08/avaliando-performance-de-queries-no-sql.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMCQXk_cCp7ImA9WhJXE0U.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-1964777959837659207</id><published>2012-08-01T18:48:00.002-03:00</published><updated>2012-08-07T22:14:20.748-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-08-07T22:14:20.748-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Notícias" /><title>Aplicações em Java ainda valem a pena ?</title><content type="html">Depois de protagonizar o primeiro grande ataque a sistemas Mac OS no início deste ano, quando uma &lt;a href="http://www.infoworld.com/d/security/fast-growing-flashback-botnet-includes-over-600000-macs-190268"&gt;vulnerabilidade crítica permitiu a infecção de mais de 600 mil Macs&lt;/a&gt;, o Java volta a ficar na berlinda. Desta vez, um pesquisador do Centro de Proteção a &lt;i&gt;Malwares&lt;/i&gt; da Microsoft &lt;a href="http://blogs.technet.com/b/mmpc/archive/2012/07/25/how-to-protect-yourself-from-java-based-malware.aspx"&gt;publicou um artigo&lt;/a&gt; intitulado "Como se proteger de &lt;i&gt;malwares&lt;/i&gt; baseados em Java" onde aconselha os usuários a trabalharem sempre com as releases mais recentes da Virtual Machine e, quando for possível, que a deixem desativada para proteger seus sistemas. No caso de não utilizar aplicações Java, a recomendação é de remover completamente o JRE.&lt;br/&gt;
&lt;br/&gt;
Na mesma linha, só que um pouco mais radical, &lt;a href="http://podcasts.infoworld.com/author-bios/woody-leonhard?_kip_ipx=1367494980-1343848860"&gt;Woody Leonhard&lt;/a&gt; defendeu em &lt;a href="http://podcasts.infoworld.com/t/java-programming/microsoft-hits-java-where-it-hurts-198936?_kip_ipx=509354338-1343844128"&gt;artigo publicado na InfoWorld.com&lt;/a&gt; que a melhor opção é mesmo abandonar a tecnologia, substituindo-a o mais rápido possível. O texto abaixo é uma tradução do artigo onde ele expressa sua opinião:
&lt;br/&gt;
&lt;div style="border:1px solid silver;padding: 5px 10px 1em 5px;width:98%;background-color:#e9e9fb"&gt;
Quatro meses atrás, eu critiquei o Java -- ou, mais apropriadamente, o uso do Java Runtime Environment (JRE) -- no post &lt;a href="http://www.infoworld.com/t/java-programming/its-time-run-java-out-of-town-190525"&gt;"É hora de expulsar o Java da cidade".&lt;/a&gt; Quatro meses depois, a situação não melhorou um milímetro. De fato, ela piorou, se é que piorar é uma opção para o vetor de infecção número 1 em PCs e Macs.&lt;br/&gt;
&lt;br/&gt;
Na semana passada, o pesquisador Matt Oh do Centro de Proteção Contra Malware da Microsoft publicou um artigo no TechNet sobre como se proteger contra os malwares baseados em Java. Para enfatizar o ponto, ele &lt;a href="http://www.blackhat.com/usa/bh-us-12-briefings.html#Oh"&gt;deu uma palestra no Black Hat 2012&lt;/a&gt; no mesmo dia, dizendo que a situação com o Java está se deteriorando -- e não somente no Windows.&lt;br/&gt;
&lt;br/&gt;
"Estamos vendo cada vez mais vulnerabilidades no Java sendo exploradas ... e uma vulnerabilidade no Java pode às vezes ser explorada em múltiplas plataformas," disse o pesquisador.&lt;br/&gt;
&lt;br/&gt;
A principal preocupação para Oh são as brechas no &lt;i&gt;sandbox&lt;/i&gt;. Se autores de malware conseguirem acesso fora dos limites do &lt;i&gt;sandbox&lt;/i&gt; de execução do Java/JRE, eles podem tomar o controle de um sistema, não importando se ele está em Windows, Mac OS X ou Unix. Uma única vulnerabilidade no Java -- como a brecha de segurança "confusão de tipos" CVE-2012-1723, descoberta há apenas algumas semanas, ou a velha CVE-2012-0507, que levou à rede de robôs Flashback, com mais de 600 mil Macs infectados neste ano -- pode resultar numa exploração bem sucedida que burle as defesas do sistema operacional simplesmente por ele estar executando o Java.&lt;br/&gt;
&lt;br/&gt;
"A confusão de tipos é uma vulnerabilidade que ocorre quando a verificação de segurança de tipos feita pelo JRE falha quando são fornecidos tipos diferentes do esperado para uma instrução. Alguns dos tipos do Java, como o ClassLoader, podem ser alvos desse ataque. Se a segurança de tipos dessas classes é quebrada, pode-se ter acesso a alguns métodos que não deveriam estar acessíveis a processos externos à própria classe. Esta violação na segurança de tipos leva, em última análise, ao comprometimento do &lt;i&gt;sandbox&lt;/i&gt; do Java," disse Oh.&lt;br/&gt;
&lt;br/&gt;
Para piorar, o fato do programa ser escrito em Java torna mais fácil ocultar a violação usando ferramentas disponíveis e bem documentadas da própria linguagem para embaralhar o código.&lt;br/&gt;
&lt;br/&gt;
A recomendação de Oh é que você esteja sempre com o JRE mais atualizado e que o desabilite sempre que isso for possível. Se você não usa aplicações Java, então simplesmente desinstale o JRE.&lt;br/&gt;
&lt;br/&gt;
Minha recomendação para TI é um pouco mais proativa: é hora de tirar seus usuários da esteira do JRE/JVM. Se você tem um produto que requer o JRE, migre-o. Se seus planos de negócio incluem aplicações Java, altere seus planos. Se você ou sua equipe de desenvolvimento programam aplicações &lt;i&gt;client&lt;/i&gt; Java, é hora de diversificar suas habilidades.&lt;br/&gt;
&lt;br/&gt;
Ao continuar usando Java, você está colocando sua empresa e seus clientes em risco.
&lt;/div&gt;
&lt;br/&gt;
Embora eu entenda as razões dele e concorde com sua argumentação - que é irretocável, considerando-se a agudez da crise atual - acredito que ainda seja cedo pra tomar uma decisão tal radical quanto simplesmente abdicar das aplicações feitas em Java. Digo isso porque me parece que a Oracle vem mantendo um plano razoavelmente consistente de atualizações da linguagem. Veja, por exemplo, o &lt;a href="http://images.infoworld.com/d/application-development/project-jigsaw-delayed-until-java-9-198007?source=rss_application_development"&gt;projeto JigSaw&lt;/a&gt; e os planos para &lt;a href="http://images.infoworld.com/d/application-development/oracle-keeps-hope-alive-javafx-java-ios-197686?source=rss_application_development"&gt;levar Java para o iOS&lt;/a&gt;. &lt;br/&gt;
&lt;br/&gt;
Apesar de às vezes a Oracle pecar na velocidade das correções, creio que o ideal é seguir as recomendações de Matt Oh: manter sempre atualizado o JRE e eventualmente desligá-lo (se possível) quando brechas críticas forem detectadas e a correção demorar a sair.
&lt;br/&gt;
&lt;br/&gt;
&lt;div style="border:1px solid silver;padding: 10px 5px 10px 5px;width: 98%;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://podcasts.infoworld.com/t/java-programming/microsoft-hits-java-where-it-hurts-198936?_kip_ipx=509354338-1343844128"&gt;Microsoft hits Java where it hurts&lt;/a&gt;,
&lt;a href="http://blogs.technet.com/b/mmpc/archive/2012/07/25/how-to-protect-yourself-from-java-based-malware.aspx"&gt;How to protect yourself from Java-based malware&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/AV53RG3Le7o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/1964777959837659207/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/08/aplicacoes-em-java-ainda-valem-pena.html#comment-form" title="4 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/1964777959837659207?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/1964777959837659207?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/AV53RG3Le7o/aplicacoes-em-java-ainda-valem-pena.html" title="Aplicações em Java ainda valem a pena ?" /><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/2012/08/aplicacoes-em-java-ainda-valem-pena.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MMR3Y_eip7ImA9WhBbEUU.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-495592908384683706</id><published>2012-07-18T17:35:00.000-03:00</published><updated>2013-05-10T09:38:06.842-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-10T09:38:06.842-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="CAPICOM" /><category scheme="http://www.blogger.com/atom/ns#" term="XML" /><title>Assinando documentos XML com CAPICOM e Delphi</title><content type="html">A Microsoft disponibiliza para o Windows uma biblioteca com tecnologia &lt;a href="http://pt.wikipedia.org/wiki/Component_Object_Model"&gt;COM&lt;/a&gt; para tratar a criação e manipulação de arquivos XML. A biblioteca, chamada &lt;a href="http://en.wikipedia.org/wiki/MSXML"&gt;MSXML&lt;/a&gt;, está atualmente na versão 6 e suporta também transformações XSLT e validação através de esquemas XSD. Em apenas uma das versões (o MSXML5), foram incluídos ainda recursos para fazer assinatura digital de XMLs. &lt;br/&gt;
&lt;br/&gt;
A versão 5 foi distribuída exclusivamente com o Microsoft Office para que os desenvolvedores dessa plataforma pudessem assinar XMLs. No entanto, uma busca na internet revela que a biblioteca é amplamente utilizada fora desse contexto.&lt;br/&gt;
&lt;br/&gt;
Isto é uma boa notícia para quem usa Delphi (ou outra linguagem que suporte COM) pois o MSXML5, em associação com o CAPICOM, facilita bastante a tarefa de assinar XMLs. Neste post eu mostro como realizar este processo, considerando que você já tem montado o XML que quer assinar. O quadro abaixo mostra parte do XML de uma Nota Fiscal que vou usar como exemplo:&lt;br/&gt;
&lt;div style="font-size:8pt;font-family:Courier New;border:1px solid silver;padding:5px 10px 1em 5px;width: 98%;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" ?&amp;gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left: 0;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;enviNFe versao&lt;/span&gt;&lt;span style="color:blue;"&gt;="&lt;/span&gt;&lt;b&gt;&lt;span&gt;2.00&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;"&lt;/span&gt;&lt;span style="color:red;"&gt; xmlns&lt;/span&gt;&lt;span style="color:blue;"&gt;="&lt;/span&gt;&lt;b&gt;&lt;span style="color:red;"&gt;http://www.portalfiscal.inf.br/nfe&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;"&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;idLote&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;71&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;idLote&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;NFe&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;infNFe Id&lt;/span&gt;&lt;span style="color:blue;"&gt;="&lt;/span&gt;&lt;span style="color:red;"&gt;&lt;b&gt;NFe3508059978&lt;/b&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;"&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt; versao&lt;/span&gt;&lt;span style="color:blue;"&gt;="&lt;/span&gt;&lt;b&gt;&lt;span style="color:red;"&gt;2.00&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;"&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;cUF&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;35&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;cUF&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;cNF&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;518005127&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;cNF&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;natOp&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;Venda a vista&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;natOp&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;mod&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;55&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;mod&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;serie&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;1&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;serie&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;dEmi&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;2012-05-06&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;dEmi&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;tpAmb&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;2&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;tpAmb&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;infNFe&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;NFe&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;enviNFe&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
A primeira providência é importar os fontes dos ActiveX MSXML5 e CAPICOM para podermos utilizá-los no projeto Delphi. Há um resumo de como fazer essa importação &lt;a href="http://balaiotecnologico.blogspot.com.br/2009/04/trabalhando-com-o-certificate-store-em.html"&gt;neste endereço&lt;/a&gt;; para o MSXML5, a descrição da Type Library é &lt;b&gt;Microsoft XML, v5.0&lt;/b&gt;. Ambos os fontes gerados devem ser incluídos na cláusula &lt;b&gt;uses&lt;/b&gt; da &lt;i&gt;unit&lt;/i&gt; que for fazer a assinatura.&lt;br /&gt;
&lt;br /&gt;
Obviamente, vamos precisar de um certificado digital para realizar a assinatura. Utilizando o CAPICOM, podemos &lt;a href="http://balaiotecnologico.blogspot.com.br/2009/07/acessando-o-certificate-store-do.html"&gt;acessar o Certificate Store do Windows&lt;/a&gt; e localizar um apropriado, que tenha sido gerado para sua empresa. No entanto, as interfaces disponíveis no MSXML5 exigem que você informe um Certificate Store com o certificado que será utilizado, bem como sua cadeia de validação, se for necessário. Este passo extra é mostrado no quadro abaixo.&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;var&lt;/span&gt; store : IStore3;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;cert : TCertificate;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;lKey : IPrivateKey;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;begin&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;cert := getCert;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lKey := Cert.PrivateKey;&lt;/span&gt;&lt;br /&gt;
  &lt;br /&gt;
  &lt;span style="margin-left:1em;color:green;"&gt;{ Monta um Store em memória com o Certificado obtido antes }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;store := CoStore.Create;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;store.Open(CAPICOM_CURRENT_USER_STORE, &lt;span style="color:maroon;"&gt;'My'&lt;/span&gt;, CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;store.Add(cert.DefaultInterface);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;color:green;"&gt;{ ... }&lt;/span&gt;
&lt;/div&gt;
&lt;br /&gt;
A função &lt;b&gt;GetCert&lt;/b&gt; utilizada acima é minha e segue as instruções descritas no post sobre &lt;a href="http://balaiotecnologico.blogspot.com.br/2009/04/trabalhando-com-o-certificate-store-em.html"&gt;acesso ao Certificate Store com CAPICOM&lt;/a&gt;. De resto, o código apenas cria um Store em memória e adiciona a ele o certificado encontrado. O trecho também salva a chave privada deste certificado, informação que será usada mais adiante para gerar a assinatura em si.&lt;br /&gt;
&lt;br /&gt;
A seguir, precisamos preparar o XML do exemplo para receber a assinatura. É que a interface do MSXML5 responsável por essa etapa se baseia num nó &lt;b&gt;Signature&lt;/b&gt; do XML. Esse nó descreve as transformações pelas quais o XML deve ser submetido antes de ser de fato assinado. O nó &lt;b&gt;Signature&lt;/b&gt; deve ser criado como mostrado abaixo:
&lt;div style="font-size:8pt;font-family:Courier New;border:1px solid silver;padding:5px 10px 1em 5px;width: 98%;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" ?&amp;gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left: 0;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;enviNFe versao&lt;/span&gt;&lt;span style="color:blue;"&gt;="&lt;/span&gt;&lt;b&gt;&lt;span&gt;2.00&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;"&lt;/span&gt;&lt;span style="color:red;"&gt; xmlns&lt;/span&gt;&lt;span style="color:blue;"&gt;="&lt;/span&gt;&lt;b&gt;&lt;span style="color:red;"&gt;http://www.portalfiscal.inf.br/nfe&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;"&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;idLote&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;71&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;idLote&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;NFe&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;Signature&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;SignedInfo&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="margin-left: 4em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;CanonicalizationMethod Algorithm=&lt;/span&gt;&lt;span style="color:red;"&gt;&lt;b&gt;"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"&lt;/b&gt;&lt;/span&gt;/&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;SignatureMethod Algorithm&lt;/span&gt;=&lt;span style="color:red;"&gt;&lt;b&gt;"http://www.w3.org/2000/09/xmldsig#rsa-sha1"&lt;/b&gt;&lt;/span&gt;/&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;Reference URI&lt;/span&gt;=&lt;span style="color:red;"&gt;"&lt;b&gt;#NFe3508059978"&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 5em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;Transforms&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 6em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;Transform Algorithm&lt;/span&gt;=&lt;span style="color:red;"&gt;&lt;b&gt;"http://www.w3.org/2000/09/xmldsig#enveloped-signature"&lt;/b&gt;&lt;/span&gt;/&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 6em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;Transform Algorithm&lt;/span&gt;=&lt;span style="color:red;"&gt;&lt;b&gt;"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"&lt;/b&gt;&lt;/span&gt;/&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 5em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:rgb(153,0,0);"&gt;Transforms&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 5em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;DigestMethod Algorithm&lt;/span&gt;=&lt;span style="color:red;"&gt;&lt;b&gt;"http://www.w3.org/2000/09/xmldsig#sha1"&lt;/b&gt;&lt;/span&gt;/&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 5em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;DigestValue&lt;/span&gt;&gt;&amp;lt;/&lt;span style="color:rgb(153,0,0);"&gt;DigestValue&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:rgb(153,0,0);"&gt;Reference&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:rgb(153,0,0);"&gt;SignedInfo&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;SignatureValue&lt;/span&gt;&gt;&amp;lt;&lt;span style="color:rgb(153,0,0);"&gt;SignatureValue&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:rgb(153,0,0);"&gt;Signature&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 1em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;NFe&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;enviNFe&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
Como podemos ver acima, o nó também deixa reservado um local para receber o &lt;b&gt;hash&lt;/b&gt; (&lt;b&gt;DigestValue&lt;/b&gt;) e outro para a própria assinatura (&lt;b&gt;SignatureValue&lt;/b&gt;), que serão preenchidos automaticamente. A única parte variável do bloco preparado acima é o atributo &lt;b&gt;URI&lt;/b&gt; da &lt;i&gt;tag&lt;/i&gt; &lt;b&gt;Reference&lt;/b&gt;, valor que reflete a identificação da Nota Fiscal contida no XML. Ou seja, deve-se montar o valor desse atributo a partir do valor do atributo &lt;b&gt;Id&lt;/b&gt; da &lt;i&gt;tag&lt;/i&gt; &lt;b&gt;infNFe&lt;/b&gt;, precedendo este valor com o sinal &lt;b&gt;#&lt;/b&gt;. Como o próprio nome diz, essa parte do XML faz referência ao nó (e seus filhos) que será resguardado pela assinatura digital.&lt;br /&gt;
&lt;br /&gt;
Uma vez que o XML está preparado, podemos partir para a assinatura propriamente dita, o que é conseguido através da interface &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms756071%28v=vs.85%29.aspx"&gt;IXMLDigitalSignature&lt;/a&gt; do MSXML5. Então, precisamos criar uma instância dela e lhe fornecedor os dados para a assinatura:&lt;br/&gt;
&lt;div style="font-size:8pt;font-family:Courier New;border:1px solid silver;padding:5px 10px 1em 5px;width: 98%;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;var&lt;/span&gt; &lt;span style="color:green;"&gt;{...}&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;xmlDoc: IXmlDomDocument3;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;noSignature : IXMLDOMElement;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;xmlSign : IXMLDigitalSignature;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;xmlDsigKey: IXMLDSigKey;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;begin&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;color:green;"&gt;{...}&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;color:green;"&gt;{ Monta o XML e prepara a tag Signature }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;xmlDoc := PreparaXML ();&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;noSignature := EncontraNodeSignature (xmlDoc);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;if&lt;/span&gt; (noSignature &lt;&gt; &lt;span style="font-weight:bold;color:navy;"&gt;Nil&lt;/span&gt;) &lt;span style="font-weight:bold;color:navy;"&gt;then begin&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:2em;"&gt;xmlSign := CoMXDigitalSignature50.Create;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:2em;"&gt;xmlSign.signature := noSignature;&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:2em;"&gt;xmlSign.store := store;&lt;/span&gt;&lt;br /&gt;
    &lt;br /&gt;
      &lt;span style="margin-left:2em;color:green;"&gt;{ Monta a chave com o tipo exigido pelo método Sign }&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:2em;"&gt;xmlDsigKey := xmlSign.createKeyFromCSP(lKey.ProviderType, lKey.ProviderName, lKey.ContainerName, &lt;span style="color:blue;"&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:2em;color:green;"&gt;{ Assina o XML }&lt;/span&gt;&lt;br /&gt;
      &lt;span style="margin-left:2em;"&gt;xmlSign.sign(xmlDsigKey, NOKEYINFO);&lt;/span&gt;&lt;br /&gt;
     &lt;span style="margin-left:2em;color:green;"&gt;{...}&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
&lt;br /&gt;
Como podemos ver no trecho de código acima, o &lt;b&gt;IXMLDigitalSignature&lt;/b&gt; precisa que indiquemos qual é o nó &lt;b&gt;Signature&lt;/b&gt; do nosso &lt;b&gt;XmlDomDocument&lt;/b&gt; e o &lt;i&gt;Certificate Store&lt;/i&gt; que construímos no início do post. Agora, temos que chamar o método &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms755717%28v=vs.85%29.aspx"&gt;sign&lt;/a&gt; para completar o serviço. Para funcionar, ele precisa de algumas informações baseadas na chave privada do certificado. No exemplo acima, utilizei a chave recuperada a partir do certificado para criar uma instância da interface &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms753796%28v=vs.85%29.aspx"&gt;IXMLDSigKey&lt;/a&gt; contendo as informações necessárias.&lt;br /&gt;
&lt;br /&gt;
O segundo parâmetro da função &lt;b&gt;sign&lt;/b&gt; determina como os dados da chave serão incluídos na estrutura do XML. No exemplo, usei o valor &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms757002%28v=vs.85%29.aspx"&gt;NOKEYINFO&lt;/a&gt; para que tais dados não sejam incluídos automaticamente.&lt;br /&gt;
&lt;br /&gt;
Após chamar a função &lt;b&gt;sign&lt;/b&gt;, as tags que deixamos reservadas no nó &lt;b&gt;Signature&lt;/b&gt; são automaticamente calculadas e preenchidas. Finalizando, para que o XML fique no padrão exigido para Notas Fiscais pela Receita Federal, só falta incluir um nó com os dados do certificado usado para assinar. Mostrei como fazer isso no post &lt;a href="http://balaiotecnologico.blogspot.com.br/2012/05/preparando-o-certificado-digital-para.html"&gt;Certificado Digital para inclusão no XML com CAPICOM e Delphi&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://msdn.microsoft.com/en-us/library/windows/desktop/ms756025%28v=vs.85%29.aspx"&gt;XML Digital Signatures Reference&lt;/a&gt;,
&lt;a href="http://balaiotecnologico.blogspot.com.br/2012/05/preparando-o-certificado-digital-para.html"&gt;Preparando o Certificado Digital para inclusão no XML com CAPICOM e Delphi&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/waGLFajzXRY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/495592908384683706/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/07/assinando-documentos-xml-com-capicom-e.html#comment-form" title="23 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/495592908384683706?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/495592908384683706?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/waGLFajzXRY/assinando-documentos-xml-com-capicom-e.html" title="Assinando documentos XML com CAPICOM e 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>23</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2012/07/assinando-documentos-xml-com-capicom-e.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAMR3g9fyp7ImA9WhJRFkk.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-6778289413495397684</id><published>2012-06-22T19:23:00.001-03:00</published><updated>2012-07-18T17:36:26.667-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-18T17:36:26.667-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><title>Trabalhando com informações sobres tipos no Delphi em tempo de execução - parte II</title><content type="html">A extensão do mecanismo de &lt;b&gt;RTTI&lt;/b&gt; (Run Time Type Information) introduzida no Delphi 2010 - e que eu citei &lt;a href="http://balaiotecnologico.blogspot.com.br/2012/06/trabalhando-com-informacoes-sobres.html"&gt;no meu último post&lt;/a&gt; - abre novas possibilidades de soluções para arquitetura de softwares feitos em Delphi. Isso é particularmente útil para desenvolvedores de infraestrutura de software, situação onde é comum a necessidade de se criar rotinas genéricas para certas tarefas.&lt;br /&gt;
&lt;br /&gt;
Customizar classes estendendo o &lt;b&gt;RTTI&lt;/b&gt; também permite melhorar a organização da solução já que estas classes serão mais coesas. Isto é, funcionalidades que não são centrais podem ser transferidas para outras classes associadas. É o caso, por exemplo, da exportação de objetos para XML (ou outro formato qualquer), processo conhecido como &lt;i&gt;serialização&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Estender o RTTI significa fazer marcações em classes, métodos, campos ou propriedades, introduzindo características extras no elemento marcado. Como a marcação também é uma classe, podemos criar comportamentos auxiliares complexos.&lt;br /&gt;
&lt;br /&gt;
O quadro abaixo mostra a declaração de uma classe simples que possui algumas marcações para permitir exportar seu conteúdo como um XML:&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;[TWXmlExportable(&lt;span style="color:maroon;"&gt;'notaFiscal'&lt;/span&gt;)]&lt;br/&gt;
  TWNota=&lt;span style="color:navy;font-weight:bold;"&gt;class&lt;/span&gt;&lt;br/&gt;
  &lt;span style="color:navy;font-weight:bold;"&gt;public&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;[TWXmlExportableNode(&lt;span style="color:maroon;"&gt;'nro'&lt;/span&gt;)]&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;Numero : longint;&lt;/span&gt;&lt;br/&gt;
    &lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;[TWXmlExportableNode(&lt;span style="color:maroon;"&gt;'serie'&lt;/span&gt;)]&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;Serie : String;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;[TWXmlExportableNode(&lt;span style="color:maroon;"&gt;'observ'&lt;/span&gt;)]&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;Observ: String;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;[TWXmlExportableNode(&lt;span style="color:maroon;"&gt;'vlrTotal'&lt;/span&gt;)]&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;Valor: Double;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;InfoNaoExport : String;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;procedure&lt;/span&gt; GravaNota;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
Como podemos ver, a marcação de um elemento é feita colocando-se um par abre e fecha colchetes antes da declaração desse elemento, inserindo entre eles o nome da classe usada para marcá-lo. No exemplo, há duas classes de marcação sendo usadas - &lt;b&gt;TWXmlExportable&lt;/b&gt; e &lt;b&gt;TWXmlExportableNode&lt;/b&gt;, sendo que ambas aceitam um parâmetro do tipo &lt;i&gt;string&lt;/i&gt; em seus construtores, o que também é fornecido na marcação do exemplo. Aqui, o parâmetro indica o nome da tag XML que conterá o elemento marcado. Observe que nem todos os campos foram marcados; apenas aqueles que eu quero exportar.&lt;br /&gt;
&lt;br /&gt;
As classes de marcação são também chamadas de &lt;b&gt;atributos&lt;/b&gt; e em Delphi têm obrigatoriamente que ser heranças da classe &lt;a href="http://docwiki.embarcadero.com/Libraries/en/System.TCustomAttribute"&gt;TCustomAttribute&lt;/a&gt;. A declaração das classes usadas no exemplo está na listagem a seguir:
&lt;br /&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;TWXmlExportable = &lt;span style="color:navy;font-weight:bold;"&gt;class&lt;/span&gt;(TCustomAttribute)&lt;br/&gt;
  &lt;span style="color:navy;font-weight:bold;"&gt;protected&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;FIsRoot: Boolean;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;FTagName: String;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="color:navy;font-weight:bold;"&gt;public&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;constructor&lt;/span&gt; Create (ATagName: String); &lt;span style="color:navy;font-weight:bold;"&gt;virtual&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;property&lt;/span&gt; TagName : String &lt;span style="color:navy;font-weight:bold;"&gt;read&lt;/span&gt; FTagName;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;property&lt;/span&gt; IsRoot: Boolean &lt;span style="color:navy;font-weight:bold;"&gt;read&lt;/span&gt; FIsRoot;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;br/&gt;
  &lt;br/&gt;
  TWXmlExportableNode = &lt;span style="color:navy;font-weight:bold;"&gt;class&lt;/span&gt;(TWXmlExportable)&lt;br/&gt;
  &lt;span style="color:navy;font-weight:bold;"&gt;public&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;constructor&lt;/span&gt; Create (ATagName: String); &lt;span style="color:navy;font-weight:bold;"&gt;override&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;br/&gt;
&lt;br/&gt;
 &lt;span style="color:green;"&gt;{ ... }&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;constructor&lt;/span&gt; TWXmlExportable.Create (ATagName: String);&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;begin&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;inherited&lt;/span&gt; Create;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;FTagNAme := ATagName;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;FIsRoot := true;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;constructor&lt;/span&gt; TWXmlExportableNode.Create (ATagName: String);&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;begin&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;inherited&lt;/span&gt; Create(ATagName);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;FIsRoot := false;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
Introduzi nelas a propriedade &lt;b&gt;IsRoot&lt;/b&gt; para poder diferenciar classes - que são elementos compostos por outros elementos - dos demais tipos. Assim, os campos de uma classe poderão ser aninhados em uma tag, enquanto cada campo de &lt;a href="http://docwiki.embarcadero.com/RADStudio/en/Simple_Types"&gt;tipo básico&lt;/a&gt; é exportado em sua tag individual. Com isso, a exportação funcionará corretamente até mesmo com classes que possuam outros objetos exportáveis em sua estrutura. &lt;br/&gt;
&lt;br/&gt;
Portanto, essas classes de marcação podem ser aplicadas livremente a quaisquer outros elementos no programa. A grande vantagem é que tal flexibilidade nos permite montar uma rotina genérica que seja capaz de exportar para XML qualquer objeto que contenha as marcações apropriadas. Da mesma forma que recuperamos a lista de métodos de um objeto &lt;a href="http://balaiotecnologico.blogspot.com.br/2012/06/trabalhando-com-informacoes-sobres.html"&gt;no outro post&lt;/a&gt;, podemos interagir com os atributos desse objeto:
&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;function&lt;/span&gt; TForm1.GetExportToXml (AObj: TObject) : TWXmlExportable;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;var&lt;/span&gt; i : integer;
    &lt;span style="margin-left:3em;"&gt;lTipo: TRttiType;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;begin&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;Result := &lt;span style="color:navy;font-weight:bold;"&gt;Nil&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{_RttiCntxt é um TRttiContext instanciado em outro ponto do sistema }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;lTipo := _RttiCntxt.GetType(AObj.ClassType);&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Obtem os atributos - ou marcações - do objeto }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;i := Length (lTipo.GetAttributes()) - &lt;span style="color:blue;"&gt;1&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;{ Verifica se algum dos atributos é do tipo TWXmlExportable; isso significa que o objeto passado no parâmetro é "exportável" }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;while&lt;/span&gt; (Result = &lt;span style="color:navy;font-weight:bold;"&gt;Nil&lt;/span&gt;) &lt;span style="color:navy;font-weight:bold;"&gt;And&lt;/span&gt; (i &gt;= &lt;span style="color:blue;"&gt;0&lt;/span&gt;) &lt;span style="color:navy;font-weight:bold;"&gt;do begin&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;if&lt;/span&gt; (lTipo.GetAttributes()[i] &lt;span style="color:navy;font-weight:bold;"&gt;is&lt;/span&gt; TWXmlExportable) &lt;span style="color:navy;font-weight:bold;"&gt;then&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:3em;"&gt;Result := (lTipo.GetAttributes()[i] &lt;span style="color:navy;font-weight:bold;"&gt;As&lt;/span&gt; TWXmlExportable);&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;Dec (i);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
A exportação para XML, então, passa a ser uma questão de levantar quais são os campos do objeto, determinar quais desses campos são "exportáveis" usando a mesma técnica acima, obter o nome da tag e o valor do campo. A função listada no quadro abaixo faz a exportação, seguindo esses passos:
&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;function&lt;/span&gt; TForm1.ExportToXml (AObj: TObject) : string;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;var&lt;/span&gt; lTipo: TRttiType;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;lCampo: TRttiField;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;lAttrib : TCustomAttribute;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;lExpField, lExpObj : TWXmlExportable;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;begin&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;Result := &lt;span style="color:maroon;"&gt;''&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;lExpObj := GetExportToXml (AObj);&lt;/span&gt;&lt;br/&gt;
  &lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ só continua se o objeto é "exportável" }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;if&lt;/span&gt; lExpObj &lt;&gt; &lt;span style="color:navy;font-weight:bold;"&gt;Nil then begin&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;lTipo := _RttiCntxt.GetType(AObj.ClassType);&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:green;"&gt;{ Inicia a tag XML, obtendo o nome no atributo encontrado para o objeto }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;Result := &lt;span style="color:maroon;"&gt;'&amp;lt;'&lt;/span&gt; + lExpObj.TagName + &lt;span style="color:maroon;"&gt;'&amp;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;{ Quais são os campos nesse tipo de classe ? }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;for&lt;/span&gt; lCampo &lt;span style="color:navy;font-weight:bold;"&gt;in&lt;/span&gt; lTipo.GetFields() &lt;span style="color:navy;font-weight:bold;"&gt;do begin&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:3em;"&gt;&lt;span style="color:green;"&gt;{ Analisa os atributos do campo pra ver quais são exportáveis }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:3em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;for&lt;/span&gt; lAttrib &lt;span style="color:navy;font-weight:bold;"&gt;in&lt;/span&gt; lCampo.GetAttributes() &lt;span style="color:navy;font-weight:bold;"&gt;do&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:4em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;if&lt;/span&gt; (lAttrib &lt;span style="color:navy;font-weight:bold;"&gt;is&lt;/span&gt; TWXmlExportable) &lt;span style="color:navy;font-weight:bold;"&gt;then begin&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:5em;"&gt;lExpField := lAttrib &lt;span style="color:navy;font-weight:bold;"&gt;As&lt;/span&gt; TWXmlExportable;&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:5em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;if&lt;/span&gt; (lExpField.IsRoot) &lt;span style="color:navy;font-weight:bold;"&gt;then&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
            &lt;span style="margin-left:6em;"&gt;&lt;span style="color:green;"&gt;{ campos do tipo classe são exportados recursivamente }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
            &lt;span style="margin-left:6em;"&gt;Result := Result + ExportToXml (lCampo.GetValue(AObj).AsObject)&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:5em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;else begin&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
            &lt;span style="margin-left:6em;"&gt;&lt;span style="color:green;"&gt;{ campos de tipos simples apenas envolve com o nome da tag contido no atributo do campo }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
            &lt;span style="margin-left:6em;"&gt;Result := Result + &lt;span style="color:maroon;"&gt;'&amp;lt;'&lt;/span&gt; + lExpField.TagName + '&gt;';&lt;/span&gt;&lt;br/&gt;
            &lt;span style="margin-left:6em;"&gt;&lt;span style="color:green;"&gt;{ Obtem o valor atual do campo }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
            &lt;span style="margin-left:6em;"&gt;Result := Result + lCampo.GetValue(AObj).toString();&lt;/span&gt;&lt;br/&gt;
            &lt;span style="margin-left:6em;"&gt;Result := Result + &lt;span style="color:maroon;"&gt;'&amp;lt;/'&lt;/span&gt; + lExpField.TagName + &lt;span style="color:maroon;"&gt;'&amp;gt;'&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
          &lt;span style="margin-left:5em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
        &lt;span style="margin-left:4em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;end&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;{ Encerra a tag desse objeto }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;Result := Result + &lt;span style="color:maroon;"&gt;'&amp;lt;/'&lt;/span&gt; + lExpObj.TagName + &lt;span style="color:maroon;"&gt;'&amp;gt;'&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
As informações sobre cada campo de uma classe são mantidas em instâncias de &lt;a href="http://docwiki.embarcadero.com/Libraries/en/System.Rtti.TRttiField"&gt;TRttiField&lt;/a&gt;. Além dos eventuais atributos associados ao campo, podemos descobrir com ela o nome do campo, seu tipo e sua visibilidade (público, protegido ou privado). Ela também fornece meios para recuperarmos ou modificarmos o valor do campo, conforme podemos ver no quadro anterior.&lt;br/&gt;
&lt;br/&gt;
Agora, para exportar uma instância da classe de Nota precisamos apenas passá-la para a função acima. Na verdade, a função é genérica o suficiente pra ser capaz de exportar para XML instâncias de qualquer classe anotada com os atributos apresentados aqui.&lt;br/&gt;
&lt;br/&gt;
Do jeito que esse recurso funciona, a classe de Nota apresentada no início do post pode focar na implementação das tarefas inerentes ao negócio, deixando a tarefa acessória de exportar os dados para outros pontos do sistema, favorecendo a coesão das classes na solução.&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.br/2012/06/trabalhando-com-informacoes-sobres.html"&gt;Trabalhando com informações sobres tipos no Delphi em tempo de execução - parte I&lt;/a&gt;, &lt;a href="http://robstechcorner.blogspot.com.br/2009/10/rtti-practical-examples.html"&gt;RTTI - Practical Examples&lt;/a&gt;, &lt;a href="http://docwiki.embarcadero.com/Libraries/en/System.TCustomAttribute"&gt;Classe TCustomAttribute&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/ZCkp0L_kK_k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/6778289413495397684/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/06/trabalhando-com-informacoes-sobres_22.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/6778289413495397684?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/6778289413495397684?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/ZCkp0L_kK_k/trabalhando-com-informacoes-sobres_22.html" title="Trabalhando com informações sobres tipos no Delphi em tempo de execução - 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/2012/06/trabalhando-com-informacoes-sobres_22.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUACRHk_eSp7ImA9WhJRFkk.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-2876738053353545953</id><published>2012-06-01T15:20:00.002-03:00</published><updated>2012-07-18T17:36:05.741-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-18T17:36:05.741-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Conceitos" /><title>Trabalhando com informações sobres tipos no Delphi em tempo de execução - parte I</title><content type="html">Em muitas situações num programa é conveniente saber o tipo de dado exato com o qual uma rotina está trabalhando, principalmente quando envolve objetos complexos. Dependendo do cenário, é preciso tomar uma decisão baseada no tipo e acessar propriedades e métodos do tipo específico.&lt;br/&gt;
&lt;br/&gt;Imagine, por exemplo, que você queira garantir que os textos nas telas do seu sistema sejam exibidos usando uma fonte predeterminada. Ao invés de ajustar o fonte manualmente em cada componente da tela, podemos percorrer a lista de componentes e automatizar o ajuste:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;procedure&lt;/span&gt; TForm1.FormCreate(Sender: TObject);&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;var&lt;/span&gt; i : integer;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;lLabel : TLabel;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;begin&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;for&lt;/span&gt; i := &lt;span style="color:blue;"&gt;0&lt;/span&gt; &lt;span style="color:navy;font-weight:bold;"&gt;to&lt;/span&gt; ComponentCount - &lt;span style="color:blue;"&gt;1&lt;/span&gt; &lt;span style="color:navy;font-weight:bold;"&gt;do&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;if&lt;/span&gt; (Components[i] &lt;span style="color:navy;font-weight:bold;"&gt;is&lt;/span&gt; TLabel) &lt;span style="color:navy;font-weight:bold;"&gt;then begin&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:3em;"&gt;lLabel := Components[i] &lt;span style="color:navy;font-weight:bold;"&gt;as&lt;/span&gt; TLabel;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:3em;"&gt;lLabel.Font.Name := &lt;span style="color:maroon;"&gt;'Calibri'&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:3em;"&gt;lLabel.Font.Color := clBlue;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:3em;"&gt;lLabel.Font.Size := &lt;span style="color:blue;"&gt;10&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
O código acima percorre a lista de componentes da tela e usa a palavra chave &lt;a href="http://www.delphibasics.co.uk/RTL.asp?Name=is"&gt;IS&lt;/a&gt; para saber se o componente atual é do tipo &lt;a href="http://docwiki.embarcadero.com/Libraries/en/Vcl.StdCtrls.TLabel"&gt;TLabel&lt;/a&gt; (ou uma herança dessa classe). Em caso positivo, é feito um &lt;a href="http://en.wikipedia.org/wiki/Cast_%28computer_science%29"&gt;cast&lt;/a&gt; usando o &lt;a href="http://www.delphibasics.co.uk/RTL.asp?Name=as"&gt;AS&lt;/a&gt; e, então, as propriedades relacionadas ao fonte podem ser configuradas à vontade.&lt;br/&gt;
&lt;br/&gt;
O recurso de uma linguagem de programação que permite obter informações sobre tipos de dados em tempo de execução é chamado de &lt;b&gt;RTTI&lt;/b&gt; (Run Time Type Information). Em alguns ambientes, isso também é chamado de Reflexion.&lt;br/&gt;
&lt;br/&gt;
Todos os objetos em Delphi conseguem reportar informações básicas sobre si mesmos, como o nome da classe a que pertencem, de qual classe ela herda, se implementa um determinado método, entre outros.&lt;br/&gt;
&lt;br/&gt;
No entanto, a versão 2010 do Delphi passou por uma grande reformulação no tratamento de &lt;b&gt;RTTI&lt;/b&gt;, aumentando significativamente sua capacidade. Agora você também pode obter informações sobre tipos atômicos, além de poder levantar os métodos e propriedades de classes, mesmo aqueles que sejam protegidos ou privados. Também é possível personalizar o RTTI, disponibilizando outras informações e funcionalidades a classes Delphi.&lt;br/&gt;
&lt;br/&gt;
O novo mecanismo é baseado no conceito de "contexto", que nada mais é que o escopo constituido pelo programa principal, as bibliotecas (DLLs) e pacotes agregados. Toda aplicação Delphi passa a ter um único contexto RTTI onde são lançadas as informações sobre os tipos de dados em uso. Com isso, o primeiro passo para se obter informações sobre tipos é declarar e instanciar um contexto.&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;var&lt;/span&gt; lContexto: TRttiContext;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;lType: TRttiType;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;lMetodo : TRttiMethod;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;lParm : TRttiParameter;&lt;/span&gt;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;begin&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;lContexto := TRttiContext.Create;&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;lType := lContexto.GetType(TypeInfo (TForm1));&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;for&lt;/span&gt; lMetodo &lt;span style="color:navy;font-weight:bold;"&gt;in&lt;/span&gt; lType.GetMethods() &lt;span style="color:navy;font-weight:bold;"&gt;do begin&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;ListBox1.AddItem(lMetodo.Name, lMetodo);&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;for&lt;/span&gt; lParm &lt;span style="color:navy;font-weight:bold;"&gt;in&lt;/span&gt; lMetodo.GetParameters () &lt;span style="color:navy;font-weight:bold;"&gt;do&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:3em;"&gt;ListBox1.AddItem(&lt;span style="color:maroon;"&gt;'   '&lt;/span&gt; + lParm.ToString (), lParm);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;lContexto.Free&lt;/span&gt;;&lt;br/&gt;
&lt;span style="color:navy;font-weight:bold;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
Após instanciar o contexto, esse trecho de código obtém informações sobre o Form atual em dois passos. No primeiro, a função &lt;a href="http://docwiki.embarcadero.com/Libraries/en/System.TypeInfo"&gt;TypeInfo&lt;/a&gt; retorna um ponteiro para as informações básicas. Então, o ponteiro é usado num segundo passo para obter as informações extendidas que foram introduzidas na nova versão do RTTI e que são representadas pela classe &lt;a href="http://docwiki.embarcadero.com/Libraries/en/System.Rtti.TRttiType"&gt;TRttiType&lt;/a&gt;.&lt;br/&gt;
&lt;br/&gt;
Em seguida, o código percorre a lista de métodos do Form1 - incluindo toda a hierarquia de classes a qual ele pertence - e adiciona seus nomes num &lt;i&gt;list box&lt;/i&gt; para exibição. Para cada método também é recuperada a lista dos parâmetros que devem ser passados quando ele for chamado em seu programa.&lt;br/&gt;
&lt;br/&gt;
Embora não esteja representado no exemplo, o mesmo tipo de levantamento pode ser feito com as propriedades, ainda que elas não estejam declaradas como &lt;b&gt;published&lt;/b&gt;.&lt;br/&gt;
&lt;br/&gt;
A dúvida mais frequente sobre esse tipo de recurso é: em que situações isso pode ser aplicado ? Além do cenário citado no início do post, outras situações podem ser mais facilmente resolvidas com RTTI, tais como a clonagem de objetos (incluindo o estado completo dele), serialização de objetos (transformá-los em um XML ou enviá-los para a impressora, por exemplo), criação de uma infraestutura para aceitar &lt;i&gt;plugins&lt;/i&gt; em uma aplicação, chamada dinâmica de métodos, etc.&lt;br/&gt;
&lt;br/&gt;
O próprio IDE do Delphi usa aspectos do RTTI para poder trabalhar com as classes e Forms que você desenvolve, fornecendo informações, por exemplo, para o Code Insight ou serializando a estrutura do Form em um arquivo DFM.&lt;br/&gt;
&lt;br/&gt;
No próximo post, mostro o recurso que permite incrementar as informações de &lt;i&gt;runtime&lt;/i&gt; em classes, métodos e propriedades.&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/RADStudio/en/Working_with_RTTI_Index"&gt;Working with RTTI&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/ZkXVSgKB1lE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/2876738053353545953/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/06/trabalhando-com-informacoes-sobres.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/2876738053353545953?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/2876738053353545953?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/ZkXVSgKB1lE/trabalhando-com-informacoes-sobres.html" title="Trabalhando com informações sobres tipos no Delphi em tempo de execução - 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/2012/06/trabalhando-com-informacoes-sobres.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QNRH45fCp7ImA9WhJRFEs.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-1825182628094006464</id><published>2012-05-16T11:59:00.001-03:00</published><updated>2012-07-16T17:09:55.024-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-16T17:09:55.024-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="CAPICOM" /><title>Preparando o Certificado Digital para inclusão no XML com CAPICOM e Delphi</title><content type="html">Há algum tempo, publiquei uma série de posts sobre a manipulação de XMLs e a criação de assinatura digital para eles. Como a plataforma .NET da Microsoft traz classes prontas para realizar o grosso das tarefas envolvidas, eu usei o C# para montar os exemplos contidos naqueles posts.&lt;br /&gt;
&lt;br /&gt;
Mas muita gente não pode usar a solução com .Net, principalmente quem já têm aplicações desenvolvidas em outras linguagens. Algumas dessas pessoas entraram em contato pra saber como fazer esse mesmo procedimento usando a biblioteca de criptografia da Microsoft - o CAPICOM. Uma dúvida bastante frequente é relativa ao conteúdo a ser inserido na tag &lt;b&gt;X509Certificate&lt;/b&gt; do XML assinado. O quadro abaixo mostra o trecho de um XML assinado de Nota Fiscal Eletrônica que inclui a tag em questão:&lt;br /&gt;
&lt;div style="font-size:8pt;font-family:Courier New;border:1px solid silver;padding:5px 10px 1em 5px;width: 98%;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" ?&amp;gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left: 0;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;enviNFe versao&lt;/span&gt;&lt;span style="color:blue;"&gt;="&lt;/span&gt;&lt;b&gt;&lt;span&gt;2.00&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;"&lt;/span&gt;&lt;span style="color:red;"&gt; xmlns&lt;/span&gt;&lt;span style="color:blue;"&gt;="&lt;/span&gt;&lt;b&gt;&lt;span style="color:red;"&gt;http://www.portalfiscal.inf.br/nfe&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;"&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;idLote&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;71&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;idLote&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;NFe&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;infNFe Id&lt;/span&gt;&lt;span style="color:blue;"&gt;="&lt;/span&gt;&lt;span style="color:red;"&gt;&lt;b&gt;NFe3508059978&lt;/b&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;"&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt; versao&lt;/span&gt;&lt;span style="color:blue;"&gt;="&lt;/span&gt;&lt;b&gt;&lt;span style="color:red;"&gt;2.00&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;"&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;cUF&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;35&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;cUF&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;cNF&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;518005127&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;cNF&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;natOp&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;Venda a vista&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;natOp&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;mod&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;55&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;mod&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;serie&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;1&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;serie&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;dEmi&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;2012-05-06&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;dEmi&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;tpAmb&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;2&lt;/span&gt;&lt;/b&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;tpAmb&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;infNFe&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;Signature&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;SignedInfo&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="margin-left: 5em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;CanonicalizationMethod Algorithm=&lt;/span&gt;&lt;span style="color:red;"&gt;&lt;b&gt;"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"&lt;/b&gt;&lt;/span&gt;/&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 5em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;SignatureMethod Algorithm&lt;/span&gt;=&lt;span style="color:red;"&gt;&lt;b&gt;"http://www.w3.org/2000/09/xmldsig#rsa-sha1"&lt;/b&gt;&lt;/span&gt;/&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 5em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;Reference URI&lt;/span&gt;=&lt;span style="color:red;"&gt;"&lt;b&gt;#NFe3508059978"&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 6em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;Transforms&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 7em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;Transform Algorithm&lt;/span&gt;=&lt;span style="color:red;"&gt;&lt;b&gt;"http://www.w3.org/2000/09/xmldsig#enveloped-signature"&lt;/b&gt;&lt;/span&gt;/&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 7em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;Transform Algorithm&lt;/span&gt;=&lt;span style="color:red;"&gt;&lt;b&gt;"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"&lt;/b&gt;&lt;/span&gt;/&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 6em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:rgb(153,0,0);"&gt;Transforms&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 6em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;DigestMethod Algorithm&lt;/span&gt;=&lt;span style="color:red;"&gt;&lt;b&gt;"http://www.w3.org/2000/09/xmldsig#sha1"&lt;/b&gt;&lt;/span&gt;/&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 6em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;DigestValue&lt;/span&gt;&gt;&lt;b&gt;4aXU7m8rl14ALy6X...=&lt;/b&gt;&amp;lt;/&lt;span style="color:rgb(153,0,0);"&gt;DigestValue&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 5em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:rgb(153,0,0);"&gt;Reference&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:rgb(153,0,0);"&gt;SignedInfo&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;SignatureValue&lt;/span&gt;&gt;&lt;b&gt;Igq7eI/Fy3PyjjSW...=&lt;/b&gt;&amp;lt;/&lt;span style="color:rgb(153,0,0);"&gt;SignatureValue&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;KeyInfo&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 5em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;X509Data&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 6em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;X509Certificate&lt;/span&gt;&gt;&lt;b&gt;MIIGxDCCBaygAwIBAgIIN6q4...=&lt;/b&gt;&amp;lt;/&lt;span style="color:rgb(153,0,0);"&gt;X509Certificate&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 5em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:rgb(153,0,0);"&gt;X509Data&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 4em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:rgb(153,0,0);"&gt;KeyInfo&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 3em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:rgb(153,0,0);"&gt;Signature&lt;/span&gt;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left: 2em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;NFe&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style="color:red;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(153,0,0);"&gt;enviNFe&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;

Como podemos ver, a tag &lt;b&gt;X509Certificate&lt;/b&gt; é parte da estrutura que traz as informações sobre a chave usada pela assinatura e é incluída no fim do XML, junto com a área reservada para a assinatura em si. O valor armazenado na &lt;b&gt;X509Certificate&lt;/b&gt; descreve o certificado usado na assinatura, codificado na &lt;a href="http://balaiotecnologico.blogspot.com.br/2011/06/trabalhando-com-base64-em-delphi.html"&gt;Base64&lt;/a&gt;. Esse valor representa a chave do certificado e é parte imprescindível para a validação do documento XML, isso é, ele ajuda a garantir que o XML não foi adulterado depois de ter sido assinado.&lt;br /&gt;
&lt;br /&gt;
E como calcular esse valor com CAPICOM? Após recuperar o certificado digital de acordo com as instruções do post &lt;a href="http://balaiotecnologico.blogspot.com.br/2009/07/acessando-o-certificate-store-do.html"&gt;Acessando o Certificate Store do Windows com CAPICOM&lt;/a&gt;, podemos conseguir o conteúdo desse certificado já na Base64 em um único comando:&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;weight:bold;"&gt;var&lt;/span&gt; cert : TCertificate;&lt;br /&gt;
    &lt;span style="margin-left:3em;"&gt;certBase64 : WideString;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:blue;weight:bold;"&gt;begin&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;color:green;"&gt;{ ... }&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;certBase64 := cert.Export(CAPICOM_ENCODE_BASE64);&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;color:green;"&gt;{ ... }&lt;/span&gt;
&lt;/div&gt;
A função &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa376520%28v=vs.85%29.aspx"&gt;export&lt;/a&gt; da interface &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa376092%28v=vs.85%29.aspx"&gt;ICertificate2&lt;/a&gt; aceita como parâmetro o tipo de codificação que se deseja como resultado da exportaçao. Os valores permitidos para esse parâmetros são os definidos no tipo enumerado &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa375673%28v=vs.85%29.aspx"&gt;CAPICOM_ENCODING_TYPE&lt;/a&gt;. Ele pode assumir basicamente dois tipo de codificação : a Base64 ou a informação binária pura, sem codificação.&lt;br /&gt;
&lt;br /&gt;
O código utilizado no exemplo - &lt;b&gt;CAPICOM_ENCODE_BASE64&lt;/b&gt; - faz a exportação de todas as informações necessárias para inclusão na tag &lt;b&gt;X509Certificate&lt;/b&gt; do XML assinado. Há, no entanto, um detalhe no qual é preciso prestar atenção: o texto exportado está quebrado em diversas linhas.&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;
MIIGNjCCBR6gAwIBAgIITDgm4uwI+60wDQYJKoZIhvcNAQEFBQAwTDELMAkGA1UE&lt;br /&gt;
BhMCQlIxEzARBgNVBAoTCklDUC1CcmFzaWwxKDAmBgNVBAMTH1NFUkFTQSBDZXJ0&lt;br /&gt;
aWZpY2Fkb3JhIERpZ2l0YWwgdjEwHhcNMTEwNzA3MTMxMDA0WhcNMTIwNzA2MTMx&lt;br /&gt;
MDA0WjCB7jELMAkGA1UEBhMCQlIxEzARBgNVBAoTCklDUC1CcmFzaWwxFDASBgNV&lt;br /&gt;
BAsTCyhFTSBCUkFOQ08pMRgwFgYDVQQLEw8wMDAwMDEwMDE5NjExNzIxFDASBgNV&lt;br /&gt;
BAsTCyhFTSBCUkFOQ08pMRQwEgYDVQQLEwsoRU0gQlJBTkNPKTEUMBIGA1UECxML&lt;br /&gt;
&lt;span style="margin-left:3em;"&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:3em;"&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:3em;"&gt;.&lt;/span&gt;&lt;br /&gt;
aXRhbC5jb20uYnIvc2VyYXNhY2R2MTANBgkqhkiG9w0BAQUFAAOCAQEAY8NBFO6e&lt;br /&gt;
kPTHirS8DHnlsx1kTJfmsHoUR1QgnDMNdChQjW7ctAn5nIpPYXdhf26om+Us80D/&lt;br /&gt;
5RA2iXHhXFT5eL7Crqq0DQ73zWbdn8e81dIDFqYjxIt4LBMy4CO0lJeiT9YHkmYB&lt;br /&gt;
XSuADpElqwXA0rzx7bBeIOzuVUGMoYQBduViByI813XIQ2i86Z9VgRLO5KuPUNPn&lt;br /&gt;
0RkZS2rSpX1/wLkef8ura++dZEYmbVWpu3g2yCLQJfCArYy/fzsIDwBKruSWnY/O&lt;br /&gt;
NK/1AgUaceVAcxxvVmuECwCBqtpfmHqAOXC/uEOXiKefF7L++j0Xc+Okew1SMkHJ&lt;br /&gt;
sNNJ+AcX4VfQrw==
&lt;/div&gt;
&lt;br/&gt;
Como o conteúdo da tag &lt;b&gt;X509Certificate&lt;/b&gt; deve estar numa única linha, o texto retornado pelo &lt;b&gt;export&lt;/b&gt; deve ser tratado, removendo-se os espaços em branco do fim e as quebras de linha:
&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;certBase64 := Trim (ReplaceStr (certBase64, &lt;span style="color:maroon;"&gt;#13#10&lt;/span&gt;, &lt;span style="color:maroon;"&gt;''&lt;/span&gt;));&lt;/span&gt;
&lt;/div&gt;
&lt;br/&gt;
O valor da variável &lt;i&gt;certBase64&lt;/i&gt; agora pode ser incluído sem problemas como conteúdo da tag &lt;b&gt;X509Certificate&lt;/b&gt; em seu XML assinado.
&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.br/search/label/CAPICOM"&gt;Posts sobre CAPICOM&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa376520%28v=vs.85%29.aspx"&gt;Função ICertificate2::Export&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/Y-L_HKO37AI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/1825182628094006464/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/05/preparando-o-certificado-digital-para.html#comment-form" title="4 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/1825182628094006464?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/1825182628094006464?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/Y-L_HKO37AI/preparando-o-certificado-digital-para.html" title="Preparando o Certificado Digital para inclusão no XML com CAPICOM e 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/2012/05/preparando-o-certificado-digital-para.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIMQH8zcCp7ImA9WhVVEEo.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-9163034444086741473</id><published>2012-05-03T17:23:00.000-03:00</published><updated>2012-05-03T17:23:01.188-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-03T17:23:01.188-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Internet" /><title>Trabalhando com HTTP em Delphi</title><content type="html">O protocolo &lt;a href="http://pt.wikipedia.org/wiki/Hypertext_Transfer_Protocol"&gt;HTTP&lt;/a&gt; - HyperText Transfer Protocol ou Protocolo de Transferência de Hipertexto) - é certamente o mais utilizado na internet. É com ele que as páginas da internete são transferidas para seu computador antes de serem exibidas no navegador. O termo "hipertexto" diz respeito ao fato de que os documentos obtidos através do protocolo podem conter &lt;i&gt;links&lt;/i&gt; remetendo a outros documentos.&lt;br/&gt;
&lt;br/&gt;
Numa primeira olhada, a utilidade do &lt;b&gt;HTTP&lt;/b&gt; não parece muito diferente do &lt;a href="http://balaiotecnologico.blogspot.com.br/2010/10/fazendo-download-e-upload-usando-ftp.html"&gt;FTP usado para fazer downloads&lt;/a&gt;. O código abaixo, por exemplo, obtém o documento padrão do site do Google Brasil, isto é, a página HTML que é exibida quando se digita o endereço do Google Brasil num  navegador. No exemplo, estou usando o componente &lt;a href="http://docwiki.embarcadero.com/Libraries/en/IdHTTP.TIdHTTP"&gt;TIdHTTP&lt;/a&gt; da paleta do projeto Indy:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; lResponse : TStringStream;&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;lResponse := TStringStream.Create(&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: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;&lt;span style="color:green;"&gt;{ lResponse conterá a página HTML requisitada :}&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;idHttp1.Get(&lt;span style="color:maroon;"&gt;'http://www.google.com.br'&lt;/span&gt;, lResponse);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;finally&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;lResponse.Free();&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;/div&gt;
Apesar de não ser necessário configurar explicitamente um servidor/porta e usuário/senha como no FTP, o resultado final é o mesmo: o download de um arquivo remoto. Na verdade, a infraestrutura da internete mapeia automaticamente o endereço do Google para um servidor/porta; nesse caso, o usuário e senha é dispensável pois se trata de um site público que permite acesso anônimo.&lt;br/&gt;
&lt;br/&gt;
Se olharmos mais a fundo, no entanto, veremos que o HTTP é mais flexível porque permite adicionar parâmetros à requisição enviada ao servidor. Na prática, isso dá ao servidor a chance de montar dinamicamente a resposta mais adequada à solicitação feita. As APIs de serviços publicados na internete normalmente são baseados no HTTP e se valem dos parâmetros pra flexibilizar as requisições. É o caso, por exemplo, do &lt;b&gt;Google Docs&lt;/b&gt; e de outros serviços do Google, que usam a &lt;a href="http://code.google.com/intl/pt-BR/apis/gdata/"&gt;API de dados&lt;/a&gt; da empresa. Em outro post, eu mostro como se comunicar com o &lt;b&gt;Google Docs&lt;/b&gt; usando a API de dados para ler os documentos salvos nesse serviço.&lt;br/&gt;
&lt;br/&gt;
Se você já trabalhou com &lt;b&gt;HTML&lt;/b&gt;, deve ter notado que a sintaxe dos &lt;a href="http://www.w3schools.com/tags/tag_form.asp"&gt;Forms&lt;/a&gt; inclui uma "action", um método de envio e os diversos campos que serão preenchidos pelo usuário da página, sendo admitido até mesmo a existência de campos invisíveis contendo informações pré alimentadas.&lt;br/&gt;
&lt;br/&gt;
Para relembrar o significado dessas propriedades do &lt;b&gt;Form HTML&lt;/b&gt; : A "action" é o endereço na internete para onde a requisição será submetida. O "método" diz repespeito a como e quais informações serão enviadas; os valores mais comuns são &lt;b&gt;GET&lt;/b&gt; (as informações são formatadas e acrescentadas ao endereço da "action", que então é enviado ao servidor) ou &lt;b&gt;POST&lt;/b&gt; (as informações são transportadas à parte e não é possível enxergá-las na barra de endereço do navegador).&lt;br/&gt;
&lt;br/&gt;
O &lt;b&gt;form&lt;/b&gt; de pesquisa do Google, por exemplo, admite que você selecione a língua na qual deseja obter as repostas e, claro, os termos a serem pesquisados. O exemplo abaixo submete ao Google uma pesquisa em português com o nome do &lt;a href="http://balaiotecnologico.blogspot.com"&gt;blog&lt;/a&gt;:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; lURL : String;&lt;br/&gt;
    &lt;span style="margin-left:3em;"&gt;lResponse : TStringStream;&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;lResponse := TStringStream.Create(&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: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;lURL := &lt;span style="color:maroon;"&gt;'http://www.google.com.br/search?'&lt;/span&gt; +&lt;/span&gt;&lt;br/&gt;
            &lt;span style="margin-left:5em;"&gt;&lt;span style="color:maroon;"&gt;'hl=pt-BR&amp;'&lt;/span&gt; +&lt;/span&gt;&lt;br/&gt;
            &lt;span style="margin-left:5em;"&gt;&lt;span style="color:maroon;"&gt;'q=balaio%20tecnologico'&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;idHttp1.Get(lURL, lResponse);&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;lResponse.Position := &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:green;"&gt;{ Exemplo de uso do response : carregar o conteúdo  num RichEdit : }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
     &lt;span style="margin-left:2em;"&gt;reResp.Lines.LoadFromStream(lResponse);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;finally&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;lResponse.Free();&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;/div&gt;
Veja que cada parâmetro é composto de um nome (o mesmo configurado nas &lt;i&gt;tag&lt;/i&gt;s &lt;a href="http://www.w3schools.com/tags/tag_input.asp"&gt;input&lt;/a&gt; do &lt;i&gt;form&lt;/i&gt;) seguido por um sinal de igual (=) e o valor que o parâmetro deve assumir (normalmente, os próprios valores fornecidos pelo usuário). Cada parâmetro é concatenado ao anterior através de um "E Comercial" (&amp;).&lt;br/&gt;
&lt;br/&gt;
Ambos os parâmetros considerados pelo exemplo estão incluídos no &lt;i&gt;form&lt;/i&gt; da pesquisa do Google. Ou seja, se você souber quais são os parâmetros de um &lt;i&gt;form&lt;/i&gt;, poderá simular via Delphi a requisição que ele submeteria numa página da Web e, então, obter exatamente a mesma reposta, podendo tratá-la do modo que for mais apropriado para sua aplicação.&lt;br/&gt;
&lt;br/&gt;
Por causa dessa facilidade de simular requisições via programação, muitos sites se protegem implementando um &lt;a href="http://pt.wikipedia.org/wiki/CAPTCHA"&gt;CAPTCHA&lt;/a&gt;. Trata-se de uma imagem com um texto embutido que é gerada dinamicamente pelo servidor de modo que apenas operadores humanos consigam ler. O texto deve, então, ser digitado num campo e enviado junto com as demais informações. A requisição só é atendida se o texto estiver correto.&lt;br/&gt;
&lt;br/&gt;
Como podemos notar pelo exemplo, usar o &lt;b&gt;GET&lt;/b&gt; para recuperar um documento pode ser problemático se certas informações sensíveis - como uma senha - tiverem que ser transmitidas direto na URL. Nestes casos, é recomendado usar o &lt;b&gt;POST&lt;/b&gt; pois com ele as informações trafegam por outros meios.&lt;br/&gt;
&lt;br/&gt;
O uso do &lt;b&gt;POST&lt;/b&gt; também é simples. Basta passar os parâmetros num &lt;a href="http://docwiki.embarcadero.com/Libraries/en/System.Classes.TStringList"&gt;TStringList&lt;/a&gt; separado. A URL do "action" é informada sem quaisquer decorações extras:
&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; lParams :TStringList;&lt;br/&gt;
&lt;span style="margin-left:3em;"&gt;lResponse : TStringStream;&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;
  lParams := TStringList.Create;&lt;br/&gt;
  lResponse := TStringStream.Create(&lt;span style="color:maroon;"&gt;''&lt;/span&gt;);&lt;br/&gt;
&lt;br/&gt;
  &lt;span style="color:navy;"&gt;&lt;b&gt;try&lt;/b&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;lParams.Add(&lt;span style="color:maroon;"&gt;'filt=all'&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;lParams.Add(&lt;span style="color:maroon;"&gt;'p=balaio%20tecnologico'&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;idHttp1.Post(&lt;span style="color:maroon;"&gt;'http://br.search.yahoo.com/search'&lt;/span&gt;, lParams, lResponse);&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;&lt;span style="color:green;"&gt;{ Exemplo de uso do response : carregar o conteúdo  num RichEdit : }&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;lResponse.Position := &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
     &lt;span style="margin-left:2em;"&gt;reResp.Lines.LoadFromStream(lResponse);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;finally&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;lParams.Free();&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;lResponse.Free();&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;/div&gt;
Neste exemplo, usei o &lt;a href="http://br.yahoo.com/?p=us"&gt;Yahoo!&lt;/a&gt; porque o Google não implementa &lt;b&gt;POST&lt;/b&gt; para pesquisas.&lt;br/&gt;
&lt;br/&gt;
Ajustes ainda mais finos para submeter a requisição podem ser configuras na propriedade &lt;b&gt;Request&lt;/b&gt; do TIdHTTP. Com ele, é possível ajustar o tipo de documento que se espera receber de volta (HTML, XML, etc.), o tipo de &lt;i&gt;encoding&lt;/i&gt;, se há necessidade de passar por um proxy, 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://pt.wikipedia.org/wiki/Hypertext_Transfer_Protocol"&gt;Protocolo HTTP&lt;/a&gt;, &lt;a href="http://www.w3schools.com/tags/tag_form.asp"&gt;Tag Form do HTML&lt;/a&gt;, &lt;a href="http://pt.wikipedia.org/wiki/CAPTCHA"&gt;CAPTCHA&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/fmbywnrpJ8Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/9163034444086741473/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/05/trabalhando-com-http-em-delphi.html#comment-form" title="7 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/9163034444086741473?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/9163034444086741473?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/fmbywnrpJ8Q/trabalhando-com-http-em-delphi.html" title="Trabalhando com HTTP 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>7</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2012/05/trabalhando-com-http-em-delphi.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUFQXk9fCp7ImA9WhVXEUo.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-1880197552433467840</id><published>2012-04-11T16:40:00.001-03:00</published><updated>2012-04-11T16:40:10.764-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-11T16:40:10.764-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Notícias" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML" /><title>Novo IPad complica a vida dos desenvolvedores HTML5</title><content type="html">Se você já achava dura a vida de desenvolvedor HTML, com as muitas diferenças de implementação nos diversos navegadores e a infinidade de tamanhos de telas disponíveis em &lt;i&gt;desktops&lt;/i&gt;, &lt;i&gt;tablets&lt;/i&gt; e celulares, veja só essa matéria publicada na &lt;a href="http://akamai.infoworld.com/"&gt;InfoWorld&lt;/a&gt; sobre os teste feitos com os recursos do novo tablet da Apple - o iPad 3.&lt;br/&gt;
&lt;div style="border:1px solid silver;padding: 5px 10px 1em 5px;width:98%;background-color:#e9e9fb"&gt;
O novo iPad da Apple, já um sucesso entre os consumidores com sua tela de alta resolução, está, no entanto, decepcionando alguns desenvolvedores HTML5. O sistema operacional do tablet - iOS 5.1 - complica o armazenamento de dados do HTML5, não oferece novos suportes ao HTML5 e a performance na navegação web é, na melhor das hipóteses, similar à do iPad 2.&lt;br /&gt;
&lt;br /&gt;
É demais classificar isso de "retrocesso" e ninguém está dizendo que a Apple está recuando de seu apoio agressivo aos padrões na web, o que eventualmente deixará aplicações web com comportamento próximo ao das aplicações nativas. Mas, para alguns, as decisões da Apple comprometem e poderiam viver sem elas.&lt;br /&gt;
&lt;br /&gt;
A &lt;a href="http://www.sencha.com"&gt;Sencha&lt;/a&gt;, fornecedora de ferramentas para HTML5, postou na semana passada uma "Avaliação HTML5' para o novo iPad e o iOS 5.1, classificando os resultados como um "saco misto" para a Apple. A avaliação do fornecedor pesou dois critérios: completude –- quanto dos vários elementos do HTML5 estão presentes –- e correção –- se o suporte a esses elementos está bem implementado, diz Aditya Bansod, diretor senior e gerente de produto da empresa de software sediada em Redwood City, Califórnia. O post também inclui resultados de comparativos com outros produtos em relação à performance do tablet na navegação.&lt;br /&gt;
&lt;br /&gt;
"Ainda é a melhor plataforma HTML5 no mercado", diz Bansod. "Mas esperávamos um avanço maior que este (no novo iPad). Ao invés disso, estamos pisando em terreno pantanoso e até mesmo retrocedemos um pouco. É um tanto desapontador por parte da Apple."&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Complicando o armazenamento de dados Web&lt;/b&gt;&lt;br /&gt;
Uma mudança, introduzida primeiro em 2011 com uma distribuição beta do iOS 5.1, limita alguns aspectos do armazenamento de dados local do HTML5. Dados armazenados localmente usando o LocalStorage do HTML5 não são mais tratados como persistentes pelo sistema operacional. Isto introduz um problema para desenvolvedores que usam este recurso para armazenar dados locais ou o WebSQL como mecanismo de armazenamento. Como o sistema não enxerga mais esses dados como persistentes e sim como temporários, "o iOS pode removê-los a qualquer momento, sem aviso, até em cenários onde o sistema está com pouca memória disponível", anotou Bansod em seu post.&lt;br /&gt;
&lt;br /&gt;
Os desenvolvedores web rapidamente captaram a mudança em janeiro, discutindo-a em vários foruns online, como o forum &lt;b&gt;Phonegap&lt;/b&gt; no &lt;b&gt;Google Groups&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
O problema afeta um sub grupo de aplicações do iOS, às vezes chamadas de aplicações híbridas, que utilizam uma &lt;i&gt;WebView&lt;/i&gt; embutida. "WebViews são a força das aplicações HTML5 inseridas em pacotes nativos, como os do &lt;b&gt;PhoneGap&lt;/b&gt; ou do &lt;b&gt;Sencha Touch&lt;/b&gt;," escreveu Bansod. "Elas embutem um navegador web em aplicações nativas, o que permite a distribuição de aplicações web através das &lt;i&gt;App Stores&lt;/i&gt; nativas. &lt;i&gt;WebViews&lt;/i&gt; estão presentes em todos os sistemas operacionais mobile modernos."&lt;br /&gt;
&lt;br /&gt;
Até o iOS 5.1, aplicações &lt;i&gt;WebView&lt;/i&gt; podiam armazenar dados localmente e persistí-los usando o armazenamento do HTML5. "Especificamente, se sua aplicação usava LocalStorage ou WebSQL, isso era considerado parte dos dados da aplicação," diz Bansod. Se uma nova versão da aplicação fosse lançada, os dados ainda estariam presentes.&lt;br /&gt;
&lt;br /&gt;
Este não é mais o caso. "É possível que isso se dê porque a Apple não conseguiu fazer de forma confiável a sincronização de dados pelo iCloud quando esses dados não estão armazenados no sistema de armazenamento nativo do iOS." especula Bansod. Um desenvolvedor disse no forum do &lt;b&gt;Phonegap&lt;/b&gt; que ele foi informado por alguém da Apple que a razão para a mudança era "para economizar espaço, pois aplicações carregando muito conteúdo numa &lt;i&gt;UIWebView&lt;/i&gt; (como o Twitter) ocuparia espaço demais [na sincronização com o serviço iCloud da Apple]... Mas eles esqueceram completamente de nós, pobres desenvolvedores Phonegap, que contavam com o LocalStorage ou o WebSQL para armazenar os dados dos usuários."&lt;br /&gt;
&lt;br /&gt;
"Para os desenvolvedores que contavam com o LocalStorage ou o WebSQL como mecanismo para armazenar dados de suas aplicações, interrompê-lo é um grande problema," disse Bansod em seu post. Não é impeditivo: "Há vários meios de contornar o problema, como usar o SQLPlugin do &lt;b&gt;PhoneGap&lt;/b&gt; que usa o SQLite padrão, or escrever seu próprio JavaScript para acessar diretamente o CoreData do iOS." Para muitos, afirma ele, isso significa recodificar suas aplicações.&lt;br /&gt;
&lt;br /&gt;
De fato, aplicações que não forem alteradas "esquecerão" os dados. Os usuários também podem perder dados já que aplicações nas quais eles costumavam armazenar dados relevantes, de repente deixaram de fazer esse armazenamento, por exemplo.&lt;br /&gt;
&lt;br /&gt;
Ao menos alguns desenvolvedores têm a esperança de que esta mudança seja apenas um bug que a Apple corrigirá. Em 7 de Março, com o anúncio do novo iPad e o iOS 5.1, eles descobriram que a Apple os colocou num novo território. "Eles fizeram isto. A Apple lançou o programa com aquele bug. Eu já tenho usuários furiosos porque perderam seus trabalhos com minha aplicação. :-/," postou Sam no forum do &lt;b&gt;Phonegap&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
As formas de contornar o problema não são simples, como se vê ao acompanhar as discussões para um plugin do &lt;b&gt;Phonegap&lt;/b&gt;, criado por Shazron Abdullah na Apache Software Foundation.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Sem avanços nos recursos do HTML5&lt;/b&gt;&lt;br /&gt;
A avaliação da Sencha também revelou a ausência de quaisquer novas funções HTML5 no iOS 5.1 e na novíssima versão mobile do navegador Safari da Apple. "Nenhum novo recurso apareceu entre as versões iOS 5.0 e iOS 5.1," escreveu. "O iOS ainda apresenta um dos melhores suportes ao HTML5 entre os navegadores mobile, mas esta última encarnação não aprofundou o suporte do Safari aos padrões."&lt;br /&gt;
&lt;br /&gt;
O Safari 6 no Mac, por exemplo, suporta um recurso chamado Regiões de &lt;i&gt;Cascading Style Sheets&lt;/i&gt; (CSS), um modo simples de criar e modificar o layout de revistas digitais. Mas está faltando na versão atual do Safari para dispositivos com iOS 5.1.&lt;br /&gt;
&lt;br /&gt;
"Queríamos ver também se o &lt;b&gt;WebGL&lt;/b&gt; [uma API JavaScript para desenhar gráficos em 3D sem a necessidade de um plugin], que atualmente é suportado somente no Apple iAds, está disponível no navegador," Bansod escreveu. "haz.io [um site que avalia se seu navegador suporta padrões web emergentes] reporta que o WebGL é suportado pela versão mobile do Safari, mas, quando usamos o repositório de exemplos Khronos para testar, foi impossível fazer com que algum dos exemplos funcionasse."&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Performance web&lt;/b&gt;&lt;br /&gt;
Para avaliar a performance web do novo iPad, a &lt;b&gt;Sencha&lt;/b&gt; executou um conjunto de testes comparativos específicos da web usando um novo iPad, um iPad 2 (ambos com iOS 5.1), um tablet Motorola Xoom com Android 3.0, e um RIM PlayBook com Tablet OS 1.0. A equipe de Bansod executou o teste SunSpider e o V8 Benchmark Suite para medir o poder de processamento de códigos JavaScript.&lt;br /&gt;
&lt;br /&gt;
Como é sabido, o novo iPad usa uma versão do chip dual-core A5 da Apple, com um novo processador gráfico quadcore.&lt;br /&gt;
&lt;br /&gt;
No geral, o novo iPad (apelidado "Retina iPad" nos resultados dos testes da Sencha) foi um pouco mais lento em 6 dos 9 testes SunSpider. Nos sete testes do V8, o novo iPad empatou com o iPad 2 mas ambos perderam do tablet da Motorola.&lt;br /&gt;
&lt;br /&gt;
Segundo Bansod, em muito da navegação pela internet, os usuários do novo iPad não verão problemas. Mas a diferença entre os dois iPads é perceptível quando se trata de desenhar páginas complexas. Por exemplo, o novo iPad estava visivelmente carregando novos blocos na parte de baixo de uma página de exemplo enquanto a página era rolada, coisa que raramente ocorria com o iPad 2.&lt;br /&gt;
&lt;br /&gt;
Ele especula que uma razão para o patamar de desempenho do novo iPad é que a Apple acrescentou o processador gráfico quad-core e mais memória, mas não tornaram a memória mais rápida. Isso significaria, diz ele, que jogar imagens e outros recursos gráficos para a GPU está consumindo mais tempo e banda do que o dispositivo pode manipular em tempo real.
&lt;/div&gt;
&lt;br/&gt;
A matéria original em inglês pode ser acessada &lt;a href="http://akamai.infoworld.com/d/mobile-technology/new-ipad-complicates-life-html5-developers-190266?source=rss_application_development"&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://akamai.infoworld.com/d/mobile-technology/new-ipad-complicates-life-html5-developers-190266?source=rss_application_development"&gt;New iPad complicates life for HTML5 developers&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/mR1eMlQGreY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/1880197552433467840/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/04/novo-ipad-complica-vida-dos.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/1880197552433467840?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/1880197552433467840?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/mR1eMlQGreY/novo-ipad-complica-vida-dos.html" title="Novo IPad complica a vida dos desenvolvedores 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/2012/04/novo-ipad-complica-vida-dos.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMASHw7eCp7ImA9WhJWFEU.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-6366137310286186787</id><published>2012-04-03T14:02:00.000-03:00</published><updated>2012-08-20T14:40:49.200-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-08-20T14:40:49.200-03: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="Registry" /><title>Preparando aplicações Delphi para requerer incremento no Nível de Execução</title><content type="html">Desde o Windows XP, a Microsoft vem implementando medidas que dificultam o acesso não autorizado a certos recursos do sistema, como o &lt;a href="http://en.wikipedia.org/wiki/Windows_Registry"&gt;Registry&lt;/a&gt;, por exemplo. O intuito é incrementar a segurança do sistema operacional, evitando seu comprometimento ou até mesmo o roubo de informações. Esse esforço foi mais notado no Windows Vista, quando foi introduzido o &lt;a href="http://en.wikipedia.org/wiki/User_Account_Control"&gt;UAC&lt;/a&gt; (User Account Control) para solicitar ao usuário permissão para acessar os recursos.&lt;br&gt;
&lt;br&gt;
Com essa mudança, programas que antes liam tranquilamente o registro do Windows deixaram de funcionar. Dependendo de como o programa foi implementado, a exceção levantada pela falta de privilégio de acesso ao recurso pode até mesmo derrubar a aplicação com mensagens de erro pouco amistosas. O quadro abaixo traz um exemplo de código em Delphi que executa sem problemas no XP mas que não funcionará no Vista e no Win7 - a menos que o usuário comande a execução como Administrador:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;procedure&lt;/span&gt; TForm1.BitBtn1Click(Sender: TObject);&lt;br/&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;var&lt;/span&gt; lReg: TRegistry;&lt;br/&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;begin&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;lReg := TRegistry.Create();&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;try&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;lReg.RootKey := HKEY_LOCAL_MACHINE;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;lReg.OpenKey(&lt;span style="color:maroon;"&gt;'Software\empresa'&lt;/span&gt;, &lt;span style="bold;color:blue;"&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;lReg.WriteString(&lt;span style="color:maroon;"&gt;'TipoImpressora'&lt;/span&gt;, &lt;span style="color:maroon;"&gt;'0'&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:2em;"&gt;Application.MessageBox(&lt;span style="bold;color:maroon;"&gt;'Opção gravada com sucesso'&lt;/span&gt;, &lt;span style="color:maroon;"&gt;'Aviso'&lt;/span&gt;, MB_OK);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;except&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;on&lt;/span&gt; Erro: Exception &lt;span style="font-weight:bold;color:navy;"&gt;do&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
      &lt;span style="margin-left:2em;"&gt;Application.ShowException(Erro);&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="font-weight:bold;color:navy;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
  &lt;span style="margin-left:1em;"&gt;lReg.Free;&lt;/span&gt;&lt;br/&gt;
&lt;span style="font-weight:bold;color:navy;"&gt;end&lt;/span&gt;;
&lt;/div&gt;
Felizmente, há um meio de informar ao sistema operacional que uma operação dessa natureza vai ocorrer e que, portanto, o usuário necessitará obrigatoriamente de privilégios de administrador para executar o programa. Esse processo é chamado de &lt;b&gt;Requisição de Elevação do Nível de Execução&lt;/b&gt; e é feito através de um arquivo de manifesto que deve ser linkado junto com a aplicação.&lt;br/&gt;
&lt;br/&gt;
O manifesto é um arquivo XML com estrutura bem definida, como a mostrada no quadro abaixo:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;
&lt;span style="bold;color:blue;"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&amp;gt;&lt;/span&gt;&lt;br&gt;
&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;assembly xmlns=&lt;/span&gt;"urn:schemas-microsoft-com:asm.v1" &lt;span style="color:maroon;"&gt;manifestVersion=&lt;/span&gt;"1.0"&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;
&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;assemblyIdentity&lt;/span&gt;&lt;br&gt;
    &lt;span style="margin-left:3em;"&gt;&lt;span style="color:maroon;"&gt;name=&lt;/span&gt;"ABC71.TesteManifest"&lt;/span&gt;&lt;br&gt;
    &lt;span style="margin-left:3em;"&gt;&lt;span style="color:maroon;"&gt;processorArchitecture=&lt;/span&gt;"x86"&lt;/span&gt;&lt;br&gt;
    &lt;span style="margin-left:3em;"&gt;&lt;span style="color:maroon;"&gt;version=&lt;/span&gt;"1.0.0.0"&lt;/span&gt;&lt;br&gt;
    &lt;span style="margin-left:3em;"&gt;&lt;span style="color:maroon;"&gt;type=&lt;/span&gt;"win32"/&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;v3:trustInfo xmlns:v3=&lt;/span&gt;"urn:schemas-microsoft-com:asm.v3"&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;v3:security&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
      &lt;span style="margin-left:2em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;v3:requestedPrivileges&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
        &lt;span style="margin-left:3em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;v3:requestedExecutionLevel level=&lt;/span&gt;"requireAdministrator"&lt;span style="color:maroon;"&gt; uiAccess=&lt;/span&gt;"false"/&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
      &lt;span style="margin-left:2em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:maroon;"&gt;v3:requestedPrivileges&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:maroon;"&gt;v3:security&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:maroon;"&gt;v3:trustInfo&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;
&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;description&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;TesteManifest&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:maroon;"&gt;description&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;
&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;/&lt;span style="color:maroon;"&gt;assembly&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;

&lt;/div&gt;
O manifesto é composto de duas partes obrigatórias. O &lt;b&gt;assembly&lt;/b&gt; é o nó raiz do XML, usado para aninhar as demais tags com as configurações em si. A tag interna &lt;b&gt;assemblyIdentity&lt;/b&gt; identifica nossa aplicação, armazenando um nome único para ela e informando sua versão e a arquitetura para a qual ela foi desenhada. No exemplo, vemos que a nossa aplicação é &lt;i&gt;Win32&lt;/i&gt; e roda em processadores &lt;i&gt;x86&lt;/i&gt;.&lt;br/&gt;
&lt;br/&gt;
As outras tags são opcionais mas o nosso exemplo inclui também a tag &lt;b&gt;v3:trustInfo&lt;/b&gt;, que é onde registramos a  requisição do incremento de nível de execução. Tal requisição é feita no parâmetro &lt;b&gt;level&lt;/b&gt; da &lt;i&gt;tag&lt;/i&gt; &lt;b&gt;requestedExecutionLevel&lt;/b&gt;, seguindo a estrutura mostrada acima. Quando informamos o valor &lt;b&gt;requireAdministrator&lt;/b&gt; em &lt;b&gt;level&lt;/b&gt; estamos dizendo ao Windows que o programa só pode executar se tiver privilégios de administrador. Então, antes de executá-lo, o Windows apresentará a tela para que o usuário forneça as credenciais do administrador - nome e senha - e só prosseguirá se elas estiverem corretas.&lt;br/&gt;
&lt;br/&gt;
Para que essa configuração tenha efeito, precisamos criar um &lt;a href="http://en.wikipedia.org/wiki/Resource_%28Windows%29"&gt;arquivo de recursos&lt;/a&gt; que aponta o manifesto e então, linká-lo ao programa Delphi. Um arquivo de recursos é um repositório onde são indicadas informações a serem agregadas a um programa, permitindo adicionar desde ícones e cursores até blocos de texto e dados binários para uso da aplicação. O arquivo de recurso pode ter extensão RC (quando é somente um texto) ou RES (resultado da compilação do RC). Supondo que o arquivo de manifesto se chame &lt;i&gt;manifesto.manifest&lt;/i&gt;, um arquivo RC pode ser montado assim:&lt;br/&gt;
&lt;div style="font-size:9pt;font-family:Courier New;border:1px solid silver;padding: 5px 10px 1em 5px;width: 98%;"&gt;
&lt;span style="color:green;"&gt;#define MANIFEST_RESOURCE_ID 1&lt;/span&gt;&lt;br /&gt;
MANIFEST_RESOURCE_ID &lt;span style="color:blue;"&gt;24&lt;/span&gt; manifesto.manifest
&lt;/div&gt;
O número 24 nesse arquivo indica ao Windows que o recurso em questão é um arquivo de manifesto. O arquivo RC deve ser adicionado ao projeto do Delphi e o arquivo de manifesto deve estar disponível na mesma pasta. Lembre-se que o Delphi cria automaticamente um arquivo RES com o mesmo nome do projeto; então, escolha um nome diferente do projeto para o RC extra.&lt;br/&gt;
&lt;br/&gt;
Essa requisição de elevação de nível é especialmente útil em programas para configuração ou instalação de sistemas, situações que geralmente exigem privilégios mais altos para acesso a recursos protegidos, mais sensíveis. Na verdade, arquivos de manifesto são mais complexos do que o que foi apresentado aqui, servindo também para indicar se uma aplicação utilizará temas do Windows, se essa aplicação tem dependências de bibliotecas externas, entre outras coisas. O &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa374191%28v=vs.85%29.aspx"&gt;MSDN&lt;/a&gt; documenta o conteúdo permitido para esses arquivos &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa374191%28v=vs.85%29.aspx"&gt;neste link&lt;/a&gt;.&lt;br/&gt;
&lt;br/&gt;
Versões mais recentes do Delphi permitem utilizar temas na criação de aplicações e, por isso, elas embutem automaticamente um manifesto em cada projeto. Assim, para conseguir inserir a requisição de incremento do nível de execução nestas versões, é preciso modificar a configuração do projeto, pedindo que se considere um arquivo de manifesto externo ao invés daquele que vem por padrão. Na página de &lt;a href="http://docwiki.embarcadero.com/RADStudio/en/Application_Options"&gt;configuração da aplicação&lt;/a&gt; - a mesma onde se muda o ícone do seu programa, selecione a opção &lt;b&gt;"Use Custom Manifest"&lt;/b&gt; na caixa &lt;b&gt;Runtime Themes&lt;/b&gt;. Depois, informe o caminho do seu arquivo de manifesto na caixa &lt;b&gt;Custom Manifest&lt;/b&gt;, logo abaixo.&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/bb756929.aspx"&gt;Create and Embed an Application Manifest (UAC)&lt;/a&gt;,
&lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa374191%28v=vs.85%29.aspx"&gt;Referência de Arquivos de Manifesto para Aplicações&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/User_Account_Control"&gt;User Account Control&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/dnA9-REEoDQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/6366137310286186787/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/04/configurando-nivel-de-execucao.html#comment-form" title="7 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/6366137310286186787?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/6366137310286186787?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/dnA9-REEoDQ/configurando-nivel-de-execucao.html" title="Preparando aplicações Delphi para requerer incremento no Nível de Execução" /><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/2012/04/configurando-nivel-de-execucao.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8FRnw-eyp7ImA9WhVRFU4.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-4255803880728733692</id><published>2012-03-23T13:11:00.000-03:00</published><updated>2012-03-23T18:23:37.253-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-23T18:23:37.253-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><title>Trabalhando com rotinas T-SQL no SQL Server</title><content type="html">O &lt;a href="http://pt.wikipedia.org/wiki/SQL"&gt;SQL&lt;/a&gt; (Structured Query Language) é muito mas que apenas uma linguagem para manutenções num banco de dados. Ela não se restringe às quatro operações básicas (INSERT, DELETE, UPDATE e SELECT) ou àquelas funções para gerenciar tabelas ou transações. O SQL Server da Microsoft, por exemplo, implementa uma extensão do padrão SQL chamada &lt;b&gt;T-SQL&lt;/b&gt; (&lt;a href="http://en.wikipedia.org/wiki/Transact-SQL"&gt;Transact SQL&lt;/a&gt;) que permite construir funções complexas. Elas combinam queries com elementos típicos das linguagens de programação comuns, fornecendo uma sintaxe que inclui variáveis, &lt;i&gt;loops&lt;/i&gt; e controle de fluxo.&lt;br /&gt;
&lt;br /&gt;
Com essa linguagem, você pode construir &lt;a href="http://msdn.microsoft.com/en-us/library/ms189799.aspx"&gt;Triggers&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/ms187926(SQL.100).aspx"&gt;Stored Procedures&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/ms186755.aspx"&gt;Functions&lt;/a&gt; ou simplesmente executar comandos pelo &lt;b&gt;SQL Server Management Studio&lt;/b&gt; (função antigamente disponível no &lt;b&gt;Query Analyser&lt;/b&gt;). Neste post, vou usar essa ferramenta para mostrar alguns dos recursos do &lt;b&gt;T-SQL&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Para montarmos o exemplo básico, considere que vamos gerar uma lista de preços baseada nas informações contidas numa tabela chamada &lt;b&gt;LISTAPR&lt;/b&gt;, criada de acordo com o comando a seguir:&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:green;"&gt;-- Em SQL Server&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:blue;"&gt;create table&lt;/span&gt; LISTAPR&lt;br /&gt;(&lt;br /&gt;
&lt;span style="margin-left:1em;"&gt;ID &lt;span style="color:blue;"&gt;int&lt;/span&gt; not null,&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:1em;"&gt;PRODUTO &lt;span style="color:blue;"&gt;varchar&lt;/span&gt;(25) null,&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:1em;"&gt;DESCRICAO &lt;span style="color:blue;"&gt;varchar&lt;/span&gt;(255) null,&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:1em;"&gt;PRECO &lt;span style="color:blue;"&gt;numeric&lt;/span&gt;(15,4) null,&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:1em;"&gt;DATA_VLD &lt;span style="color:blue;"&gt;smalldatetime&lt;/span&gt; null&lt;/span&gt;&lt;br /&gt;
)&lt;/div&gt;&lt;br /&gt;
Como toda linguagem, o &lt;b&gt;T-SQL&lt;/b&gt; possui comandos de declaração de variáveis para armazenar valores ao longo do programa. Basicamente, os &lt;a href="http://msdn.microsoft.com/pt-br/library/ms187752.aspx"&gt;tipos de dados permitidos&lt;/a&gt; são os mesmos que são válidos para criação de campos num tabela, com exceção dos tipos que representam &lt;b&gt;BLOB&lt;/b&gt;s (&lt;i&gt;text&lt;/i&gt;, &lt;i&gt;ntext&lt;/i&gt; e &lt;i&gt;image&lt;/i&gt;). A declaração em si é feita com a palavra chave &lt;a href="http://msdn.microsoft.com/pt-br/library/ms188927.aspx"&gt;DECLARE&lt;/a&gt; seguida de um arroba (@) acompanhando o nome da variável e, para finalizar, o tipo de dado que essa variável será capaz de armazenar. Exemplos:&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:blue;"&gt;DECLARE&lt;/span&gt; @produto &lt;span style="color:blue;"&gt;varchar&lt;/span&gt;(25)&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:blue;"&gt;DECLARE&lt;/span&gt; @descricao &lt;span style="color:blue;"&gt;varchar&lt;/span&gt;(255)&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:blue;"&gt;DECLARE&lt;/span&gt; @preco &lt;span style="color:blue;"&gt;numeric&lt;/span&gt;(15,4)&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:blue;"&gt;DECLARE&lt;/span&gt; @linha &lt;span style="color:blue;"&gt;varchar&lt;/span&gt;(300)&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:blue;"&gt;DECLARE&lt;/span&gt; @nro_regs &lt;span style="color:blue;"&gt;int&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; @nro_regs = 0&lt;/span&gt;
&lt;/div&gt;&lt;br /&gt;
A forma como os valores são recuperados do banco de dados nos obriga a declarar variáveis para os campos que pretendemos manipular. Assim, no trecho acima eu declarei uma variável para cada campo que será impresso. Como se vê também, o comando &lt;b&gt;SELECT&lt;/b&gt; pode ser usado para atribuir manualmente valores para as variáveis.&lt;br /&gt;
&lt;br /&gt;
Há um tipo especial de variável para ser usado na obtenção de um &lt;i&gt;result set&lt;/i&gt; (lista de registros). O nome desse tipo é &lt;b&gt;CURSOR&lt;/b&gt; e é através dele que estabelecemos quais dados serão recuperados do banco, qual o tipo de navegação será permitida nos registros (apenas avançar ou ir pra frente e pra trás) e também se será possível atualizar os dados. Para o cenário proposto neste &lt;i&gt;post&lt;/i&gt;, precisaremos de uma coleção &lt;i&gt;read-only&lt;/i&gt; que contenha todos os registros da tabela &lt;b&gt;LISTAPR&lt;/b&gt; que estejam dentro da validade. A declaração abaixo atende esses requisitos:&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;DECLARE&lt;/span&gt; lista &lt;span style="color:blue;"&gt;CURSOR SCROLL FOR&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:4em;"&gt;&lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; produto, descricao, preco&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:4em;"&gt;&lt;span style="color:blue;"&gt;FROM&lt;/span&gt; LISTAPR&lt;/span&gt;&lt;br/&gt;
  &lt;span style="margin-left:4em;"&gt;&lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; DATA_VLD &gt; &lt;span style="color:fuchsia;"&gt;GETDATE&lt;/span&gt;() &lt;span style="color:blue;"&gt;OR&lt;/span&gt; DATA_VLD &lt;span style="color:gray;"&gt;IS NULL&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;br /&gt;
O tipo da navegação é irrelevante aqui mas eu inclui a palavra &lt;b&gt;SCROLL&lt;/b&gt; na declaração, possibilitando a navegação pelos registros em qualquer direção que queiramos. Outro detalhe é que eu estipulei quais campos eu quero recuperar. Isso é uma boa prática pois, conforme veremos adiante, deixa claro quais campos corresponderão a quais variáveis.&lt;br /&gt;
&lt;br /&gt;
Agora, podemos abrir o cursor criado, navegar pela lista de registros obtidos, processar os dados conforme necessário e, finalmente, encerrar o cursor. O quadro abaixo traz o código com os passos citados:&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;OPEN&lt;/span&gt; lista&lt;br /&gt;
&lt;span style="color:green;"&gt;-- Primeiro registro&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:blue;"&gt;FETCH FIRST FROM&lt;/span&gt; lista &lt;span style="color:blue;"&gt;INTO&lt;/span&gt; @produto, @descricao, @preco&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:blue;"&gt;WHILE&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;@@FETCH_STATUS&lt;/span&gt; = 0&lt;br /&gt;
&lt;span style="color:blue;"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;-- O processamento do registro atual será feito aqui&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;-- Próximo registro&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:blue;"&gt;FETCH NEXT FROM&lt;/span&gt; lista &lt;span style="color:blue;"&gt;INTO&lt;/span&gt; @produto, @descricao, @preco&lt;/span&gt;&lt;br /&gt;
&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:blue;"&gt;CLOSE&lt;/span&gt; lista&lt;br /&gt;
&lt;span style="color:blue;"&gt;DEALLOCATE&lt;/span&gt; lista
&lt;/div&gt;
&lt;br /&gt;
Vamos destrinchar esse código. O comando &lt;b&gt;OPEN&lt;/b&gt; apenas abre o cursor, submetendo a &lt;i&gt;query&lt;/i&gt; ao banco de dados. O comando &lt;b&gt;FETCH FIRST&lt;/b&gt; posiciona no primeiro registro e transfere para as variáveis os valores obtidos. Veja que a ordem das variáveis na cláusula &lt;b&gt;INTO&lt;/b&gt; segue a mesma ordem estabelecida na cláusula &lt;b&gt;SELECT&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
 A instrução &lt;b&gt;WHILE&lt;/b&gt; é um laço tradicional, repetindo os comandos entre o &lt;b&gt;BEGIN&lt;/b&gt; e o &lt;b&gt;END&lt;/b&gt; enquanto o valor da expressão após o &lt;b&gt;WHILE&lt;/b&gt; for verdadeira. Neste caso, &lt;b&gt;@@FETCH_STATUS&lt;/b&gt; é uma variável nativa do &lt;b&gt;T-SQL&lt;/b&gt;. Ela é afetada pela execução de comandos &lt;b&gt;FETCH&lt;/b&gt;, assumindo valor 0 (zero) quando há um registro válido posicionado. Com isso, o comando &lt;b&gt;FETCH NEXT&lt;/b&gt;, é executado enquanto ainda houver registros a recuperar no cursor.&lt;br /&gt;
&lt;br /&gt;
Para encerrar, o cursor é fechado com o comando &lt;b&gt;CLOSE&lt;/b&gt; e os recursos usados por ele são devolvidos ao sistema através do comando &lt;b&gt;DEALLOCATE&lt;/b&gt;. Variáveis do tipo &lt;b&gt;CURSOR&lt;/b&gt; são as únicas que requerem a desalocação explícita.&lt;br /&gt;
&lt;br /&gt;
Ficou faltando a parte do processamento interno do laço. Como planejamos simplesmente imprimir os valores das variáveis, podemos usar o comando &lt;b&gt;PRINT&lt;/b&gt; para isso. Ele aceita um texto como parâmetro, de modo que teremos que fazer a conversão dos tipos numéricos antes de imprimir.&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;SELECT&lt;/span&gt; @nro_regs = @nro_regs + 1,  @linha = &lt;span style="color:maroon;"&gt;''&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; @linha = @linha + @produto + &lt;span style="color:fuchsia;"&gt;REPLICATE&lt;/span&gt; (&lt;span style="color:maroon;"&gt;' '&lt;/span&gt;, 21 - &lt;span style="color:fuchsia;"&gt;LEN&lt;/span&gt; (@produto))&lt;br /&gt;
  &lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; @linha = @linha + @descricao + &lt;span style="color:fuchsia;"&gt;REPLICATE&lt;/span&gt; (&lt;span style="color:maroon;"&gt;' '&lt;/span&gt;, 21 - &lt;span style="color:fuchsia;"&gt;LEN&lt;/span&gt; (@descricao))&lt;br /&gt;
  &lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; @linha = @linha + &lt;span style="color:fuchsia;"&gt;STR&lt;/span&gt; (@preco, 10, 2)&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="color:fuchsia;"&gt;PRINT&lt;/span&gt; @linha
&lt;/div&gt;
&lt;br /&gt;
Cada chamada ao &lt;b&gt;PRINT&lt;/b&gt; gera uma nova linha na janela de saída do &lt;i&gt;Management Studio&lt;/i&gt;, razão pela qual concateno os valores num único texto antes de imprimí-lo. Assim, cada produto terá sua própria linha. A ginástica com o &lt;a href="http://msdn.microsoft.com/pt-br/library/ms174383.aspx"&gt;REPLICATE&lt;/a&gt; e o &lt;a href="http://msdn.microsoft.com/pt-br/library/ms190329.aspx"&gt;LEN&lt;/a&gt; é para garantir que produto e descrição apareçam sempre com a mesma quantidade de caracteres, mantendo o resultado alinhado, mais fácil de ler. O &lt;a href="http://msdn.microsoft.com/pt-br/library/ms189527.aspx"&gt;STR&lt;/a&gt; converte o preço em um texto para a impressão.&lt;br /&gt;
&lt;br /&gt;
É claro que, dada a simplicidade do exemplo, poderíamos ter resolvido o problema apenas executando a &lt;i&gt;query&lt;/i&gt;. Mas o objetivo aqui era mostrar a flexibilidade da linguagem já que ela permite conter cursores aninhados, trabalhar com decisões de fluxo (instrução &lt;b&gt;IF&lt;/b&gt;), cálculos complexos e outras interações. Aqui na &lt;a href="http://www.abc71.com.br"&gt;ABC71&lt;/a&gt;, nós aproveitamos essa flexibilidade do &lt;b&gt;T-SQL&lt;/b&gt; mesclada a queries que &lt;a href="http://balaiotecnologico.blogspot.com.br/2010/04/obtendo-informacoes-sobre-as-tabelas-de.html"&gt;obtêm informações sobre tabelas do banco de dados&lt;/a&gt; para gerar certos tipos de codigo fonte auxiliares de nosso &lt;b&gt;ERP&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;br /&gt;
&lt;a href="http://en.wikipedia.org/wiki/Transact-SQL"&gt;Transact SQL&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/ms174318%28v=sql.105%29.aspx"&gt;Funções nativas T-SQL para SQL Server 2008&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/1ODD9KXXdIc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/4255803880728733692/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/03/criando-rotinas-no-sql-server.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4255803880728733692?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/4255803880728733692?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/1ODD9KXXdIc/criando-rotinas-no-sql-server.html" title="Trabalhando com rotinas T-SQL no SQL Server" /><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/03/criando-rotinas-no-sql-server.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIBQ3g7eCp7ImA9WhVREks.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-7153613079027770951</id><published>2012-03-13T17:42:00.003-03:00</published><updated>2012-03-20T13:22:32.600-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-20T13:22:32.600-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: Visitor - Parte II</title><content type="html">No &lt;a href="http://balaiotecnologico.blogspot.com/2012/02/design-patterns-com-delphi-visitor.html"&gt;último post&lt;/a&gt;, eu apresentei o &lt;a href="http://balaiotecnologico.blogspot.com/2012/02/design-patterns-com-delphi-visitor.html"&gt;conceito do Design Pattern &lt;b&gt;Visitor&lt;/b&gt;&lt;/a&gt; usando para isso um diagrama UML com um exemplo prático da aplicabilidade do padrão. O exemplo consiste na representação de um &lt;i&gt;Produto Acabado&lt;/i&gt; composto por uma lista de recursos (as matérias primas, máquinas e instruções) usados para fabricá-lo. O objetivo é permitir aplicar ao produto operações externas cujo resultado depende da aplicação da operação em cada parte que compõe a estrutura. No exemplo, há duas operações: uma que exporta a arquitetura do produto em formato XML e outra que faz a impressão dessa estrutura.&lt;br /&gt;
&lt;br /&gt;
Neste &lt;i&gt;post&lt;/i&gt;, mostro uma sugestão de implementação em Delphi para o exemplo do &lt;b&gt;Visitor&lt;/b&gt;. Para facilitar a referência, publico novamente o diagrama que o retrata:&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/Visitor.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;width:100%;" src="http://lgaf.webs.com/arqs/Visitor.gif" alt="Diagrama UML para o padrão Visitor" id="designPatternVisitor20120301" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
O primeiro passo é definir as classes que representam o propósito do sistema, estabelecendo as regras de negócio que constituirão o cerne dele. No nosso caso, essas classes são o recurso de produção, suas heranças e o produto acabado. O quadro abaixo mostra as declarações delas, que são bastante simples :
&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:green;"&gt;{ Recursos para a produção }&lt;/span&gt;&lt;br/ &gt;
  TWRecursoProducao=&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;public&lt;/b&gt;&lt;/span&gt;&lt;br/ &gt;
    &lt;span style="margin-left:1em;"&gt;_Nome: String;&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;Constructor&lt;/b&gt;&lt;/span&gt; Create (ANome: String);&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;procedure&lt;/b&gt;&lt;/span&gt; Accept (AOper: TWOperacoesPA);&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="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br/ &gt;
  &lt;br/ &gt;
  TWMateriaPrima=&lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWRecursoProducao)&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;_CProd: String;&lt;/span&gt;&lt;br/ &gt;
    &lt;span style="margin-left:1em;"&gt;_Qtde: Double;&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;Constructor&lt;/b&gt;&lt;/span&gt; Create (ANome: String);&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; Accept (AOper: TWOperacoesPA);&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;
  TWMaquina=&lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWRecursoProducao)&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;_Cod: String;&lt;/span&gt;&lt;br/ &gt;
    &lt;span style="margin-left:1em;"&gt;_Tempo: Double;&lt;/span&gt;&lt;br/ &gt;
    &lt;span style="margin-left:1em;"&gt;_TempoSetup: Double;&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;Constructor&lt;/b&gt;&lt;/span&gt; Create (ANome: String);&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; Accept (AOper: TWOperacoesPA);&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;
  TWRoteiro=&lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWRecursoProducao)&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;_Cod: String;&lt;/span&gt;&lt;br/ &gt;
    &lt;span style="margin-left:1em;"&gt;_Texto: String;&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;Constructor&lt;/b&gt;&lt;/span&gt; Create (ANome: String);&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; Accept (AOper: TWOperacoesPA);&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:green;"&gt;{ Produto Acabado }&lt;/span&gt;&lt;br/ &gt;
  TWProdutoAcabado=&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;_MatPrimas : TObjectList;&lt;/span&gt;&lt;br/ &gt;
    &lt;span style="margin-left:1em;"&gt;_Maquinas : TObjectList;&lt;/span&gt;&lt;br/ &gt;
    &lt;span style="margin-left:1em;"&gt;_Roteiro : TWRoteiro;&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; ClearListaRec (ALista: TObjectList);&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;_Nome: String;&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;Constructor&lt;/b&gt;&lt;/span&gt; Create (ANome: String);&lt;/span&gt;&lt;br/ &gt;
    &lt;span style="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;Destructor&lt;/b&gt;&lt;/span&gt; Destroy; &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="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; ClearRecursos;&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; AddMatPrima (ARecurso: TWRecursoProducao);&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; AddMaquina (ARecurso: TWRecursoProducao);&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; SetRoteiro (ARoteiro: TWRoteiro);&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; DoOperacao (AOper: TWOperacoesPA);&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 classe que representa o produto acabado (&lt;b&gt;TWProdutoAcabado&lt;/b&gt;) possui membros do tipo &lt;b&gt;TObjectList&lt;/b&gt; e também um roteiro separado. Esses membros armazenarão os recursos necessários para fabricar o produto acabado. Neste exemplo, as classes que compõem a agregação são heranças de uma mesma classe base - a &lt;b&gt;TWRecursoProducao&lt;/b&gt; - mas o padrão &lt;b&gt;Visitor&lt;/b&gt; não faz essa exigência. Assim, ele ainda é aplicável mesmo quando a agregação é composta por classes que não guardam relação entre si. Então, usei variáveis separadas pra cada tipo de recurso apenas para deixar clara essa possibilidade.&lt;br/ &gt;
&lt;br/ &gt;
Repare ainda na função &lt;b&gt;Accept&lt;/b&gt; introduzida na classe base de recursos. É ela quem define a família de classes como &lt;b&gt;Visitable&lt;/b&gt;, determinando que os recursos de produção que elas representam poderão ser visitados por qualquer operação externa herdada de &lt;b&gt;TWOperacoesPA&lt;/b&gt;. Na verdade, &lt;b&gt;Accept&lt;/b&gt; simplesmente solicitará à operação que "visite" o recurso em questão, o que fará com que a operação seja aplicada ao recurso :&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; TWMateriaPrima.Accept (AOper: TWOperacoesPA);&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;AOper.Visit (Self);&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; TWMaquina.Accept (AOper: TWOperacoesPA);&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;AOper.Visit (Self);&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; TWRoteiro.Accept (AOper: TWOperacoesPA);&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;AOper.Visit (Self);&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 seguir, podemos definir a hierarquia de classes que implementarão as operações externas nos recursos de produção. Tais classes exercerão o papel de &lt;b&gt;Visitors&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;
   TWOperacoesPA=&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;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; InitOper(AInfo: TObject);&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;procedure&lt;/b&gt;&lt;/span&gt; TermOper;&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="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; Visit (pRecurso: TWMateriaPrima);&lt;span style="color:navy;"&gt;&lt;b&gt;overload&lt;/b&gt;&lt;/span&gt;;&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;procedure&lt;/b&gt;&lt;/span&gt; Visit (pRecurso: TWMaquina);&lt;span style="color:navy;"&gt;&lt;b&gt;overload&lt;/b&gt;&lt;/span&gt;;&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;procedure&lt;/b&gt;&lt;/span&gt; Visit (pRecurso: TWRoteiro);&lt;span style="color:navy;"&gt;&lt;b&gt;overload&lt;/b&gt;&lt;/span&gt;;&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="color:navy;"&gt;&lt;b&gt;end&lt;/b&gt;&lt;/span&gt;;&lt;br/ &gt;
&lt;br/ &gt;
   TWRecursoSaveToXml=&lt;span style="color:navy;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;(TWOperacoesPA)&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;_Xml : String;&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; InitOper(AInfo: TObject);&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; TermOper;&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="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;procedure&lt;/b&gt;&lt;/span&gt; Visit (pRecurso: TWMateriaPrima);&lt;span style="color:navy;"&gt;&lt;b&gt;overload&lt;/b&gt;&lt;/span&gt;;&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; Visit (pRecurso: TWMaquina);&lt;span style="color:navy;"&gt;&lt;b&gt;overload&lt;/b&gt;&lt;/span&gt;;&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; Visit (pRecurso: TWRoteiro);&lt;span style="color:navy;"&gt;&lt;b&gt;overload&lt;/b&gt;&lt;/span&gt;;&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="margin-left:1em;"&gt;&lt;span style="color:navy;"&gt;&lt;b&gt;function&lt;/b&gt;&lt;/span&gt; GetXML : String;&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 operação para imprimir o produto acabado é bastante similar à de salva para XML e, por isso, eu a omiti do quadro.&lt;br/ &gt;
&lt;br/ &gt;
Veja que a classe &lt;b&gt;TWOperacoesPA&lt;/b&gt;, que é base para todas as operações, possui 3 métodos &lt;b&gt;Visit&lt;/b&gt; &lt;a href="http://pt.wikipedia.org/wiki/Sobrecarga"&gt;sobrecarregados&lt;/a&gt; (&lt;b&gt;overload&lt;/b&gt;). Cada um deles trata um tipo diferente de recurso, o que, na prática, nos permite adequar o comportamento da operação. Isso quer dizer que a operação será realizada de um modo coerente com o tipo do recurso.&lt;br/ &gt;
&lt;br/ &gt;
Um outro detalhe nessa classe é a função &lt;b&gt;InitOper&lt;/b&gt;. Ela é desenhada para realizar procedimentos iniciais da operação, aceitando um parâmetro genérico do tipo &lt;a href="http://docwiki.embarcadero.com/VCL/XE2/en/System.TObject"&gt;TObject&lt;/a&gt; com informações que façam sentido para a operação. Por exemplo, pode representar uma impressora para a operação de Imprimir ou um objeto &lt;a href="http://en.wikipedia.org/wiki/Document_Object_Model"&gt;DOM&lt;/a&gt; para a exportação em formato XML.&lt;br/ &gt;
&lt;br/ &gt;
O trecho de código abaixo mostra as funções de inicialização e encerramento da operação de exportação para XML. Também retrata a versão da função &lt;b&gt;Visit&lt;/b&gt; sobrecarregada para os tipos de recurso "Matéria Prima" e "Máquina":
&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; TWRecursoSaveToXml.InitOper(AInfo: TObject);&lt;br/ &gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; lProd: TWProdutoAcabado;&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;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{Abre a tag raiz para o XML }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lProd := AInfo   &lt;span style="color:navy;"&gt;&lt;b&gt;As&lt;/b&gt;&lt;/span&gt; TWProdutoAcabado;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := &lt;span style="color:maroon;"&gt;'&amp;lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'&amp;lt;produtoAcabado name="'&lt;/span&gt; + lProd._Nome + &lt;span style="color:maroon;"&gt;'"&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&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;procedure&lt;/b&gt;&lt;/span&gt; TWRecursoSaveToXml.TermOper;&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;{ Fecha a tag XML raiz }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'&amp;lt;/produtoAcabado&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;inherited&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;procedure&lt;/b&gt;&lt;/span&gt; TWRecursoSaveToXml.Visit (pRecurso: TWMateriaPrima);&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;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Versão específica dessa operação p/ o recurso "Matéria Prima" }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'  &amp;lt;materiaPrima&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'    &amp;lt;codigo&gt;'&lt;/span&gt; + pRecurso._CProd + &lt;span style="color:maroon;"&gt;'&amp;lt;/codigo&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'    &amp;lt;nome&gt;'&lt;/span&gt; + pRecurso._Nome + &lt;span style="color:maroon;"&gt;'&amp;lt;/nome&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'    &amp;lt;qtde&gt;'&lt;/span&gt; + FormatFloat (&lt;span style="color:maroon;"&gt;'#,##0.00'&lt;/span&gt;, pRecurso._Qtde) + &lt;span style="color:maroon;"&gt;'&amp;lt;/qtde&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'  &amp;lt;/materiaPrima&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&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;procedure&lt;/b&gt;&lt;/span&gt; TWRecursoSaveToXml.Visit (pRecurso: TWMaquina);&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;&lt;span style="color:green;"&gt;{ Versão específica dessa operação p/ o recurso "Máquina" }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'  &amp;lt;maquina&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'    &amp;lt;codigo&gt;'&lt;/span&gt; + pRecurso._Cod + &lt;span style="color:maroon;"&gt;'&amp;lt;/codigo&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'    &amp;lt;nome&gt;'&lt;/span&gt; + pRecurso._Nome + &lt;span style="color:maroon;"&gt;'&amp;lt;/nome&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'    &amp;lt;setup&gt;'&lt;/span&gt; + FormatFloat (&lt;span style="color:maroon;"&gt;'#,##0.00'&lt;/span&gt;, pRecurso._TempoSetup) + &lt;span style="color:maroon;"&gt;'&amp;lt;/setup&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'    &amp;lt;tempo&gt;'&lt;/span&gt; + FormatFloat (&lt;span style="color:maroon;"&gt;'#,##0.00'&lt;/span&gt;, pRecurso._Tempo) + &lt;span style="color:maroon;"&gt;'&amp;lt;/tempo&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;_XML := _XML + &lt;span style="color:maroon;"&gt;'  &amp;lt;/maquina&gt;'&lt;/span&gt; + &lt;span style="color:maroon;"&gt;#13#10&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;
Por fim, podemos implementar a função que aplica a operação ao produto acabado. Por definição, isso implica aplicar a mesma operação sobre os recursos que compõe esse produto acabado. Por isso, teremos que passar por todos os recursos, chamando a função &lt;b&gt;Accept&lt;/b&gt; para determinar como a operação deve ser executada em cada um deles:
&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; TWProdutoAcabado.DoOperacao (AOper: TWOperacoesPA);&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; i : integer;&lt;br /&gt;
&lt;span style="margin-left:3em;"&gt;lMatPrima: TWMateriaPrima;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:3em;"&gt;lMaquina : TWMaquina;&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;AOper.InitOper (Self);&lt;/span&gt;&lt;br /&gt;
  &lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Aplica a operação a cada matéria prima da lista }&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;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; _MatPrimas.Count - 1 &lt;span style="color:navy;"&gt;&lt;b&gt;do&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;lMatPrima := _MatPrimas.Items[i] &lt;span style="color:navy;"&gt;&lt;b&gt;As&lt;/b&gt;&lt;/span&gt; TWMateriaPrima;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:1em;"&gt;lMatPrima.Accept (AOper);&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;{ Aplica a operação a cada máquina da lista }&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;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; _Maquinas.Count - 1 &lt;span style="color:navy;"&gt;&lt;b&gt;do&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;lMaquina := _Maquinas.Items[i] &lt;span style="color:navy;"&gt;&lt;b&gt;As&lt;/b&gt;&lt;/span&gt; TWMaquina;&lt;/span&gt;&lt;br /&gt;
    &lt;span style="margin-left:2em;"&gt;lMaquina.Accept (AOper);&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;{ Aplica a operação no roteiro, se houver um }&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; (_Roteiro &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;_Roteiro.Accept (AOper);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;AOper.TermOper;&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;{ ... }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color:navy;"&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; lOperacao : TWRecursoSaveToXml;&lt;br /&gt;
&lt;span style="margin-left:3em;"&gt;lProd : TWProdutoAcabado;&lt;/span&gt;&lt;br /&gt;
&lt;span style="margin-left:3em;"&gt;lXml : 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;lProd := TWProdutoAcabado.Create (&lt;span style="color:maroon;"&gt;'Computador'&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;
  &lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lOperacao := TWRecursoSaveToXml.Create;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lProd.DoOperacao(lOperacao);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;&lt;span style="color:green;"&gt;{ Publica o resultado da operação }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
  &lt;span style="margin-left:1em;"&gt;lXml := lOperacao.GetXML ();&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;br /&gt;
&lt;br /&gt;
&lt;/div&gt;
A parte inferior do quadro demonstra como se dá a aplicação de uma operação.&lt;br /&gt;
&lt;br /&gt;
O projeto com esse exemplo pode ser salvo a partir &lt;a href="http://lgaf.webs.com/arqs/Visitor.7z"&gt;desse link&lt;/a&gt;. Ele foi criado em Delphi 2005 mas deve ser possível compilá-lo em outras versões do IDE sem problemas.&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/2012/02/design-patterns-com-delphi-visitor.html"&gt;Design Patterns com Delphi: Visitor - 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;a href="http://lgaf.webs.com/arqs/Visitor.7z"&gt;Download do projeto do exemplo&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/zmyx0B010FA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/7153613079027770951/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/03/design-patterns-com-delphi-visitor.html#comment-form" title="1 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/7153613079027770951?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/7153613079027770951?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/zmyx0B010FA/design-patterns-com-delphi-visitor.html" title="Design Patterns com Delphi: Visitor - 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>1</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2012/03/design-patterns-com-delphi-visitor.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QGRX0-fSp7ImA9WhVTE0s.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-442674857689644878</id><published>2012-02-27T13:48:00.002-03:00</published><updated>2012-02-27T13:48:44.355-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-27T13:48:44.355-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><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: Visitor - Parte I</title><content type="html">Coleções de objetos são uma das estruturas mais comumente usadas na construção de programas de computador. Elas podem aparecer na forma de listas, vetores ou em &lt;a href="http://ootips.org/uml-hasa.html"&gt;agregações e composições&lt;/a&gt;, onde diferentes tipos de objeto são mantidos juntos para representar um objeto mais complexo.&lt;br /&gt;
&lt;br /&gt;
Um dos propósitos que nos leva a agruparmos objetos numa mesma estrutura é facilitar a execução de operações envolvendo as partes que constituem esse objeto. Ou seja, operações nas quais percorreremos todos os elementos e aplicaremos a cada um deles a operação desejada. Nesse processo, a existência de objetos de tipos distintos deve ser levada em conta porque uma mesma operação pode ter significado diferente, dependente do tipo de objeto. Isto nos leva a ter que escolher a versão correta da operação que deve ser executada em cada elemento. Por exemplo, considere que você tem uma classe representando a lista de recursos necessários para fabricar um produto. A lista inclui as matérias primas, as máquinas envolvidas e até roteiros descrevendo o processo de fabricação. Uma operação que imprima a estrutura terá que considerar as diferenças entre cada uma dessas partes pois elas têm informações específicas distintas.&lt;br /&gt;
&lt;br /&gt;
Em princípio, parece que uma herança simples pode resolver a questão. Mas, e se for necessário acrescentar novos tipos de operação, com nomes e parâmetros diferentes - salvar em formato XML, por exemplo ? Teríamos que alterar a estrutura da agregação para que ela comporte a nova operação.&lt;br /&gt;
&lt;br /&gt;
O intuito 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;Visitor&lt;/b&gt; é facilitar a manutenção desse tipo de estrutura heterogênea. Ele nos obriga a manter separada a estrutura de um objeto e os algoritmos das operações que podem ser aplicadas sobre seus componentes. Com isso, podemos introduzir novas operações à estrutura sem que seja preciso modificar as classes onde essas operações serão aplicadas. Em outras palavras, o que o &lt;b&gt;Visitor&lt;/b&gt; propõe é transferir a implementação das operações, removendo-as das classes que compõem a agregação e passando-as para classes próprias. Com isso, preserva-se a estrutura original tanto da agregação quanto das partes que a compõem.&lt;br /&gt;
&lt;br /&gt;
O diagrama abaixo mostra um exemplo prático da aplicabilidade desse padrão. Nele, um &lt;i&gt;Produto Acabado&lt;/i&gt; é composto de uma lista de recursos, incluindo as matérias primas, máquinas e instruções para a fabricação dele. São definidas duas operações externas : uma para exportar a arquitetura do produto para XML e outra para imprimí-la.&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/Visitor.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;width:100%;" src="http://lgaf.webs.com/arqs/Visitor.gif" alt="Diagrama UML para o padrão Visitor" id="designPatternVisitor20120227" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
De acordo com o papel que exercem na implementação de uma solução para o padrão &lt;b&gt;Visitor&lt;/b&gt;, as classes envolvidas são formalmente conhecidas pelos nomes que seguem:&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;O &lt;b&gt;Visitor&lt;/b&gt; é uma abstração que define quais classes de objetos poderão ser submetidas às operações que serão disponibilizadas. Ele faz isso ao introduzir &lt;a href="http://pt.wikipedia.org/wiki/Sobrecarga"&gt;métodos sobrecarregados&lt;/a&gt;, um para cada tipo de elemento da agregação que sofrerá a operação. Por convenção, este método é nomeado &lt;b&gt;&lt;i&gt;Visit&lt;/i&gt;&lt;/b&gt;. No diagrama, este é o papel da classe &lt;b&gt;TWOperacoesPA&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;A implementação das operações em si é feita em classes chamadas &lt;b&gt;Concrete Visitor&lt;/b&gt;. Essas classes são heranças simples do &lt;b&gt;Visitor&lt;/b&gt;, o que significa que elas terão que fornecer sua própria versão de cada método &lt;i&gt;&lt;b&gt;Visit&lt;/b&gt;&lt;/i&gt; definido na classe base. Com isso, a operação tratará de forma condizente os diferentes componentes da coleção. No exemplo, as classes &lt;b&gt;TWRecursoImprimir&lt;/b&gt; e &lt;b&gt;TWRecursoSaveToXml&lt;/b&gt; fazem esse papel.&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;Chamamos de &lt;b&gt;Visitable&lt;/b&gt; (ou &lt;i&gt;Element&lt;/i&gt;) a classe que define um método &lt;b&gt;Accept&lt;/b&gt; capaz de receber uma instância da classe de operação e executar a versão correta do método &lt;i&gt;Visit&lt;/i&gt; dessa operação. Ela, portanto, serve de ponto de entrada da execução, definindo o comportamento esperado para todas as heranças que poderão ser "visitadas". São às vezes chamadas de &lt;i&gt;Element&lt;/i&gt; por coincidir com a classe base dos elementos que compõem uma agregação. A classe que exerce esse papel no diagrama de exemplo é a &lt;b&gt;TWRecursoProducao&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;Os &lt;b&gt;Concrete Visitable&lt;/b&gt; (ou &lt;i&gt;Concrete Element&lt;/i&gt;) são as classes que efetivamente implementam o método &lt;b&gt;Accept&lt;/b&gt;, direcionando a execução da operação para o tipo de objeto que representam. Isto é, chamando o método &lt;i&gt;Visit&lt;/i&gt; correto da operação passada como parâmetro. As classes &lt;b&gt;TWMateriaPrima&lt;/b&gt;, &lt;b&gt;TWMaquina&lt;/b&gt; e &lt;b&gt;TWRoteiro&lt;/b&gt; são exemplos disso no diagrama.&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;Object Structure&lt;/b&gt; é a classe que contém a coleção de elementos sobre os quais uma operação será executada. Ela, então, terá que prover um meio para que a coleção seja percorrida de modo que todos os seus componentes possam ser submetidos à operação desejada. Este é o papel da classe &lt;b&gt;TWProdutoAcabado&lt;/b&gt; no diagrama.&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; é responsável por manter a instância tanto do &lt;b&gt;Object Structure&lt;/b&gt; quanto da operação que será executada. Ela também navega os elementos da estrutura, executando em cada um a operação solicitada.
&lt;/div&gt;
&lt;br /&gt;
O padrão &lt;a href="http://balaiotecnologico.blogspot.com/2010/09/design-patterns-com-delphi-iterator.html"&gt;Iterator&lt;/a&gt; também é projetado para permitir a navegação entre elementos que compõem um objeto. A diferença é que no &lt;b&gt;Iterator&lt;/b&gt; os elementos devem ser herança de uma mesma classe enquanto no &lt;b&gt;Visitor&lt;/b&gt; isso não é obrigatório.&lt;br /&gt;
&lt;br /&gt;
O cenário onde o padrão &lt;b&gt;Visitor&lt;/b&gt; é aplicável se assemelha ao uso de &lt;a href="http://balaiotecnologico.blogspot.com/2009/08/usando-interfaces-em-delphi.html"&gt;interfaces&lt;/a&gt;, já que em ambos os casos, uma estrutura externa estabelece as operações que a classe é capaz de executar. No entanto, interfaces forçam a implementação das operações dentro da classe ao invés de fazê-lo em classes separadas, como no &lt;b&gt;Visitor&lt;/b&gt;. Obviamente, ambos os recursos podem ser utilizados em conjunto para produzir uma solução mais flexível.&lt;br /&gt;
&lt;br /&gt;
Alguns críticos alegam que o &lt;b&gt;Visitor&lt;/b&gt; fere o encapsulamento das classes ao obrigar que parte de seu funcionamento seja delegada a outra classe. Mas, podemos encarar essa classe extra como uma operação distinta, minimizando ou até mesmo eliminando o efeito da quebra de encapsulamento.&lt;br /&gt;
&lt;br /&gt;
No próximo &lt;i&gt;post&lt;/i&gt; eu mostro uma sugestão de implementação desse &lt;i&gt;pattern&lt;/i&gt; 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:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/2Bu0U05DOx4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/442674857689644878/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/02/design-patterns-com-delphi-visitor.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/442674857689644878?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/442674857689644878?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/2Bu0U05DOx4/design-patterns-com-delphi-visitor.html" title="Design Patterns com Delphi: Visitor - 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/2012/02/design-patterns-com-delphi-visitor.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8GRHo_eCp7ImA9WhRaEk8.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-3373424984210286160</id><published>2012-02-14T11:57:00.001-02:00</published><updated>2012-02-14T11:57:05.440-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-14T11:57:05.440-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Internet" /><title>Aplicando recursos de localização em Asp.Net</title><content type="html">por &lt;i&gt;Tiago Oliveira&lt;/i&gt;*&lt;br /&gt;
&lt;br /&gt;
Embora seja referenciado por uma palavra um tanto quanto estigmatizada - globalização - o fato é que o mundo ficou mesmo menor e os fabricantes de aplicações também passaram a levar isso em consideração. Ao planejar a construção de programas e sites, eles têm agora que incluir o conceito de &lt;a href="http://edutechwiki.unige.ch/en/Software_localization"&gt;localização&lt;/a&gt; na arquitetura, de uma forma que a aplicação se adeque à linguagem preferida pelo usuário sem que seja necessária uma reengenharia nas linhas de código.&lt;br /&gt;
&lt;br /&gt;
O ASP.NET possui recursos de localização para que possamos fazer aplicações globalizadas, ou seja, para que a aplicação se adeque à região onde ela está sendo executada. A configuração utilizada pelo ASP.NET é a informada no navegador (no caso do IE, está no seguinte caminho : Opções de Internet/Geral/Idiomas), sendo considerado tanto o &lt;b&gt;Idioma&lt;/b&gt; quanto a &lt;b&gt;Região&lt;/b&gt; estipulados. Segue abaixo um exemplo de configuração:&lt;br /&gt;
&lt;div style="border: 1px solid silver; font-family: Courier New; font-size: 10pt; padding: 5px 10px 1em 5px; width: 96%;"&gt;
&lt;div style="margin-left: 3em;"&gt;
en-US – Inglês região dos EUA.&lt;br /&gt;
pt-BR – Português região do Brasil.
&lt;/div&gt;
&lt;/div&gt;
As duas primeiras letras no código representam o Idioma e as duas últimas a região.&lt;br /&gt;
&lt;br /&gt;
Agora vamos aplicar os recursos de localização disponíveis no ASP.NET para modificar esse comportamento padrão e fornecer um mecanismo para que o usuário opte pelo idioma de sua preferência na própria aplicação. Adicione um &lt;i&gt;WebForm&lt;/i&gt; contendo 2 botões que, no caso, irão representar os possíveis idiomas suportados para visualização da aplicação : português e inglês.&lt;br /&gt;
&lt;br /&gt;
Adicione um outro &lt;i&gt;WebForm&lt;/i&gt; contendo alguns componentes &lt;i&gt;Label&lt;/i&gt;, &lt;i&gt;TextBox&lt;/i&gt;, etc. Para aplicar a localização às páginas da aplicação, o ASP.NET utiliza arquivos de &lt;i&gt;Resources&lt;/i&gt;; por isso, vamos adicionar um arquivo de resource em nossa aplicação: clique no &lt;i&gt;WebForm&lt;/i&gt; e selecione na guia &lt;b&gt;Tools&lt;/b&gt; do Visual Studio a opção &lt;b&gt;“Generate Local Resource”&lt;/b&gt;. Ao escolher essa opção. um arquivo de extensão &lt;b&gt;.RESX&lt;/b&gt; com o mesmo nome da página será gerado dentro de uma pasta chamada &lt;b&gt;App_LocalResources&lt;/b&gt; que será automaticamente adicionada ao seu projeto.&lt;br /&gt;
&lt;br /&gt;
Dentro desse arquivo &lt;b&gt;.RESX&lt;/b&gt; existe a relação de todos os componentes que comportam o recurso de localização, juntamente com a descrição dos campos. No nosso exemplo, esse arquivo irá representar a versão em português da aplicação; para gerarmos o arquivo contendo a versão em inglês, faça uma cópia do arquivo &lt;b&gt;NomeDaSuaPagina.aspx.resx&lt;/b&gt; gerado pelo Visual Studio e altere o nome para &lt;b&gt;NomeDaSuaPagina.aspx.en-US.resx&lt;/b&gt;. Nesse novo arquivo, faça a tradução dos campos para o Inglês.&lt;br /&gt;
&lt;br /&gt;
No &lt;i&gt;WebForm&lt;/i&gt; onde colocamos os 2 botões para identificar os idiomas, iremos passar a localização através de &lt;a href="http://en.wikipedia.org/wiki/Query_string"&gt;Query String&lt;/a&gt;, conforme código abaixo associado ao clique de cada um dos botões:&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;div class="MsoNormal" style="mso-layout-grid-align: none;"&gt;
&lt;span class="GramE"&gt;&lt;span lang="EN-US" style="color: blue; font-family: Consolas; font-size: 9.5pt;"&gt;protected&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt;"&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; ImageButton1_Click(&lt;span style="color: blue;"&gt;object&lt;/span&gt; sender, &lt;span class="SpellE"&gt;&lt;span style="color: #2b91af;"&gt;ImageClickEventArgs&lt;/span&gt;&lt;/span&gt; 
e)&lt;/span&gt;&lt;/div&gt;
&lt;div class="MsoNormal" style="mso-layout-grid-align: none;"&gt;
&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt;"&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div class="MsoNormal" style="mso-layout-grid-align: none; text-indent: 35.4pt;"&gt;
&lt;span class="SpellE"&gt;&lt;span class="GramE"&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt;"&gt;Response.Redirect&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="GramE"&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt;"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="color: #a31515; font-family: Consolas; font-size: 9.5pt;"&gt;"&lt;span class="SpellE"&gt;Conteudo.aspx?Language&lt;/span&gt;=pt-BR"&lt;/span&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt;"&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div class="MsoNormal" style="mso-layout-grid-align: none;"&gt;
&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div class="MsoNormal" style="mso-layout-grid-align: none;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="MsoNormal" style="mso-layout-grid-align: none;"&gt;
&lt;span class="GramE"&gt;&lt;span lang="EN-US" style="color: blue; font-family: Consolas; font-size: 9.5pt;"&gt;protected&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt;"&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; ImageButton2_Click(&lt;span style="color: blue;"&gt;object&lt;/span&gt; sender, &lt;span class="SpellE"&gt;&lt;span style="color: #2b91af;"&gt;ImageClickEventArgs&lt;/span&gt;&lt;/span&gt; 
e)&lt;/span&gt;&lt;/div&gt;
&lt;div class="MsoNormal" style="mso-layout-grid-align: none;"&gt;
&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt;"&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div class="MsoNormal" style="mso-layout-grid-align: none; text-indent: 35.4pt;"&gt;
&lt;span class="SpellE"&gt;&lt;span class="GramE"&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt;"&gt;Response.Redirect&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="GramE"&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt;"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="color: #a31515; font-family: Consolas; font-size: 9.5pt;"&gt;"&lt;span class="SpellE"&gt;Conteudo.aspx?Language&lt;/span&gt;=en-US"&lt;/span&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt;"&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div class="MsoNormal" style="mso-layout-grid-align: none;"&gt;
&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;


Na página &lt;b&gt;Conteudo.aspx&lt;/b&gt; (representando a página principal da aplicação), precisamos inicializar a cultura de exibição para considerar a que passamos por parâmetro e não aquela que está configurada no navegador. Para isso precisamos sobrescrever o método &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.page.initializeculture.aspx"&gt;InitializeCulture&lt;/a&gt; da página e ajustar a variável interna &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.page.uiculture.aspx"&gt;UICulture&lt;/a&gt;, que é a responsável por controlar o idioma em que a aplicação está sendo exibida:&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;div class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"&gt;
&lt;span class="GramE"&gt;&lt;span lang="EN-US" style="color: blue; font-family: Consolas; font-size: 9.5pt; mso-ansi-language: EN-US; mso-bidi-font-family: Consolas;"&gt;protected&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt; mso-ansi-language: EN-US; mso-bidi-font-family: Consolas;"&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; &lt;span class="SpellE"&gt;InitializeCulture&lt;/span&gt;()&lt;/span&gt;&lt;/div&gt;
&lt;div class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"&gt;
&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt; mso-ansi-language: EN-US; mso-bidi-font-family: Consolas;"&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none; text-indent: 35.4pt;"&gt;
&lt;span class="SpellE"&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt; mso-ansi-language: EN-US; mso-bidi-font-family: Consolas;"&gt;UICulture&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt; mso-ansi-language: EN-US; mso-bidi-font-family: Consolas;"&gt; = &lt;span class="SpellE"&gt;&lt;span class="GramE"&gt;Request.QueryString&lt;/span&gt;&lt;/span&gt;&lt;span class="GramE"&gt;[&lt;/span&gt;&lt;span style="color: #a31515;"&gt;"Language"&lt;/span&gt;]; &lt;/span&gt;&lt;/div&gt;
&lt;div class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none; text-indent: 35.4pt;"&gt;
&lt;span class="SpellE"&gt;&lt;span class="GramE"&gt;&lt;span lang="EN-US" style="color: blue; font-family: Consolas; font-size: 9.5pt; mso-ansi-language: EN-US; mso-bidi-font-family: Consolas;"&gt;base&lt;/span&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt; mso-ansi-language: EN-US; mso-bidi-font-family: Consolas;"&gt;.InitializeCulture&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="GramE"&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt; mso-ansi-language: EN-US; mso-bidi-font-family: Consolas;"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt; mso-ansi-language: EN-US; mso-bidi-font-family: Consolas;"&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"&gt;
&lt;span lang="EN-US" style="font-family: Consolas; font-size: 9.5pt; mso-ansi-language: EN-US; mso-bidi-font-family: Consolas;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;


Ao exibir os textos da página, o ASP.Net passará a considerar automaticamente o conteúdo do arquivo &lt;b&gt;.RESX&lt;/b&gt; referente ao idioma e região escolhidos.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="background-color: #e1e1dc; border: 1px solid silver; padding: 10px 5px 10px 5px; text-align: justify; width: 96%;"&gt;
* &lt;b&gt;Tiago Oliveira&lt;/b&gt; é desenvolvedor na &lt;a href="http://www.abc71.com.br/"&gt;ABC71&lt;/a&gt;, onde trabalha com os módulos fiscais, de faturamento e de vendas.&lt;/div&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://edutechwiki.unige.ch/en/Software_localization"&gt;Software localization&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.page.initializeculture.aspx"&gt;InitializeCulture&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Query_string"&gt;Query String&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/XZHlv-MafEk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/3373424984210286160/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/02/aplicando-recursos-de-localizacao-em.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/3373424984210286160?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/3373424984210286160?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/XZHlv-MafEk/aplicando-recursos-de-localizacao-em.html" title="Aplicando recursos de localização em Asp.Net" /><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/02/aplicando-recursos-de-localizacao-em.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUACQXoyeSp7ImA9WhRbGEQ.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-3153377311912839722</id><published>2012-02-10T15:09:00.001-02:00</published><updated>2012-02-10T15:09:20.491-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-10T15:09:20.491-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Notícias" /><title>Microsoft abre extensão do C++ para uso em outros compiladores</title><content type="html">Já há algum tempo que os computadores vêm sendo montados com placas gráficas - as chamadas &lt;a href="http://en.wikipedia.org/wiki/Graphics_processing_unit"&gt;GPU&lt;/a&gt;s - cada vez mais poderosas. No início, elas eram requisitadas apenas por quem apreciava jogos no PC pois esse tipo de software exige cálculos complexos intensos para apresentar a parte gráfica, o que usa massivamente as GPUs. Essa história começou a mudar com o Windows Vista, quando o próprio sistema operacional passou a fazer uso mais intenso da capacidade dessas placas, oferecendo aos usuários uma experiência visualmente mais agradável no uso do computador. Com isso, a preocupação de melhorar a apresentação dos programas aproveitando a GPU entrou na lista das empresas desenvolvedoras de software.&lt;br /&gt;
&lt;br /&gt;
Já que se trata de uma CPU extra no computador, muitas vezes a GPU ainda acaba sendo sub utilizada. Mas, acessar plenamente os recursos das GPUs não é uma tarefa trivial. Atenta a isso, a Microsoft vem trabalhando em uma biblioteca para facilitar a utilização desses recursos por qualquer desenvolvedor.&lt;br /&gt;
&lt;br /&gt;
Na verdade, a solução proposta pela Microsoft é estender a linguagem C++, introduzindo nela uma forma nativa e transparente de se ter acesso aos recursos da GPU, fornecendo junto os mecanismos de controle inerentes à computação paralela -  notadamente, a sincronização de processamentos.&lt;br /&gt;
&lt;br /&gt;
Abaixo segue uma tradução da reportagem publicada pela &lt;a href="http://www.infoworld.com"&gt;Infoworld&lt;/a&gt; dando mais detalhes dos planos da Microsoft. A reportagem original em inglês pode ser acessada no link &lt;a href="https://www.infoworld.com/d/application-development/microsoft-opens-c-extension-other-compilers-185831?source=rss_application_development"&gt;Microsoft opens C++ extension for other compilers&lt;/a&gt;.
&lt;br /&gt;
&lt;div style="border:1px solid silver;padding: 5px 10px 1em 5px;width:98%;background-color:#e9e9fb"&gt;
A Microsoft abriu sua especificação do C++ AMP de modo que ela agora pode ser usada por compiladores de outros fabricantes para aproveitar o poder das GPUs (graphics processing units).&lt;br /&gt;
&lt;br /&gt;
"Estamos vendo cada vez mais gente procurando tirar proveito das GPUs em suas aplicações", disse Tony Goodhew, gerente de produto na Microsoft para o Visual Studio.&lt;br /&gt;
&lt;br /&gt;
A proposta do C++ Accelerated Massive Parallelism (C++ AMP), primeiro desenvolvido para o Visual Studio 11 e liberado junto com a versão preliminar desse software para desenvolvedores em setembro, é permitir que os programadores C++ possam escrever programas que executem em paralelo em ambientes computacionais heterogênios.&lt;br /&gt;
&lt;br /&gt;
Agora, ele é livre para ser utilizado por outros fabricantes de compiladores C++, como a Embarcadero, Intel, e a Free Software Foundation.&lt;br /&gt;
&lt;br /&gt;
Cada vez mais, os fabricantes de GPU, tais como a Nvidia, vêm oferecendo suas GPUs para incrementar a performance de programas, auxiliando a CPU a concluir tarefas que demandam muitos cálculos. Tradicionalmente, programar para computação paralela tem sido uma tarefa complicada, apenas dominada por codificadores altamente especializados que normalmente trabalharam com super computadores em laboratórios ou empresas do mercado financeiro.&lt;br /&gt;
&lt;br /&gt;
Com o C++ AMP, "Não precisarei ser um especialista altamente treinado para alcançar esse hardware," diz Goodhew.&lt;br /&gt;
&lt;br /&gt;
Os engenheiros da Microsoft trabalharam para minimizar a quantidade de mudanças em relação à versão canônica do C++. O C++ AMP realmente traz algumas restrições adicionais necessárias quando se executa um código através de múltiplos processadores. Ele também tem recursos adicionais, como tipos array multidimensionais, bem como suporte para transferência assíncrona em memória, memória compartilhada e sincronização.&lt;br /&gt;
&lt;br /&gt;
Em sua implementação, a Microsoft usou a biblioteca DirectCompute para DirectX do Windows para interagir com as GPUs, embora os fabricantes de compiladores possam se valer de outras interfaces para GPU, como a Cuda da Nvidia. Segundo Goodhew, embora esta versão do AMP tenha sido projetada especificamente para GPUs, ela também assenta as bases para eventualmente suportar outros tipos de aceleradores de hardware.&lt;br /&gt;
&lt;br /&gt;
A especificação está publicada sob a &lt;a href="http://www.microsoft.com/openspecifications/en/us/programs/community-promise/default.aspx"&gt;licença Microsoft Community Promise&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
A Microsoft lançou o C++ AMP em setembro passado, como parte da versão prévia para desenvolvedores do Visual Studio 11, depois de ter anunciado em junho a intenção de abrir a especificação para o mercado. A próxima release do Visual Studio 11 Beta incluirá suporte adicional para a especificação, que &lt;a href="http://blogs.msdn.com/b/nativeconcurrency/archive/2012/02/03/c-amp-open-spec-published.aspx"&gt;foi apresentada pela empresa&lt;/a&gt; sexta-feira na conferência GoingNative 2012 C++, ocorrida semana passada em Redmond, Washington.&lt;br /&gt;
&lt;br /&gt;
A companhia está trabalhando com o comitê de padronização do C++ na esperança de que o grupo usará as ideias do C++ AMP como parte do núcleo da especificação da linguagem C++. Levará um tempo até que isso ocorra, entretanto, dado o longo intervalo entre as atualizações no padrão. A versão mais recente do padrão para o C++, informalmente chamada de C++2011, &lt;a href="http://balaiotecnologico.blogspot.com/2011/08/atualizacao-da-especificacao-do-c-ganha.html"&gt;foi lançada no ano passado&lt;/a&gt;, no que foi a primeira grande mudança em quatro anos.
&lt;/div&gt;
&lt;br /&gt;
O documento com a especificação do C++ AMP está disponível no formato PDF &lt;a href="http://download.microsoft.com/download/4/0/E/40EA02D8-23A7-4BD2-AD3A-0BFFFB640F28/CppAMPLanguageAndProgrammingModel.pdf"&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="https://www.infoworld.com/d/application-development/microsoft-opens-c-extension-other-compilers-185831?source=rss_application_development"&gt;Microsoft opens C++ extension for other compilers&lt;/a&gt;, 
&lt;a href="http://download.microsoft.com/download/4/0/E/40EA02D8-23A7-4BD2-AD3A-0BFFFB640F28/CppAMPLanguageAndProgrammingModel.pdf"&gt;Especificação do C++ AMP&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/zvsdA7o_lsE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/3153377311912839722/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/02/microsoft-abre-extensao-do-c-para-uso.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/3153377311912839722?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/3153377311912839722?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/zvsdA7o_lsE/microsoft-abre-extensao-do-c-para-uso.html" title="Microsoft abre extensão do C++ para uso em outros compiladores" /><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/02/microsoft-abre-extensao-do-c-para-uso.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEABRnk4eip7ImA9WhVSEkQ.&quot;"><id>tag:blogger.com,1999:blog-2614552592180424653.post-6796120470963487464</id><published>2012-01-31T16:46:00.000-02:00</published><updated>2012-03-09T09:39:17.732-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-09T09:39:17.732-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Script" /><category scheme="http://www.blogger.com/atom/ns#" term="Internet" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML" /><title>Informações sobre rotas com a versão 3 da API do Google Maps</title><content type="html">No ano passado eu publiquei dois &lt;i&gt;posts&lt;/i&gt; mostrando como traçar rotas usando a &lt;a href="http://code.google.com/intl/pt-BR/apis/maps/documentation/javascript/"&gt;versão 3 da API do Google Maps&lt;/a&gt;. O primeiro tratava de um &lt;a href="http://balaiotecnologico.blogspot.com/2010/08/tracando-rotas-com-versao-3-da-api-do.html"&gt;cenário básico&lt;/a&gt; onde consideramos um endereço de origem e outro de destino; o segundo avançava um passo ao permitir a inclusão de &lt;a href="http://balaiotecnologico.blogspot.com/2011/02/tracando-rotas-com-versao-3-da-api-do.html"&gt;um ou mais pontos intermediários&lt;/a&gt; ao trajeto. Por razões distintas, várias pessoas me perguntaram como é possível obter a distância total entre a origem e o destino em uma rota, independendo se vamos efetivamente exibir a rota traçada.&lt;br /&gt;
&lt;br /&gt;
Pra refrescar a memória, o quadro a seguir ilustra os comandos e estruturas básicos necessários pra trabalharmos com uma rota.&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;var&lt;/b&gt; directionsService, directionsRenderer;&lt;br/&gt;
&lt;b&gt;var&lt;/b&gt; enderDe, enderAte;&lt;br/&gt;
&lt;br/&gt;
directionsService = &lt;span style="color:blue;"&gt;new&lt;/span&gt; google.maps.DirectionsService();&lt;br/&gt;
directionsRenderer = &lt;span style="color:blue;"&gt;new&lt;/span&gt; google.maps.DirectionsRenderer();&lt;br/&gt;
directionsRenderer.setMap(map);&lt;br/&gt;
&lt;br/&gt;
enderDe = &lt;span style="color:maroon;font-size:8pt;"&gt;'ALAMEDA SANTOS, 1000, SÃO PAULO - SP, 01418-9028'&lt;/span&gt;;&lt;br/&gt;
enderAte =&lt;br/&gt;
 &lt;span style="color:maroon;font-size:8pt;"&gt;'AVENIDA NAÇÕES UNIDAS, 17-17, BAURU - SP, 17013-035'&lt;/span&gt;;&lt;br/&gt;
&lt;br/&gt;
&lt;b&gt;var&lt;/b&gt; request = {&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;origin:endDe, &lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;destination:endPara,&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;travelMode: google.maps.DirectionsTravelMode.DRIVING&lt;/span&gt;&lt;br/&gt;
};&lt;br/&gt;
&lt;br/&gt;
directionsService.route(request, &lt;b&gt;function&lt;/b&gt;(response, status) {&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;b&gt;if&lt;/b&gt; (status == google.maps.DirectionsStatus.OK) {&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;directionsRenderer.setDirections(response);&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;}&lt;/span&gt;&lt;br/&gt;
});)&lt;br/&gt;
&lt;/div&gt;
&lt;br /&gt;
A linha &lt;span style="font-size:10pt;font-family:Courier New;color:navy;"&gt;directionsRenderer.setDirections (response)&lt;/span&gt; usa o objeto &lt;b&gt;response&lt;/b&gt; para traçar automaticamente a rota no mapa. Esse objeto é do tipo &lt;a href="http://code.google.com/intl/pt-BR/apis/maps/documentation/javascript/reference.html#DirectionsResult"&gt;DirectionsResult&lt;/a&gt; e é montado pela função &lt;b&gt;route&lt;/b&gt; antes de ser repassado como &lt;i&gt;response&lt;/i&gt; à nossa função de &lt;a href="http://en.wikipedia.org/wiki/Callback_%28computer_programming%29"&gt;callback&lt;/a&gt;. No entanto, você pode usar manualmente as informações contidas em &lt;i&gt;response&lt;/i&gt; sem que a rota precise ser exibida.&lt;br /&gt;
&lt;br /&gt;
De acordo com a documentação, o &lt;b&gt;DirectionsResult&lt;/b&gt; possui como única propriedade um &lt;i&gt;Array&lt;/i&gt; chamado &lt;b&gt;routes&lt;/b&gt; contendo a lista de rotas encontradas pelo serviço para atender a requisição feita. Cada elemento dessa lista traz detalhes de uma rota específica, descrita na forma de um objeto &lt;a href="http://code.google.com/intl/pt-BR/apis/maps/documentation/javascript/reference.html#DirectionsRoute"&gt;DirectionsRoute&lt;/a&gt;, o que inclui detalhes de cada trecho do trajeto, como a distância de cada um (em metros) e o tempo estimado usando o tipo de locomoção escolhido.&lt;br/&gt;
&lt;br/&gt;
Com isso, podemos facilmente obter a distância a ser percorrida para chegar ao destino usando a rota em questã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;directionsService.route(request, &lt;b&gt;function&lt;/b&gt;(response, status) {&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;b&gt;if&lt;/b&gt; (status == google.maps.DirectionsStatus.OK) {&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;&lt;b&gt;var&lt;/b&gt; distancia;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;&lt;b&gt;var&lt;/b&gt; rota = response.routes[&lt;span style="color:blue;"&gt;0&lt;/span&gt;];&lt;/span&gt; &lt;span style="color:green;"&gt;/* Primeira rota */&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;&lt;b&gt;var&lt;/b&gt; etapa = rota.legs[&lt;span style="color:blue;"&gt;0&lt;/span&gt;];&lt;/span&gt; &lt;span style="color:green;"&gt;/* única etapa dessa rota */&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;distancia = etapa.distance.value;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;alert (&lt;span style="color:maroon;"&gt;'Distância Total =&gt; '&lt;/span&gt; + distancia.toString() + &lt;span style="color:maroon;"&gt;' metros.'&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;}&lt;/span&gt;&lt;br/&gt;
});)&lt;br/&gt;
&lt;/div&gt;
&lt;br /&gt;
A propriedade &lt;b&gt;legs&lt;/b&gt; destrincha cada etapa do trajeto usando objetos do tipo &lt;a href="http://code.google.com/intl/pt-BR/apis/maps/documentation/javascript/reference.html#DirectionsLeg"&gt;DirectionsLeg&lt;/a&gt; para descrevê-las. Por etapa entende-se o deslocamento necessário entre dois endereços. Assim, se você estipulou apenas a origem e o destino, haverá uma única etapa e, por conseguinte, uma única posição em &lt;i&gt;legs&lt;/i&gt;. Por outro lado, se você adicionou pontos de referência usando o &lt;b&gt;waypoints&lt;/b&gt; na requisição (veja &lt;a href="http://balaiotecnologico.blogspot.com/2011/02/tracando-rotas-com-versao-3-da-api-do.html"&gt;esse post&lt;/a&gt; para mais detalhes), haverá uma nova etapa descrevendo como chegar a cada ponto. Nesse caso, será preciso percorrer todas as posições, somando a distância de cada etapa para se obter a distância total da rota:
&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;directionsService.route(request, &lt;b&gt;function&lt;/b&gt;(response, status) {&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;&lt;b&gt;if&lt;/b&gt; (status == google.maps.DirectionsStatus.OK) {&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;&lt;b&gt;var&lt;/b&gt; distancia = &lt;span style="color:blue;"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;&lt;b&gt;var&lt;/b&gt; rota = response.routes[&lt;span style="color:blue;"&gt;0&lt;/span&gt;];&lt;/span&gt; &lt;span style="color:green;"&gt;/* Primeira rota */&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;&lt;b&gt;var&lt;/b&gt; etapa, i;&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;&lt;b&gt;for&lt;/b&gt; (i = &lt;span style="color:blue;"&gt;0&lt;/span&gt;; i &lt; rota.legs.length; i++)&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;{&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:3em;"&gt;&lt;span style="color:green;"&gt;/* Obtem cada etapa */&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:3em;"&gt;etapa = rota.legs[i];&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:3em;"&gt;distancia += etapa.distance.value;&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;}&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;span style="margin-left:2em;"&gt;alert (&lt;span style="color:maroon;"&gt;'Distância Total =&gt; '&lt;/span&gt; + distancia.toString() + &lt;span style="color:maroon;"&gt;' metros.'&lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;
&lt;span style="margin-left:1em;"&gt;}&lt;/span&gt;&lt;br/&gt;
});)&lt;br/&gt;
&lt;/div&gt;
&lt;br /&gt;
O detalhamento do caminho a ser seguido dentro de cada etapa do trajeto pode ser acessado através da propriedade &lt;b&gt;steps&lt;/b&gt;. Cada passo também possui sua distância mas a soma delas já está consolidada na própria etapa (&lt;i&gt;leg&lt;/i&gt;). Tenha em mente que, para certos trajetos, pode acontecer de as informações de distância e duração não estarem disponíveis. Por questão de simplicidade, os &lt;i&gt;scripts&lt;/i&gt; acima não levam isso em conta. Um exemplo completo dos recursos mostrados até agora pode ser visto na página abaixo, cujo código fonte está &lt;a href="http://lgaf.webs.com/arqs/mapadist.html"&gt;neste link&lt;/a&gt;:&lt;br/&gt;
&lt;div&gt;&lt;center&gt;&lt;iframe width='96%' height='560px' frameborder='0' src='http://lgaf.webs.com/arqs/mapadist.html'&gt;&lt;/iframe&gt;&lt;/center&gt;&lt;/div&gt;
&lt;br /&gt;
Um outro ponto importante a ser lembrado é que a função &lt;b&gt;route&lt;/b&gt; é assíncrona. Isto significa que a função de &lt;i&gt;callback&lt;/i&gt; que passamos a ela poderá ser executada depois da linha de código imediatamente seguinte ao &lt;i&gt;route&lt;/i&gt;. Assim, se tiver que comparar as distâncias de várias rotas, terá que montar uma forma de sincronizar os cálculos para que a comparação só ocorra depois da execução de todos os &lt;i&gt;callbacks&lt;/i&gt; envolvidos. Esse efeito normalmente é conseguido através da função &lt;i&gt;javascript&lt;/i&gt; &lt;a href="http://www.w3schools.com/jsref/met_win_setinterval.asp"&gt;setinterval&lt;/a&gt;, verificando a cada segundo, por exemplo, se as rotas já estão prontas.&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;
Traçando rotas com a versão 3 da API do Google Maps - &lt;a href="http://balaiotecnologico.blogspot.com/2010/08/tracando-rotas-com-versao-3-da-api-do.html"&gt;Parte I&lt;/a&gt; e &lt;a href="http://balaiotecnologico.blogspot.com/2011/02/tracando-rotas-com-versao-3-da-api-do.html"&gt;Parte II&lt;/a&gt;, &lt;a href="http://code.google.com/intl/pt-BR/apis/maps/documentation/javascript/"&gt;Google Maps JavaScript API V3&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;div style="width:98%;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;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BalaioTecnolgico/~4/jsZ4nKOtYfY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://balaiotecnologico.blogspot.com/feeds/6796120470963487464/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://balaiotecnologico.blogspot.com/2012/01/informacoes-sobre-rotas-com-versao-3-da.html#comment-form" title="29 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/6796120470963487464?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2614552592180424653/posts/default/6796120470963487464?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BalaioTecnolgico/~3/jsZ4nKOtYfY/informacoes-sobre-rotas-com-versao-3-da.html" title="Informações sobre rotas com a versão 3 da API do Google Maps" /><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>29</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2012/01/informacoes-sobre-rotas-com-versao-3-da.html</feedburner:origLink></entry><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:98%;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;/div&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="2 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>2</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:98%;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;/div&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="10 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>10</thr:total><feedburner:origLink>http://balaiotecnologico.blogspot.com/2011/12/preparando-execucao-de-um-programa-em.html</feedburner:origLink></entry></feed>
