Desenvolvimento - ASP. NET

Acessando Mapas do Google com Visual Fox Pro 9 SP2

Veja neste artigo como podemos utilizar o componente Google Maps API V3 com o Visual Fox Pro 9 SP2. Solicitando mapas dinâmicos, acrescentando marcadores, dessenhando formas, pintando, etc.

por Cyro Bergonzi



O Google disponibiliza duas formas para acesso as imagens dos mapas da ferramenta Maps através da sua API: estáticas e dinâmicas.

A ferramenta Maps é livre para uso em sites e sistemas gratuitos, mas o grande problema é que o Google não aceita que esta ferramenta fique fechada em uma aplicação desktop, assim, caso você deseje realmente utilizar esta ferramenta dentro de uma aplicação desktop será necessário entrar em contato com o escritório que representa a empresa no Brasil.

Veremos que pouca programação em Fox será utilizada, mesmo porque a API do Google Maps utiliza outras linguagens como, por exemplo, o JavaScript para realizar as operações e exemplos que serão mostrados.

No Visual FoxPro iremos criar um formulário com um controle Textbox (para a pesquisa do endereço) e um controle button que irá disparar a pesquisa. Além disso, vamos adicionar um componente OLE WebBrowserControl que irá exibir o mapa de forma dinâmica.
Para isso, na janela de comandos do Visual FoxPro digite o comando:

CREATE FORM Mapas AS Form DEFAULT

Com este comando garantimos que o novo formulário irá derivar da classe básica de formulários do Visual FoxPro. Podemos ver como ficou o formulário na Figura 1.

Formulário Mapas vazio, sem controles

Figura 1. Formulário Mapas vazio, sem controles

Agora vamos adicionar os controles Label, Textbox e CommandButton ao formulário. Para isso vamos usar os passos da Listagem 2.

Listagem 2. Nomeie os controles da seguinte forma.

  TextBox.Name: enderecoText
 CommandButton.Name: cmdPesquisar
  Label1.Caption = Endereço
  cmdPesquisar.Caption = ...

Agora formate o layout do formulário para que fique conforme a Figura 2.

Formatando layout do formulário

Figura 2. Formatando layout do formulário

Até o momento nosso formulário já tomou a forma básica, mas ainda falta o componente OLE com o controle WebBrowser que irá exibir o mapa. Por isso, na guia tools do VFP 9 acesse o item Component Gallery e selecione o controle WebBrowser Control, conforme mostra a Figura 3.

Selecionando controle

Figura 3. Selecionando controle

Arraste o controle para o formulário e o mesmo deverá ficar conforme a Figura 4.

Resultado do Formulário

Figura 4 - Resultado do Formulário

Agora dê um duplo clique no cmdPesquisar e acrescente o código da Listagem 3.

Listagem 3. Comando cmdPesquisar

  Local endereco As String
   
  If !Empty(endereco)
           endereco = ''
  Endif
   
  DECLARE INTEGER InternetCheckConnection IN wininet;
   STRING lpszUrl, INTEGER dwFlags, INTEGER dwReserved
   
  #DEFINE FLAG_ICC_FORCE_CONNECTION  1
  lcUrl = "http://www.google.com.br"
   
  LOCAL lResultado
  lResultado = (InternetCheckConnection(lcUrl, FLAG_ICC_FORCE_CONNECTION, 0)=1)
      
  IF !lResultado
           Messagebox("Conexão com a Internet não disponível!")
           Return
  Else
           With Thisform.pasta.page1
  endereco = '"'+Alltrim(.enderecoText.Value) +'"'
                     endereco = Strtran(endereco,'ã','a')
                     endereco = Strtran(endereco,'Ã','A')
                     endereco = Strtran(endereco,'õ','o')
                     endereco = Strtran(endereco,'Õ','O')
                     endereco = Strtran(endereco,'é','e')
                     endereco = Strtran(endereco,'ê','e')
                     endereco = Strtran(endereco,'É','E')
                     endereco = Strtran(endereco,'Ê','E')
                     endereco = Strtran(endereco,'í','i')
                     endereco = Strtran(endereco,'Í','I')
                     endereco = Strtran(endereco,'ó','o')
                     endereco = Strtran(endereco,'Ó','O')
                     endereco = Strtran(endereco,'ú','u')
                     endereco = Strtran(endereco,'Ú','U')
           Endwith
           
           endereco = STRTRAN(end_, ' ', '+')  
  ENDIF
   
  This.Parent._WEBBROWSER41.Navigate(SYS(5)+SYS(2003)+"\mapas\index.htm"+"?"+endereco)

Para explicar o código acima, temos alguns trechos que precisam ser comentados para trazer maior clareza do que está acontecendo. Observe a Listagem 4.

Listagem 4. Declarando variável endereço como string.

  Local endereco As String
   
  If !Empty(endereco)
           endereco = ''
  Endif
  

No trecho acima declaramos uma variável endereço como string e, em seguida, realizamos a verificação para saber se a mesma já está preenchida: caso sim igualamos a vazio.

Listagem 5. Verificando conexão com a internet.

  *--------------------------------------------------- VERIFICA A CONEXÃO COM A INTERNET
  DECLARE INTEGER InternetCheckConnection IN wininet;
   STRING lpszUrl, INTEGER dwFlags, INTEGER dwReserved
   
  #DEFINE FLAG_ICC_FORCE_CONNECTION  1
  lcUrl = "http://www.google.com.br"
  *-------------------------------------------------------------------------------------
  LOCAL lResultado
  lResultado = (InternetCheckConnection(lcUrl, FLAG_ICC_FORCE_CONNECTION, 0)=1)

Na Listagem 5 realizamos a verificação de conexão com a internet. Lembrando que para solicitar as imagens dos mapas é necessário conexão com a internet, por isso a variável lResultado de ter seu valor igual a .T..

Listagem 6. Resultado se a conexão com não existir.

  IF !lResultado
           Messagebox("Conexão com a Internet não disponível!")
           Return
  Else
           With Thisform
                     endereco = '"'+Alltrim(.enderecoText.Value)+'"'
                     endereco = Strtran(end_,'ã','a')
                     endereco = Strtran(end_,'Ã','A')
                     endereco = Strtran(end_,'õ','o')
                     endereco = Strtran(end_,'Õ','O')
                     endereco = Strtran(end_,'é','e')
                     endereco = Strtran(end_,'ê','e')
                     endereco = Strtran(end_,'É','E')
                     endereco = Strtran(end_,'Ê','E')
                     endereco = Strtran(end_,'í','i')
                     endereco = Strtran(end_,'Í','I')
                     endereco = Strtran(end_,'ó','o')
                     endereco = Strtran(end_,'Ó','O')
                     endereco = Strtran(end_,'ú','u')
                     endereco = Strtran(end_,'Ú','U')
           Endwith
           endereco = STRTRAN(endereco, ' ', '+')  
  ENDIF

Na Listagem 6 estamos realizando a verificação do acesso a internet: se o mesmo não existir, uma mensagem é exibida ao usuário; do contrário, retiramos os acentos da variável endereco que será utilizada na busca da imagem do mapa.

Listagem 7. Solicitando mapa para o endereço informado.

  ThisForm._WEBBROWSER41.Navigate(Sys(5)+Sys(2003)+"\index.htm"+"?"+endereco)

Na Listagem 7 realizamos a solicitação do mapa para o endereço informado.

Bom, até aqui fizemos a parte fácil (claro, para quem programa em Fox), ou seja toda programação do lado do VFP 9.

Temos então que partir para o lado web e criar um Web Site com JavaScript que vai instanciar a API do Google Maps e exibir os mapas e controles dentro do ambiente que criamos acima no VFP.

Para isso, você vai precisar de um editor HTML ou pode utilizar o famoso bloco de notas mesmo. Para criar a página, use o código da Listagem 8.

Listagem 8. Página HTML

  <!DOCTYPE html>
  <html>
    <head>
      <title>Google Maps JavaScript API v3 Examplo: Drawing Biblioteca</title>
      <meta http-equiv="content-type" content="text/html; charset=utf-8" />
      
      <style type="text/css"> 
                     body   {
                              font-family: "Trebuchet MS", Arial,Helvetica,Sans Serif;
                              font-size: 10pt;
                              margin:0px;
                     } 
   
                     #map_canvas {
                              width: 1920px;
                              height: 1080px;
   
                     }        
                              
                     #styles {
                              width: 370px;
                              height: 375px;
                              background-color: #ffffff;
                              margin: 2px 2px 2px 2px;
                              padding: 8px;
                              border: 5px solid gray;
                              position: absolute;
                              top: 175px;
                              left: 550px;
                              z-index:99999;
                              visibility:hidden;
                     }
                     #rectangle {
                              width: 250px;
                              height: 105px;
                              background-color: #ffffff;
                              margin: 2px 2px 2px 2px;
                              line-height: 22px;
                              padding: 8px;
                              border: 5px solid gray;
                              position: absolute;
                              top: 300px;
                              left: 650px;
                              z-index:99999;
                              visibility:hidden;
                     }        
                     
   
   
  .labels {
                                color: black;
                                background-color: lime;
                                font-family: Arial;
                                font-size: size;
                                font-weight: bold;
                                text-align: left;
                       width: length(titulo); 
              border: 1px solid lime;
              white-space: nowrap;
            }
          
  </style>

Acima definimos o tipo de documento “HTML” e a folha de estilos o CSS.

Listagem 9. Código JavaScript

  <script type="text/javascript"    src="http://maps.googleapis.com/maps/api/js?key=sua_chave_api&sensor=false&libraries=drawing" type="text/javascript">
      </script>    
      <script type="text/javascript">
           
          var map;
          var marker = [];
          var circle = [];
          var rectangle = [];
          var polygon = [];
          var polyline = [];
          var markerCount = 0;
          var circleCount = 0;
          var rectangleCount = 0;
          var polygonCount = 0;
          var polylineCount = 0;
          var markerMode = false;
          var drawingManager;

Na Listagem 9 estamos instanciando a API do Google Maps e as váriaveis que serão utilizadas na página para manipular o mapa.

No código key=sua_chave_api você deve obter uma chave da API do Google e substituir no local marcado.

Para obter uma chave acesse o link https://developers.google.com/maps/documentation/javascript/tutorial?hl=pt-br#api_key

Para acessar esta tela (mostrada na Figura 5) você deve estar devidamente logado com sua conta do Google.

Tela de serviços

Figura 5. Tela de serviços

Abaixo habilite o componente da API como mostra a Figura 6.

Habilitando componente da API

Figura 6. Habilitando componente da API

Lembre -se de consultar os termos de uso no link a seguir: https://developers.google.com/maps/terms?hl=pt-br

Listagem 10. Função que inicializa a chamada do mapa.

function initialize() {
            var url = location.href.replace(location.href.split("?")[0] + "?", "");
            geocoder = new google.maps.Geocoder();
               
            var mapOptions = {
                zoom: 18,
                mapTypeControl: true,
                mapTypeId: google.maps.MapTypeId.SATELLITE,
                streetViewControl: false,
                disableDefaultUI: true,
                mapMarker: false,
                panControl: false,
                scaleControl: false,
                disableDoubleClickZoom: true,
                zoomControl: true,
                zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL }
  }

Note que estamos recuperando o endereço da variavel “var url” que será tratado adiante. Logo em seguida definimos o geocoder.

Dentro de "var mapOptions" definimos o estilo no qual o mapa será inicializado:

  • Zoom: 18 - significa que a propriedade zoom será iniciada como valor 18, mas você pode ajustar como bem quiser.
  • mapTypeControl : false - indica que os controles do mapa não serão exibidos. maptypecontrol
  • mapTypeId : google.maps.MapTypeId.SATELLITE - define o tipo de mapa que será inicializado.
  • streetviewControl : false - desabilita o controle streetView.
  • panControl : false pancontrol
  • scaleControl : false scalecontrol
  • disableDoubleClickZoom - true : Habilita o evento duplo clique do mouse para dar zoom no mapa.
  • zoomControl : true - Habilita o controle de zoom no mapa.
  • zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL } - define o estilo do controle zoom.

Na Listagem 11 tratamos o endereço que será recuperado na URL e definimos a variável de controle do mapa

Listagem 11. Tratamento da URL.

endereco(url);
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);

drawingManager = new google.maps.drawing.DrawingManager({
drawingControl: true,
          drawingControlOptions: {
          position: google.maps.ControlPosition.TOP_LEFT,
          drawingModes: [
                                      google.maps.drawing.OverlayType.NULL,
                                      google.maps.drawing.OverlayType.CIRCLE,
                                      google.maps.drawing.OverlayType.POLYGON,
                                      google.maps.drawing.OverlayType.POLYLINE,
                                      google.maps.drawing.OverlayType.RECTANGLE,
			        google.maps.drawing.OverlayType.MARKER
     		
                        	  ]
          },
               
          circleOptions: {
          		fillColor: '#00FF00',
          		fillOpacity: 0.2,
          		strokeColor: '#00FF00',
          		strokeWeight: 2,
         		draggable: true,
          		clickable: false,
          		editable: true,
          		zIndex: 1
          },
                
          polygonOptions: {
                    fillColor: '#00FF00',
                    fillOpacity: 0.2,
                    strokeColor: '#00FF00',
                    strokeWeight: 2,
                    draggable: true,
                    clickable: false,
                    editable: true,
                    zIndex: 2
          },
                
          







polylineOptions: {
                    fillColor: '#00FF00',
                    fillOpacity: 0.2,
                    strokeColor: '#00FF00',
                    strokeWeight: 2,
                    draggable: true,
                    clickable: false,
                    editable: true,
                    zIndex: 3
          },
                
          rectangleOptions: {
                    fillColor: '#00FF00',
                    fillOpacity: 0.2,
                    strokeColor: '#00FF00',
                    strokeWeight: 2,
                    draggable: true,
                    clickable: false,
                    editable: true,
                    zIndex: 4
           }
                
  });
  drawingManager.setMap(map);

Em “endereco(url);” -> tratamos o endereço passado na função endereço e retornamos o geocode. Já a variável map recebe a instância do mapa com as opções definidas na variavel mapOptions.

Em drawingManager estamos instanciando o controle de desenhos no mapa e suas propriedades e habilitamos os estilos e formas de desenhos. Mais abaixo podemos notar as configurações de cada item de desenho habilitado na ferramenta DrawingManager.

No item drawingManager.setMap(map); estamos habilitando o controle e as propriedades definidas nele no mapa.

Na Listagem 12 vamos guardar as posições do clique de cada desenho para podermos limpar o mapa depois.

Listagem 12. Posições de cliques

  google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
  if (event.type == google.maps.drawing.OverlayType.CIRCLE) {
                                        circle[circleCount] = event.overlay;
                                        circleCount++;
                              }
  });
   
  google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
                              if (event.type == google.maps.drawing.OverlayType.RECTANGLE) {
                                        rectangle[rectangleCount] = event.overlay;
                                        rectangleCount++;
                              }
  });
   
  google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
                              if (event.type == google.maps.drawing.OverlayType.POLYGON) {
                                        polygon[polygonCount] = event.overlay;
                                        polygonCount++;
                              }
           });
   
   google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
                              if (event.type == google.maps.drawing.OverlayType.POLYLINE) {
                                        polyline[polylineCount] = event.overlay;
                                        polylineCount++;
                              }
           });
   
  google.maps.event.addListener(map, 'click', function(e) {
                              mapClick(e.latLng, map, markermode);
           });
  }
   
  google.maps.event.addDomListener(window, 'load', initialize);

Note no código que as posições são armazenadas nas variáveis definidas no início do código.

Já na Listagem 13 definimos a função endereco utilizada para traduzir o endereço passado na URL para o GeoCode.

Listagem 13. Função endereco

  //Busca o endereço para exibir no mapa                     
  function endereco(url) {
  geocoder.geocode({ 'address': url }, function(results, status) {
                              if (status == google.maps.GeocoderStatus.OK) {
                                        map.setCenter(results[0].geometry.location);
   
                                        var marker1 = new google.maps.Marker({
                              map: map,
                              position: results[0].geometry.location,
                              clickable: true,
                              draggable: true
                                        });
   
                                        var contentString = '<div id="content">' +
                                                                    '<div id="bodyContent">' +
                                                                   '<p><b>"O ponto informado encontra-se neste local:"</b>' +
                                                          '<br>' + url + '</br>' + ' Latitude/Longitude: ' + '<br>' +                results[0].geometry.location + '</br>' + '<br>' + '</br>' +
                                                                  '</div>' +
                                                                  '</div>';
   
                                        var infowindow = new google.maps.InfoWindow({
                                                 content: contentString
                                        });
   
                                        google.maps.event.addListener(marker1, 'click', function() {
                                                 infowindow.open(map, marker1);
                                        });
                     } else {
                                        alert('Não foi possivel encontrar o endereço!');
                     }
              });
  }

Note que também acrescentamos uma InfoWindow, que é um balão que aparece com a descrição “O ponto informado encontra-se neste local : Latitude/Longitude : “ . Esta mensagem somente é exibida quando clicamos no marcador, que por sua vez, inicializa o mapa quando chamamos o mesmo, assim, ele já vem fixado no endereço informado na URL.

Na Listagem 14 definimos a função deleteOverlays utilizada para limpar o mapa.

Listagem 14. Função deleeteOverlays.

  function deleteOverlays(a){
              if (a) {
                  for (var i = 0; i < markerCount; i++) {
                      marker[i].setMap(null);
                  }
                  for (var i = 0; i < markerCount1; i++) {
                      marker2[i].setMap(null);
                  }
                  for (var i = 0; i < circleCount; i++) {
                      circle[i].setMap(null);
                  }
                  for (var i = 0; i < rectangleCount; i++) {
                      rectangle[i].setMap(null);
                  }
                  for (var i = 0; i < polygonCount; i++) {
                      polygon[i].setMap(null);
                  }
                  for (var i = 0; i < polylineCount; i++) {
                      polyline[i].setMap(null);
                  }
              }
           }

Note que utilizamos as posições guardadas anteriormente nos arrays para deletar os pontos alterados no mapa.

Com isso, na Listagem 15 finalizamos o arquivo HTML.

Listagem 15. Arquivo HTML.

  </script>
  </head>
  <body  scroll="no" topmargin="0" leftmargin="0" onload="initialize()">
  <table border ="1" cellpadding ="1" cellspacing ="1" width ="100% " id="toptable" class="normal">
                    <form action="#" name="teste">    
  <td  align="center" style="font-size:12px" title="Apaga todas a alterações feitas no mapa..." onmouseover="this.className='over'" onmouseout="this.className='out'" onclick="a = confirm('Confirma a limpeza do Mapa?');deleteOverlays(a);this.className='click';">
  <img id="delete" title="Apaga todas a alterações feitas no mapa..." onclick="a = confirm('Confirma a limpeza do Mapa?');deleteOverlays(a);" src="" width="18" height="18"/>
                              <br />Limpar o Mapa         
                    </td>
           </form>
  </table>
  <table border ="0" width ="100%">
                    <div id="map_canvas" class="map_canvas"></div>
                     <tr style="vertical-align:top"></tr>
           </table>
   </body>
  </html>

Podemos notar o resultado final na Figura 7.

Resultado final do Formulário Mapas

Figura 7. Resultado final do Formulário Mapas

Conclusão

Neste pequeno tutorial foram abordados apenas conceitos básicos na operação com a API do Google e o Visual Fox. É possível ainda criar mais ferramentas como, por exemplo: captura de imagem do mapa, marcadores com títulos, trocar as imagens e configurações das formas de desenhos, criar uma função para limpar o mapa, desfazer alterações e muito mais.

Cyro Bergonzi

Cyro Bergonzi - Bacharel em Sistemas de Informação, Analista de Sistemas na CWS Systems. Trabalha como Analista Programador Visual Fox / C# .Net na empresa BDK Solutions. Tem 31 anos e possui diversos cursos na área de programação bem como Java e ASP .Net.