the club - megazine · 2015-06-02 · obs: este é o padrão de media queries do bootstrap, o que...

32
maio 2015

Upload: others

Post on 30-Jul-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015

Page 2: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015

Page 3: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 03

19

Índice

Editorial

04

11

Autor: Hamden Vogel

05

Autor: Marlon Aparecido Branco Valentino

24

Linguagem C# - Delegates em Windows Forms

Autor: Thiago C. Montebugnoli

Autor: Luciano Pimenta Dicas The Club

28

Bootstrap - 6 Truques e dicas essenciais para o desenvolvimento com Bootstrap.

Novo FastFile 3.0 – Lendo arquivos grandes – 2GB pra frente

Navegador no Delphi XE8

Page 4: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201504

Delphi é marca registrada da Borland International, as demais marcas citadas são registradas

pelos seus respectivos proprietários.

Thiago Montebugnoli - Editor [email protected]

Caro leitor,

Gostaria primeiramente de parabenizar todas as mães deste Brasil, de-sejando tudo de bom para esta importante figura em nossas vidas.

Este mês nosso colaborador Hamden Vogel continua escrevendo sobre o componente “FastFile” no Delphi. Nesta versão ele abrange a leitura de ar-quivos maiores que 2GB. O interessante deste artigo é que o autor contorna problemas de memória e travamento da aplicação com o uso deste compo-nente. Já nosso colunista Luciano Pimenta traz novidades do componente “TWebBrowser” da nova versão do Delphi XE8. Neste artigo ele ensina como criar um navegador e com ele utilizar aplicações que pesquisam informações em sites, interagindo e abrindo links diretamente da aplicação, se identi-ficando ao máximo com os novos navegadores encontrados atualmente. Já nosso consultor técnico Marlon Aparecido Branco Valentino redigiu um artigo explorando algumas dicas e truques relacionados ao BootStrap. Teremos dicas de como habilitar um “DropDown” para exibição de listas na ação “Hover”, utilização da classe “Container Fluid”, uso de “Grids” em diferentes tamanhos de telas, entre outras dicas, ou seja, neste tutorial ele procurou reunir as principais dicas para o desenvolvedor Web. Para finalizar os artigos, eu ensinei de uma forma fácil e prática o uso de “Delegates”, um importante mecanismo encontrado na linguagem C#. Sua maior finalidade é a possibilidade de passagem de métodos por parâmetros em run-time, uma técnica muito favorável em diversos momentos.

Não podemos esquecer da nossa seção de Dicas, sempre recheada com os melhores macetes envolvendo diversos tipos de linguagens de programação.

Um Abraço e até o mês que vem!

Av. Profº Celso Ferreira da Silva, 190 Jd. Europa - Avaré - SP - CEP 18.707-150

Informações e Suporte: (14) 3732-1529

Internethttp://www.theclub.com.br

Cadastro: [email protected]: [email protected] Informações: [email protected] Cadastro: theclub_cadastro

Skype Suporte: theclub_linha1 theclub_linha2 theclub_linha3

www.twitter.com/theclubbr

Copyright The Club 2013

Diretor TécnicoMarcos César Silva

DiagramaçãoVitor M. Rodrigues

DesignVitor M. Rodrigues

RevisãoDenise Blair

ColunistasHamden Vogel

Jeferson Silva de LimaLuciano Pimenta

Marlon Aparecido Branco ValentinoThiago Cavalheiro Montebugnoli

Impressão e acabamento:GRIL - Gráfica e Editora

Taquarituba-SP - Tel. (14) 3762-1345

ReproduçãoA utilização, reprodução, apropriação, armazenamento em banco de dados, sob qualquer forma ou meio, de textos, fotos e outras criações intelectuais em cada publicação da revista “The Club Megazine” são terminantemente proibidos sem autorização escrita dos titulares dos direitos autorais.

Editorial

Page 5: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 05

Introdução

Muitos desenvolvedores que utilizam o framework Bootstrap sabem que ele é bem completo pois é cheio de recursos que ajudam a agilizar o desen-volvimento front-end do seu projeto, mas as vezes acabamos escrevendo o nosso próprio CSS e JavaScript sem saber o próprio Bootstrap poderia estar fazendo aquilo por nós, o que não é necessariamente um problema, mas você acabar gastando mais tempo do que deveria em seu projeto.

O objetivo deste artigo é mostrar algumas das coisas que venho apren-dendo sobre o Framework que podem ser úteis e dar uns toques sobre outras coisas que venho observando ao longo de meus estudos, sobre as capacidades do Bootstrap.

Imagem 01 Logo oficial do Bootstrap

1- Habilitando um Dropdown para exibir sua lista na ação Hover!

Começando por um ponto que muitos perdem tempo para fazer, mas é

algo bem simples, habilitar o dropdown para exibir na ação Hover(que significa “Mouse Over” em tradução livre fica “Mouse sobre”), pois a Navbar padrão que

o Bootstrap cria não é muito funcional em termos de UX(“User Experience” em tradução livre fica Experiência do usuário), em caso de projetos com um alto nível de designe é melhor você customizar um pouco a Navbar. A imagem 02 logo abaixo exibe o menu padrão, onde é necessário clicar para exibir as opções:

Imagem 02 Dropdown padrão do Bootstrap

Apenas adicionei o código que obtive no site oficial do Bootstrap (get-bootstrap.com), note que estou com o mouse sobre o Dropdown(ele está mais escuro), porém ele não exibe a lista observe o código abaixo:

<li class=”dropdown”> <a href=”#” class=”dropdown-toggle” data-toggle=”dropdown” role=”button” aria-expanded=”false”>Dropdown Padrao<span class=”caret”></span></a> <ul class=”dropdown-menu” role=”menu”> <li><a href=”#”>Pagina 1</a></li> <li><a href=”#”>Pagina 2</a></li> <li><a href=”#”>Pagina 3</a></li>

Bootstrap - 6 Truques e dicas essenciais para o desenvolvimento com Bootstrap.

Page 6: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201506

<li class=”divider”></li> <li><a href=”#”>Pagina separada </a></li> </ul></li>

Agora iremos customizar o menu, adicionando 3 linhas de código ao CSS seu projeto, no meu caso irei adicioná-lo ao arquivo Site.css que o Visual Studio gera junto aos outros arquivos de estilos, copie o código abaixo:

@media only screen and (min-width : 768px) {/* É necessário colocá-lo dentro do Media query */ /* Transforma o dropdown de Toggle(clique) para Hover(Mouse sobre) */ .dropdown:hover .dropdown-menu { display: block; }}

Depois que adicionou o código à cima ao seu projeto, compile-o e você terá o resultado que tive, observe a imagem 03 abaixo que mostra o dropdown com o efeito Hover:

Imagem 03 Dropdown com o efeito Hover

Recentemente deixei de utilizar o NavBar padrão do Bootstrap, realizo algumas alterações em seu designe, porém não é da para customizar muito, as vezes acabo criando o meu próprio menu, mas agora utilizo o OffCanvas, recentemente descobri este menu, que é basicamente um menu que fica na lateral da página, e só é exibido quando o usuário clica no botão do menu, é possível facilmente criar um destes menu, basta utilizar o plugins para Bootstrap chamado Jasny, caso tenha se interessado no menu e no plugin, acesse o site este link: jasny.github.io/bootstrap/index.html OBS: O conteúdo do site está em inglês, ou seja, é necessário ter um inglês técnico para compreender os

conceitos dos componentes disponíveis.

2- Não deixe de utilizar a classe Container Fluid para Rows com largura da inteira (full width).

Um dos maiores erros que os desenvolvedores iniciantes cometem quando começam a utilizar o framework, é deixar de utilizar a classe “container-fluid” quando se trata de Rows com Full Width(largura da página toda), confesso que quando comecei a usar o Bootstrap nunca utilizava esta classe. Caso fosse criar uma Row com full width, apenas omitia o “container-fluid”, isso gerava um problema pois a classe Row do Bootstrap por padrão possui -15px de margin a sua direita e esquerda, o problema é exemplificado na imagem 04 logo abaixo:

Figura 1 Problema de não utilizar a classe “container-fluid” em Rows de full width

Observe que o conteúdo fica colado no canto da página, agora se você gerou o seu projeto pelo tema padrão do Visual Studio o problema não acon-tece, porque ele cria um arquivo chamado Site.css que tira a margin padrão da classe Row. Para aqueles que não criaram utilizando o tema padrão, é necessário utilizar a classe “container-fluid” toda vez que for criar uma Row com full width, note que na imagem 05 logo abaixo o problema não ocorre novamente, pois eu adicionei a classe “container-fluid” na <div> que é respon-sável pelo conteúdo da página:

Imagem 05 Utilizando a classe “container-fluid”

3- Breakpoints em Media Queries

Muitos desenvolvedores não utilizam Media Querie, mas é por eles que você define como o seu Site/App irá se comportar em vários tamanhos de dispositivos, seja ele um celular de 4 polegadas ou um monitor de desktop com 19 polegadas, é necessário saber utilizá-los com aptidão para deixar seu site responsivo. Estes são alguns dos Media Queries que você deveria estar utilizando no CSS do seu projeto:

Page 7: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 07

/*==================================================Estes são alguns dos Media Queries presentes no Bootstrap 3==================================================*//*========== Método utilizando Mobile First ==========*//* Customizado, iPhone 4 */ @media only screen and (min-width : 320px) {}/* Dispositivos muito pequenos, SmartPhones */ @media only screen and (min-width : 480px) {}/* Dispositivos pequenos, Tablets */@media only screen and (min-width : 768px) {}/* Dispositivos médios, Desktops */@media only screen and (min-width : 992px) {}/* Dispositivos grandes, Wide Screens */@media only screen and (min-width : 1200px) {}/*= Estes Media Queries não utilizam o método Mobile First =*//* Dispositivos grandes, Telas WideScreen */@media only screen and (max-width : 1200px) {}/* Dispositivos médios, Desktops */@media only screen and (max-width : 992px) {}/* Dispositivos Pequenos, Tablets */@media only screen and (max-width : 768px) {}/* Dispotivis muito pequenos,

Phones */ @media only screen and (max-width : 480px) {}/* Customizado, iPhone 4*/ @media only screen and (max-width : 320px) {}

OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra.

5- Definindo como um Grid de colunas se comporta em dife-rentes tamanhos de telas.

Os Grids do Bootstrap são realmente fantásticos e poderosos, quando se trata do desenvolvimento de sites responsivos, pois ele era para deixar você juntar os seus grids dependendo do tamanho do dispositivo, mostrando eles em uma linha só, observe a imagem 06 que exemplifica o comportamento dos grids em um dispositivo pequeno:

Imagem 06 Exemplo do comportamento do sistema de Grids em dispositivos pequenos

Page 8: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201508

Para quem estudou o básico do sistema de grids do Bootstrap sabe que o número de colunas que é possível dividir um gride é 12, neste caso, eram 4 colunas que foram dividas de forma que cada uma delas ocupasse 3 colunas da linha (utilizei a classe col-md-3 em cada div da Row). Observe o código abaixo referente a imagem 06:

<div class=”row”> <div class=”col-md-3”> ... </div> <div class=”col-md-3”> ... </div> <div class=”col-md-3”> ... </div> <div class=”col-md-3”> ... </div>

</div>

Agora se você quiser que eles sejam apresentados de uma forma mais agra-dável em dispositivos como Tablets que são considerados pequenos, como é mostrado na imagem 07 que exemplifica o comportamento em telas de Tablets:

Imagem 07 Exemplo do comportamento do grid em dispositivos como Tablets

O código do referente a imagem 07 é o seguinte:

<div class=”row”> <div class=”col-md-3 col-sm-6 col-xs-12” > ... </div> <div class=”col-md-3 col-

sm-6 col-xs-12”> ... </div> <div class=”col-md-3 col-sm-6 col-xs-12”> ... </div> <div class=”col-md-3 col-sm-6 col-xs-12”> ... </div>

</div>

Note que adicionei as classes “col-sm-6” e “col-xs-12”, “sm” significa em inglês “Small” em tradução livre fica “Pequeno” e 6 é o número de colunas que ele ocupará caso o dispositivo seja pequeno, já o “xs” também do inglês “Extra Small” que em tradução livre significa “Extra pequeno” ou “Muito Pequeno” e 12 é o número ocupadas por ele, ou seja, largura toda do grid, caso a tela do dispositivo venha a corresponder a classe.

6- Exemplo de como criar Containers com tamanhos custo-mizados para diferentes tamanhos de dispositivos.

Muitas vezes acabamos nos dando de cara com o designe de um site que não combina com o sistema padrão de grids do Bootstrap, e por padrão as colunas dentro de um Container preenchem o espaço do seu <div> pai, neste caso um Container. Se necessário criar um container com um tamanho maior ou menor, a solucionar é alterar os padrões do Framework através de Media Queries, o código abaixo exemplifica como pode ser feita esta alteração:

@media (min-width: 768px) { .container-small { width: 300px; } .container-large { width: 970px; }}@media (min-width: 992px) { .container-small { width: 500px; } .container-large { width: 1170px; }}@media (min-width: 1200px) { .container-small {

Page 9: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 09

width: 700px; } .container-large { width: 1500px; }}

Efetuando esta alteração, é necessário dar atenção ao problema com OverFlow, em casos onde o Container é maior do que a tela do Dispositivo, o conteúdo acaba excedendo a tela do dispositivo. Podemos citar por exemplo a classe container-large, utilizando ela, se o usuário de seu WebSite possuir uma tela com mais de 1200px, isso vai gerar um problema com OverFlow. O código abaixo mostra como corrigir esse problema:

.container-small, .container-large { max-width: 100%;}

Observe o resultado na imagem 09 logo abaixo: O código do meu container é este:

<div class=”container container-customizado”> <div class=”row”> <h2>Container com tamanho normal!</h2> <div class=”col-md-4”> <a class=”btn btn-block btn-primary” href=”http://go.microsoft.com/fwlink/?LinkId=301865”><i class=”glyphicon glyphicon-star”></i></a> </div> <div class=”col-md-4”> <a class=”btn btn-block btn-primary” href=”http://go.microsoft.com/fwlink/?LinkId=301865”><i class=”glyphicon glyphicon-star”></i></a> </div> <div class=”col-md-4”>

<a class=”btn btn-block btn-primary” href=”http://go.microsoft.com/fwlink/?LinkId=301865”><i class=”glyphicon glyphicon-star”></i></a> </div> </div></div>

<div class=”container container-large container-customizado”> <div class=”row”> <h2>Container grande com tamanho customizado</h2> <div class=”col-md-4”> <a class=”btn btn-block btn-success” href=”http://go.microsoft.com/fwlink/?LinkId=301865”><i class=”glyphicon glyphicon-star”></i></a> </div> <div class=”col-md-4”> <a class=”btn btn-block btn-success” href=”http://go.microsoft.com/fwlink/?LinkId=301865”><i class=”glyphicon glyphicon-star”></i></a> </div> <div class=”col-md-4”> <a class=”btn btn-block btn-success” href=”http://go.microsoft.com/fwlink/?LinkId=301865”><i class=”glyphicon glyphicon-star”></i></a> </div> </div></div>

<div class=”container container-small container-customizado”> <div class=”row”> <h2>Container pequeno com tamanho customizado!</h2> <div class=”col-md-4”> <a class=”btn btn-block btn-warning” href=”http://go.microsoft.com/fwlink/?LinkId=301865”><i

Page 10: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201510

[email protected]

Marlon Aparecido Branco Valentino jovem desenvolvedor front-end, com conhecimento nas lingua-

gens HTML5, CSS3, JavaScript, e nas frameworks jQuery, Bootstrap, AngularJS e suas demais bibliotecas.

Sobre o autor

class=”glyphicon glyphicon-star”></i></a> </div> <div class=”col-md-4”> <a class=”btn btn-block btn-warning” href=”http://go.microsoft.com/fwlink/?LinkId=301865”><i class=”glyphicon glyphicon-star”></i></a> </div> <div class=”col-md-4”> <a class=”btn btn-block btn-warning” href=”http://go.microsoft.com/fwlink/?LinkId=301865”><i class=”glyphicon glyphicon-star”></i></a> </div> </div></div>

Note que foi necessário adicionar uma classe chamada container-customi-zado, pois se tentarmos aplicar os estilos de background color(cor de fundo) e padding (espaço nas extremidades) ele irá aplicar em todos os containers do

seu projeto, então crie uma classe como a minha e aplique o CSS nela. Observe que as colunas ainda ficam responsivas nos breakpoints dos Media Queries quando você diminui o tamanho do seu browser.

Conclusão

Este artigo mostrou que as vezes o Bootstrap será uma excelente escolha e as vezes não, é aí que entra a customização e algumas das dicas citadas são muito úteis quando chegamos a este ponto. É tudo sobre escolher a ferramenta certa para o serviço, para que você não perca tempo e dinheiro. Tenha em mente que o Bootstrap não fará todo o desenvolvimento Front-end para você, mas com certeza irá deixá-lo muito mais fácil.

Page 11: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 11

Foram dias difíceis de testes. Não foi fácil encontrar uma solução que aten-desse aos quesitos de performance e estabilidade de forma satisfatória. Depois de experimentar consagradas alternativas (tradicionais e open-source), como TGpHugeFile, TLists, Memory Mapped Files, Threads, vários descendentes de TFileStream, alguns banco de dados, etc; todos frustraram as expectativas para processamento superior a 15 milhões de linhas dinamicamente em memória; por questões óbvias de falta dela tive que procurar uma outra solução que em nenhum lugar aparentemente encontrasse – teria que “criar do zero” e seguir com ela – a fim de carregar grandes arquivos de 2GB pra frente sem travar a aplicação por falta de memória ou algo parecido.

Qual o problema de ler um arquivo imensamente grande em Delphi?

Se você não ser precavido, a resposta é todos eles. Os problemas são pri-meiramente a falta de memória, depois o travamento da aplicação, e terceiro seria o Windows reclamando com também travamento de telas e processos – não adianta “acelerar o conserto” depois – já que para retomar à estabilidade de antes é bem provável que se leve um tempo considerável – e um prejuízo de sua aplicação que falhou a operação de leitura, além de perder tempo com ela também. E aí, como resolver então?

Já foi dito anteriormente, em outras edições, nas versões anteriores deste nosso projeto FastFile que uma solução baseada em listas de ponteiros (TLists) são excelentes – e é verdade – só que não foi dito é até quando que será exce-lente – ou melhor – até quanto de comprimento de um arquivo nosso objeto de TList vai armazenar as linhas deste arquivo sem estourar a memória – e isso é um fato. Testamos na edição passada nosso FastFile lendo um arquivo de 1,2 GB em 30 segundos. Funcionou e funciona até agora nesta versão com sucesso. Mas e se o arquivo for maior que 1,2 GB?

Para isso nossa outra solução teve que ser buscada – e pacientemente. Como disse anteriormente, foram muitos os caminhos trilhados – e todos falharam por não conseguir lograr êxito nesta missão. A missão a qual me refiro é poder ler mais de 15 milhões de uma forma sem travar – na memória é que não vai poder mais – portanto até este limite vamos considerar que é possível. A partir daí que vamos buscar outra implementação.

O valor de 15 milhões é simbólico – poderia ser um pouco mais que isso.

Novo FastFile 3.0 – Lendo arquivos grandes – 2GB pra frente

Mas este valor é bem “seguro” para os nossos testes. Então vamos empregar outra abordagem – os arquivos até 1,5 GB terão a abordagem da nossa classe TLineReaderList baseada em TList (já discutido na edição anterior) enquanto que os arquivos superior a 1,5 GB terão a abordagem em um outro componente adotado – e é essa a novidade do nosso artigo e a solução em definitiva – a única que não fracassou em nossa solução de leitura a arquivos grandes – a classe open-source SynBigTable !

Processando a leitura das linhas com SynBigTable

Esta classe é incrivelmente rápida; sua leitura é eficiente e invejável, lendo e salvando em um arquivo externo como o buffer da operação de leitura e armazenamento temporário das linhas de um arquivo superior a 1,5GB. A operação de leitura poderá ser repetida quantas vezes forem necessárias – e com louvável resultado de processamento, eficiente e razoável – levando em média dois minutos. E esse será o tempo de espera – mas o que são dois minu-tos para arquivos com mais de 2GB (nos testes, para ser mais exato – 2,2GB)?

Também com ela foi utilizada a unit FastMM4 como gerenciador eficiente de memória. Os resultados obtidos através dela foram impressionantes.

Com a classe TSynBigTableRecord é perfeita para manipulação de regis-tros, aos milhões de uma vez, com a rapidez em poucos segundos, sempre gravando em um arquivo temporário; de acordo com os desenvolvedores é ideal para um registro de log, e a nossa ideia a ser implementada aqui é utilizar esta classe como estrutura de apoio a nossa leitura dos arquivos “gigantes” sem comprometer a performance ou a memória, pois já está tudo bem imple-mentada com ela sem problema algum. Basta definir primeiramente o nome do arquivo temporário a ser criado – e depois criar os campos (sim, funciona como um banco de dados local baseado em arquivos, mas sem SQL) e depois popular os campos e salvando, até terminar. E esta operação será feita de forma bem rápida.

O processo básico de funcionamento com a classe TSynBigTableRecord é o seguinte:

1. Criar um arquivo - T := TSynBigTableRecord.Create(‘meuBD.extensao’,’TableName’);

Page 12: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201512

2. Definir os campos - T.AddField(‘Line’,tftWinAnsi,[tfoIndex]);3. Mais um campo - T.AddField(‘Number’,tftInt32,[tfoIndex]);4. Salvar as alterações - T.AddFieldUpdate;5. Utilizar variáveis do tipo TSynTableFieldProperties para melhor

performance de memória;6. Definir portanto duas variáveis para o nosso exemplo, sendo: fiel-

dLine, fieldNumber: TSynTableFieldProperties;7. Assim, ficando – fieldLine := T.Table[‘Line’];8. Para o segundo campo, ficando – fieldNumber := T.Table[‘Number’];9. Definir uma variável do tipo TSynTableData, para acessar os campos

em um conjunto de registros;10. Inicializar a variável definida acima – data.Init(T.Table);11. Popular os campos recém-criados, como no nosso exemplo: data.

SetFieldValue(fieldLine, strList.Strings[i]); //more faster than: data.Field[‘Line’] := strList.Strings[i];

12. E também com o segundo campo – data.SetFieldValue(fieldNumber, lineCounter); //more faster than: data.Field[‘Number’] := lineCounter;

13. Comando para criar os dados nos campos: T.RecordAdd(data);14. E finalmente, para salvar (como um “commit”) – T.UpdateToFile;15. Para terminar, logicamente como em toda variável destruí-la como

em T.Free (usamos FreeAndNil(T)).

Na prática, o código-fonte ficaria assim:

varT: TSynBigTableRecord; data: TSynTableData; fieldLine, fieldNumber: TSynTableFieldProperties; rec: TSynTableData;{ … }

T := TSynBigTableRecord.Create(FN,’TableName’);

DeleteTempDataBaseFile;// T.Clear;T.AddField(‘Line’,tftWinAnsi,[tfoIndex]);T.AddField(‘Number’,tftInt32,[tfoIndex]);T.AddFieldUpdate; fieldLine := T.Table[‘Line’];fieldNumber := T.Table[‘Number’];data.Init(T.Table);

{ ... }

data.SetFieldValue(fieldLine, strList.Strings[i]); //more faster than: data.Field[‘Line’] := strList.

Strings[i];data.SetFieldValue(fieldNumber, lineCounter); //more faster than: data.Field[‘Number’] := lineCounter;T.RecordAdd(data);{ … }

Continuação:

if T.CurrentInMemoryDataSize>400 shl 20 then // write on disk every 400 MBbegin T.Pack; T.UpdateToFile; end;

O processo básico de leitura com TSynBigTableRecord é o seguinte:1. Criar arquivo temporário;2. Processar leitura linha a linha;3. Alocar memória pra elas; 4. Gravar o fluxo de dados em arquivo a cada 400MB;5. Finalizar a operação e liberar a memória alocada;6. Remover arquivo temporário.

Porque TSynBigTableRecord?

Porque é a melhor escolha para leitura linha a linha de arquivos grandes. Outras demais tradicionais alternativas e outras desenvolvidas por terceiros frustraram todas as minhas expectativas (como disse no início deste artigo) pelo fato de estourar a memória e de travar a aplicação.

Qual o tempo gasto para ler um arquivo de 2GB?

Depende da memória utilizada para outros processos, quantos programas estão abertos e consumindo memória razoável, etc – mas com meus testes com 3GB de RAM obtive para arquivos de 2.2GB um tempo médio de 2 minutos, podendo variar até para 2,30 minutos.

Posso ler arquivos com mais de 2GB?

Sim, claro. O tempo vai subir um pouco; uma média de 1 minuto por GB, mas sem problemas desde que a memória suporte. Aparentemente nossa solu-ção contempla facilmente até 4GB de arquivos (embora não testado – testado até com 2.2GB) – mas provavelmente não haverá problema para estes limites de até 4GB. Além deste tamanho deve ser realizados testes para observar se também será possível sua leitura.

Assim sendo, realizar o processamento de um arquivo grande utilizando nossas consagradas soluções como a nossa TListView virtual utilizando a nossa estrutura TLineReaderList para arquivos de até 1.5GB e a classe TSynBigTable-

Page 13: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 13

Record para arquivos maiores que 1.5GB será a nossa solução em definitivo.

Fator Arquivos até 1.5GB Arquivos maiores que 1.5GB

Velocidade Até 30 segundos 2 minutos e meioEstrutura TLineReaderList TSynBigTableRecordMemória Full Utiliza a memória e

transfere dela para um arquivo temporário

Dependência Externa Nenhuma Um arquivo temporário como o buffer dos registros, disponível apenas durante a execução do aplicativo

Eficiência Sim SimPraticidade Ótima; pode-se

repetir a operação quantas vezes forem necessárias e desde que a memória suporte

Ótima; pode-se repetir a operação quantas vezes forem necessárias e desde que a memória suporte

Esta classe é incrivelmente rápida; sua leitura é eficiente e invejável, lendo e salvando em um arquivo externo como o buffer da operação de leitura e armazenamento temporário das linhas de um arquivo superior a 1.5GB. A operação de leitura poderá ser repetida quantas vezes forem necessárias – e com louvável resultado de processamento, eficiente e razoável – levando em média dois minutos. E esse será o tempo de espera – mas o que são dois minu-tos para arquivos com mais de 2GB (nos testes, para ser mais exato – 2.2GB)?

Os requisitos básicos para o funcionamento (vamos abordar sobre a classe TSynBigTableRecord) desse processo é a permissão de gravação no diretório do aplicativo, espaço em disco e disponibilidade de memória. Basicamente isso é tudo, por enquanto. Atendendo a estes três itens fundamentais a probabilidade de se concluir a operação com sucesso será alta. Claro que se deve observar é o tempo de espera (abordado no item “velocidade” da tabela descrita acima) – pois isso é tudo dependente de memória – portanto quando disse “dois minutos” é apenas uma média – e isso pode variar, dependendo da memória disponível e a quantidade de programas abertos no momento, se há algum aplicativo consumindo consideravelmente espaço em memória, etc – o tempo poderá demorar mais que isso. Para isso espere alguns segundos e refaça a operação, feche quantos programas puder e veja se não há algum programa “pesado” neste instante.

Figura 01 – Mensagem de confirmação de sucesso da operação de leitura.

Figura 02 – Tela do aplicativo FastFile onde mostra que um arquivo de 2.2GB foi carregado com sucesso.

Figura 03 – Outra tela do aplicativo FastFile, desta vez exibindo as últimas linhas de um arquivo de 2.2GB carregado com sucesso.

Figura 04 – Exibição (primeiro arquivo a direita) do arquivo FASTFILE (sem extensão), que é um arquivo temporário utilizado no buffer dos registros das linhas processadas pelo TSynBigTableRecord para arquivos maiores que 2GB.

Figura 05 – Tela do aplicativo FastFile onde mostra que um arquivo de 1.2GB foi

Page 14: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201514

carregado com sucesso; neste caso foi utilizada a estrutura baseada em TList, onde por ser bem rápido seu acesso o tempo estimado para abrir o arquivo foi de 24 segundos.

Figura 06 – Mensagem de confirmação da leitura – para o arquivo de 1.2GB levando 24 segundos. Para até 1.5GB geralmente tende a ser mais rápido.

Algumas considerações a serem observadas pela classe SynBigTable:1. Ela utiliza internamente uma estrutura chamada TFileBufferReader,

que é baseada em arquivos mapeados em memória (Memory Mapped Files) para arquivos até 2GB – no comentário deste fonte é informado que o Windo-ws tem problemas para alocar memória para maior que 2GB, pelo menos na versão de 32 bits. Ainda informa que as vezes o Windows também pode falhar para alocar para mais que 512 MB para um mapa de memória (memory map). Neste caso a leitura direta será realizada, sendo mais lenta porém sem limites de tamanho de arquivo. É uma importante observação, escrita na definição da classe TFileBufferReader na unit SynCommons;

2. Os dados podem ser acessados por um CD/DVD, onde ficarão em memória. Poderá inclusive manipular estes dados, como incluir novos, editar, etc; só que neste caso não serão salvos;

3. Com poucos KB será criado um arquivo que será a persistência destes dados, para inúmeros registros;

4. A classe TSynBigTableRecord permitirá gravar um milhão de registros com tempobem rápido – inferior a 900ms (utilizando índices e métodos rápidos de pesquisa);

5. Pode-se gravar também campos blob, figuras, etc;6. Alternativa fácil de compartilhamento de dados entre Delphi 7 e

Delphi XE;7. Pode ser utilizado para implementar um log ou trilha de auditoria

em sua aplicação;8. Não é indicado para substituir um banco de dados existente;9. Não suporta SQL;10. Não interage com componentes DBExpress bem como demais

componentes de acesso a dados;11. Para um banco de dados com SQL é recomendado um framework

também desenvolvido por eles chamado SQLite3;12. Os dados são armazenados em um arquivo único;13. A recuperação é muito rápida neste arquivo; 14. Os dados são acrescentados no final deste arquivo, usando um

cache para a adição imediata;15. Enquanto o método UpdateToFile não é chamado, os dados per-

manecem na memória;16. A propriedade CurrentInMemoryDataSize contém o tamanho da

memória preenchida com estes dados (em bytes) – enquanto eles não forem salvos. Com esta propriedade é possível definir um “ritmo” de salvamento destes dados para o arquivo, por exemplo: Em cada 200MB, transferir os dados para o arquivo, salvando-o;

17. Utiliza funções desenvolvidas por eles como, por exemplo, a “JSO-

NEncodeArray” – para conversão dos dados para o formato JSON;18. Utiliza também o tipo criado por eles chamado “RawUTF8” – um tipo

de string UTF-8 armazenado em um AnsiString (de acordo com os comentários do código-fonte: “Usar esse tipo em vez de System.UTF8String, pois houve mudanças entre o compilador Delphi 2009 e versões anteriores: a nossa im-plementação é consistente e compatível com todas as versões do compilador Delphi”) Declarado na unit SynCommons.

19. E por fim, também utiliza o tipo criado por eles para o formato Unicode, chamado RawUnicode, que segundo eles é mais rápido que o tipo WideString (unit SynCommons).

Segue abaixo o código-fonte da procedure “ProcessFile” – a mais impor-tante do FastFile, onde toda a lógica de implementação da leitura dos arquivos é realizada, utilizando as classes TLineReaderList e a SynBigTable:

procedure TfrmMain.ProcessFile(const StrFilename: String);var StrmInput: TFileStream; StrmOutput: TMemoryStream; FileNumber: Integer; PartFileSize: integer; OriginalFileSize: Int64; TotalPartsToDivide: Integer; i: integer; strList: TStringList; lcur_temp: TCursor;begin if (StrFilename = ‘’) then Exit; if not (SysUtils.FileExists(StrFilename)) then Exit; tempFolder := Self.ExtractName(SysUtils.ExtractFileName(StrFilename)); PathDirectory := (ExtractFilePath(StrFilename) + tempFolder); gpContainer.Caption := ‘File Contents’;

{if FileExists(Self.GetLocalDirectory + cTempDataBaseFile) then begin DeleteFile(Self.GetLocalDirectory + cTempDataBaseFile); end; }

DestroyInMemoryObjects; DestroyTLineReaderListObjects;

Page 15: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 15

TrimAppMemorySize;

FLineReaderList := TLineReaderList.Create;

GetTempDataBaseFile;

T := TSynBigTableRecord.Create(FN,’TableName’);

DeleteTempDataBaseFile; // T.Clear; T.AddField(‘Line’,tftWinAnsi,[tfoIndex]); T.AddField(‘Number’,tftInt32,[tfoIndex]); T.AddFieldUpdate; fieldLine := T.Table[‘Line’]; fieldNumber := T.Table[‘Number’]; data.Init(T.Table);

try if SysUtils.DirectoryExists(PathDirectory) then SysUtils.RemoveDir(PathDirectory); SysUtils.CreateDir(PathDirectory); except on E:Exception do Raise Exception.Create(E.Message); end;

//FileSize := Round(Biblioteca.GetFileSize(StrFilename) / NumberOfParts); try OriginalFileSize := Self.GetFileSize(StrFilename); PartFileSize := NumberOfPartsToDivide(OriginalFileSize); TotalPartsToDivide := System.Round(OriginalFileSize/PartFileSize);

except on E:Exception do Raise Exception.Create(E.Message); end;

if (Self.RoundUpWithDecimais(

OriginalFileSize/PartFileSize, 2)) > (TotalPartsToDivide) then Inc(TotalPartsToDivide);

ProgressBar.Max := TotalPartsToDivide;

lblOriginalFileSize.Caption := ‘Original FileSize: ‘ + FormatFloat(‘#,’, Self.RoundUpWithDecimais(OriginalFileSize/1024, 2)) + ‘ KB’; lblPartFileSize.Caption := ‘Part FileSize: ‘ + FormatFloat(‘#,’, Self.RoundUpWithDecimais(PartFileSize/1024, 2)) + ‘ KB’; lblNumberOfParts.Caption := ‘Number of Parts: ‘ + FormatFloat(‘#,’, TotalPartsToDivide);

FileNumber := 1; ProgressBar.Position := 0; Tag := 0; lineCounter := 0; memoLog.Clear; stLines.Caption := ‘’;

bFileIsUpTo1_5_GB := (OriginalFileSize > 1500000000);

Self.ActionComponent([ListView1, ScrollBar1], acNotVisible); strList := TStringList.Create;

StrmInput := TFileStream.Create(StrFilename,fmOpenRead or fmShareDenyNone);

Self.ActionComponent([btnCancel], acEnabled); Self.ActionComponent([btnReadToVirtualListView, btnHelp], acNotEnabled); lcur_temp := frmMain.f_set_cursor(crHourGlass);

try while (StrmInput.Position < StrmInput.Size) and (Tag = 0) and (ProgressBar.Position < FileNumber) do

Page 16: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201516

begin // SequentialFile := ChangeFileExt((ExtractFilePath(StrFilename) + // IncludeTrailingPathDelimiter(tempFolder) + ExtractFileName(StrFilename)),’.’+Format(‘%.03d’,[FileNumber]));

//StrmOutput := TFileStream.Create(SequentialFile ,fmCreate);// ==> Don´t use: it´s very slow !!

StrmOutput := TMemoryStream.Create; try if StrmInput.Size - StrmInput.Position < PartFileSize then PartFileSize := StrmInput.Size - StrmInput.Position;

StrmOutput.CopyFrom(StrmInput,PartFileSize); // strList.Clear; ==> Don´t use: it´s very slow !! strList.Text := Self.MemoryStreamToString(StrmOutput);

for i := 0 to strList.Count - 1 do begin if (bFileIsUpTo1_5_GB) then begin data.SetFieldValue(fieldLine, strList.Strings[i]); //more faster than: data.Field[‘Line’] := strList.Strings[i]; data.SetFieldValue(fieldNumber, lineCounter); //more faster than: data.Field[‘Number’] := lineCounter; T.RecordAdd(data); end else FLineReaderList.Add(TLineReader.Create(strList.Strings[i], lineCounter));

Inc(lineCounter); end;

ProgressBar.Position := ProgressBar.Position + 1;

Application.ProcessMessages; finally FreeAndNil(StrmOutput); end; Inc(FileNumber);

if (bFileIsUpTo1_5_GB) then if T.CurrentInMemoryDataSize>400 shl 20 then // write on disk every 400 MB begin T.Pack; T.UpdateToFile; end; end; finally

FreeAndNil(StrmInput); FreeAndNil(strList); Self.ActionComponent([btnCancel], acNotEnabled); Self.ActionComponent([btnReadToVirtualListView, btnHelp], acEnabled); frmMain.f_set_cursor(lcur_temp); end;end;

Acima: Transcrição do fonte da função “ProcessFile”.

Testando Performance

Foram realizados alguns testes para medir a velocidade de execução de inserção de 1.000.000 de itens dinamicamente, a fim de certificar o componen-te/estrutura com o melhor tempo de resposta. A ideia é aproveitar para novos releases do projeto e outros temas, bem como ilustrar nossa implementação visto que as estruturas utilizadas na nossa construção também fazem parte destes testes.

É importante a medição deste teste, pois podemos saber o componente/estrutura que melhor se adapta a cada situação. Por exemplo, se precisarmos armazenar certo número de itens em memória, se precisamos persistir estes dados para posterior recuperação, enfim, negocialmente qual a melhor pro-posta viável. Depende sempre do que será implementado para cada situação.

Objetivo do teste:Contar de zero a um milhão e popular um campo com este contador.

Simples.

Page 17: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 17

Foram testados os seguintes componentes e estruturas:1. TRxMemoryData (componente do pacote RXLib);2. THVDataSet (componente baseado em TMemoryStream);3. TClientDataSet (do Delphi mesmo);4. TUserList (estrutura baseada em TList);5. TSynBigTableRecord (classe do framework SynBigTable).

Figura 07 – Tela do nosso aplicativo de performance.

Figura 08 – Mensagem de confirmação informando o vencedor do teste, a estrutura TUserList. Com média de 1 segundo, um milhão de itens foram gerados.

Segue abaixo a relação dos tempos estimados de cada item testado. Levando em consideração a geração de 1.000.000 de itens dinamicamente. Computador com 4GB de memória RAM e processador 2,50 GHZ. São 5 ob-jetos que foram testados; cada um tem uma ligeira diferença de velocidade. Particularmente acreditava que o TRxMemoryData (pacote RXLIB) fosse um dos mais rápidos devido a sua implementação toda em memória, conforme é informado em seus comentários. Mas frustrou a expectativa por ser dema-siadamente lento para este propósito.

Tabela comparativa dos Objetos

Componente/Estrutura VelocidadeTRxMemoryData 7 minutos e 10 segundosTHVDataSet 5 segundosTClientDataSet 5 minutos e 58 segundosTUserList 80 milésimos de segundoTSynBigTableRecord 495 milésimos de segundo

Figura 09 – Tela inicial do nosso aplicativo de performance.

Figura 10 – Tela do nosso aplicativo de performance com o teste do clientdataset

executado.

Figura 11 – Mensagem de confirmação do teste do clientdataset, levando em média quase 6 minutos.

Figura 12 – Mensagem de confirmação do teste do TUserlist, levando em média quase 1 segundo. Impressionante a sua velocidade nesta estrutura baseada em TList – por essa razão (ser baseada em uma lista de ponteiros) a velocidade sempre será a mais rápida de todas, armazenando tudo em memória. A desvantagem é que a memória não é ilimitada e por isso esta estrutura poderá estourar a memória – dependendo da quantidade de itens gerados. Mas facilmente chegará a vinte milhões de itens na média de 1 segundo, e assim por diante.

Portanto, baseado nos testes podemos observar que o objeto mais rápido de todos foi a nossa estrutura TUserList, a campeã em velocidade, estimando cerca de 1 segundo no máximo para a geração de milhões de registros. Essa estrutura foi a utilizada no nosso aplicativo FastFile para a leitura de arquivos até 1.5GB, batendo na casa de 30 segundos no máximo (se não menos que isso) para sua leitura e exibição destas linhas em um objeto de TListView no modo virtual, sendo ela como a estrutura de suporte para a exibição destes dados.

E se um arquivo a ser lido for superior ao tamanho de 1.5GB a estrutura utilizada para renderizar o objeto TListView virtual será a classe TSynBigTable-Record, que é a segunda colocada em velocidade nos nossos testes – levando alguns segundos a mais, podendo logicamente levar um minuto a mais, dependendo da memória disponível no computador onde está sendo execu-tado o aplicativo no momento, bem como acesso ao disco rígido, aplicativos

Page 18: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201518

consumindo memória no momento, etc;

O nosso aplicativo FastFile, como vimos, utiliza os objetos campeões de velocidade. São os mais rápidos encontrados e disponíveis. Enquanto um foi desenvolvido especialmente para este projeto (TUserList) – o outro objeto (TSynBigTableRecord) foi apenas utilizado na nossa implementação; ele é componente de terceiros e open-source.

Conclusão

Este aplicativo foi construído pelo simples fato de que inúmeros desen-volvedores ainda até hoje não dispõe de uma alternativa viável, útil e eficiente de como abrir um arquivo bem grande (em GBs de tamanho) para sua leitura. Muitas classes encontradas tradicionalmente bem como as de terceiros não são tão boas assim – para carregar até uns 300MB a performance quase sem-pre é comprometida, e sem contar o tamanho além disso. Muito provável a falta de memória é apresentada como exceção pelo Delphi e o travamento da aplicação – e o usuário é frustrado por não abrir este arquivo pesado – e isso é bem comum nos dias de hoje; não temos uma solução de sucesso para esta finalidade.

As outras versões anteriores do nosso FastFile não permitiam abrir arquivos maiores de que 1.5GB de tamanho – ocasionando erro de falta de memória. Até este tamanho era possível perfeitamente – o problema era depois deste valor que sempre apresentava erros de “OutOfMemory”.

Nesta atual versão implementamos um controle eficiente de como abrir arquivos maiores que 1.5GB sem problemas, sem mais limites de tamanho – o que define o limite será a capacidade da memória RAM disponível para tal – abrindo arquivos “gigantes” agora requer um pouco mais de tempo (+/- 2 minutos) para esta operação, porém finalizando sempre com sucesso, associando com a classe TSynBigTableRecord de SynBigTable, onde por sua vez registra em um arquivo temporário todos os dados contidos na memória – então temos agora maior segurança na nossa implementação – estouro de memória será bem mais difícil – pouca memória, pouco espaço em disco, falta de permissão de gravação em disco, muitos programas abertos simulta-neamente, etc; são alguns fatores que podem prejudicar o processamento de leitura destes arquivos grandes.

Continuamos apostando na solução de TListView virtual por ser muito prático o seu carregamento dos dados, visto que na verdade este objeto não

armazenada nada diretamente, pois não é proprietário dos seus dados, e sim os nossos objetos de apoio definidos e mencionados anteriormente. Eles que manipularão a visualização linha por linha através do número de cada uma delas – e será sempre um procedimento rápido visto que já foi registrado na memória antes.

Portanto, implementamos uma alternativa eficiente, profissional e viável de como abrir um arquivo extremamente grande para sua leitura e exibir seus dados neste objeto de TListView virtual. Por enquanto, é possível apenas visualizar estes dados, não sendo possível alterá-los nem removê-los. O aplicativo apenas contempla a função de carregamento do arquivo em si, a qual é considerada a mais complexa aqui na nossa implementação. Outra observação é que apenas arquivos-texto comuns com caracteres de controle do código ASCII de “início da posição do cursor/nova linha” (Carriage Return + Line Feed = CR+LF) podem ser processados pelo aplicativo. Não é suportado para arquivos binários ou demais extensões oriundas de outros aplicativos.

O aplicativo é muito prático para esta funcionalidade, de forma elegante, rápida e “esperta” o usuário acompanha o progresso da operação de leitura do arquivo (através de um objeto do tipo TProgressBar) – onde a nossa solução poderá sempre ser repetida quantas vezes forem necessárias.

Com isso, trago a terceira versão deste aplicativo promissor para a leitura eficiente e segura em arquivos grandes. Também poderá ser abrir arquivos não tão grandes e pequenos. Mas a ênfase é para os grandes. Com isso encerro esta edição e desejo um forte abraço a todos. Bons estudos e até a próxima!

[email protected]

Hamden VogelAnalista de Sistemas pós-graduado em Engenharia de Software pela

UPIS e Programador Delphi com larga experiência desde 2000, tem de-senvolvido e vendido softwares em Delphi para a África e Estados Unidos, além do mercado nacional. Colaborou com dicas e componentes para sites especializados em Delphi. Também desenvolve em outras linguagens como C/C++, ASP, PHP e .NET.

Sobre o autor

Page 19: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 19

No artigo deste mês, irei abranger um assunto de extrema importância e muitas vezes esquecido entre nós, pois às vezes são taxados erroneamente como recursos muito complexos, discorremos de uma forma mais fácil possível dos denominados “Delegates” na linguagem C#. É inte-

ressante antes de partirmos para a parte prática aprendermos um pouco de conceito para assim compreendermos melhor.

Origem

Quando tratamos do assunto “Delegates”, não podemos esquecer do conceito de Ponteiro de função, vindo lá de trás das linguagens C e C++. Estes conceitos foram muito úteis durante a programação dos Sistemas Operacionais, sendo inteiramente baseada no conceito de funções de retorno de chamada para processar “mensagens”. Exatamente por esta razão foram implementadas mais adiante na linguagem C# os denominados “Delegates”, assumindo este papel necessário no nosso dia a dia. O uso de “Delegates” permite ao progra-mador fazer uma referência a um método, encapsulando a referência do mesmo dentro de um objeto de delegação, adquirindo uma maior flexibilidade para implementar diversas funcionalidades em tempo de execução.

Um pouco mais de teoria

Um “delegate” é um tipo especial de variável definido pelo usuário que é declarada como uma classe. Para métodos estáticos, um objeto “delegate” encapsula o método a ser chamado. Para os métodos de instância, um objeto “delegate” incorpora tanto uma instância e um método na instância. Se você tem um objeto “delegate” e um conjunto apropriado de argumentos, você pode invocar o “delegate” com os argumentos. Na linguagem C# possuímos um código gerenciado, é necessário especificar o tipo de cada parâmetro que um método receberá para que o compilador realize validações nas cha-

Linguagem C# - Delegates em Windows Forms

madas de um método. Em outras palavras, podemos dizer que para passar um método por parâmetro este deverá ser um tipo. É neste momento que o .NET Framework oferece os “delegates” como mecanismos que nos permite referenciar os métodos.

Resumo das principais propriedades

1) São como ponteiros de função, mas considerados tipos seguros.

2) Permite que os métodos são passados como parâmetros.

3) Também podem ser usados para definir os métodos de “retorno de chamada“ (callback methods)

4) Podem ser encadeados, como por exemplo, vários métodos podem ser chamados em um único evento.

5) A partir da versão 2.0 do C# foi introduzido o conceito de Métodos anô-nimos, que permitem que blocos de código a serem passados como parâmetros em vez de um método definido separadamente. Já na versão 3.0 do C #, as expressões lambda foram introduzidas como forma mais concisa de escrever blocos de código embutido. Ambos métodos anônimos e expressões lambda (em determinados contextos) são compilados para delegar tipos. Juntos, esses recursos são agora conhecidos como funções anônimas.

Para entendermos melhor

Antes de entrarmos em detalhes na declaração, sintaxe e uso prático deste mecanismo, vou aprofundar o aprendizado com analogias mais simples. Supo-nhamos a declaração de uma variável do tipo “string” e como ela se comporta.

Ver Imagem 01.

Page 20: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201520

Figura 01: Alocação de memória de uma variável “string”.

Na Figura 01 podemos ver com detalhes o que acontece quando declara-mos uma variável. Declaramos uma variável do tipo “string” e então atribuímos o valor “The Club”, sendo que para esta variável é alocado um endereço de memória que conterá o texto “The Club” e este endereço de memória aponta para a variável de nome “str”.

O funcionamento dos “Delegates” se assemelha com a declaração de uma variável, como por exemplo de um “string”, sendo que a única diferença é que um “delegate” aceita métodos, em outras palavras, podemos dizer que “guarda métodos na memória”. Com esta façanha podemos executá-los no momento que desejarmos, em “run-time”.

Declarando um Delegate

Para declarar um “delegate”, utilizamos a palavra-chave “delegate”. A sintaxe base utilizada para criá-lo é a seguinte:

<Modificador de acesso> delegate <Tipo de Retorno> <Nome do Delegate>([Parametros]);

Exemplo:

public delegate int CalculoQualquer(int valor1, int valor2, int valor3);

Abaixo iremos discorrer de todos os detalhes:

Modificador de Acesso: O modificador pode ser um ou uma combinação adequada dos mesmos, sendo: new, public, private, protected ou internal.

Delegate: Palavra necessária para declarar um “delegate”.

Tipo de Retorno: O tipo de retorno pode ser qualquer tipo de dados (int, string, decimal, etc ...) ou podemos também não retornar nada (void). Os tipos específico como classes, structs também são aceitos.

Nome do Delegate: O nome deve ser um nome válido para um método.

Parâmetros: Valores opcionais, devendo ou não tê-los em sua assinatura, dependendo da necessidade.

Após a declaração de um “delegate”, devemos nos lembrar que o mesmo apenas fornece um modelo para um método, não um método real. Para usá-lo devemos definir um método que levaria uma atribuição do mesmo.

Importante salientar que este método deve ter o mesmo tipo de retor-no, número de parâmetros caso exista. Após a implementação do método deveremos associá-lo ao nome do “delegate”.

Exemplo:

CalculoQualquer Calculo = new CalculoQualquer(EfetuarCalculo);

Lembrando que o Método “EfetuarCalculo” deverá possuir a mesma estrutura do “Delegate”, ou seja, três parâmetros de entrada e um de saída ambos inteiros. Veremos mais detalhes adiante.

Criando um Exemplo

Para fixarmos melhor este conceito iremos implementar dois exemplos, sendo o primeiro mais simples e o segundo um pouco mais elaborado. Para isto crie uma aplicação do início no Microsoft Visual Studio clicando em “File/New/Project...” e escolhendo “Windows Forms Application”. Fique a vontade para definir o nome que desejar para o Formulário. O nosso primeiro exemplo irá utilizar apenas um “Button”.

Exemplo 01

A intenção deste exemplo é de mostrar uma mensagem utilizando “De-legates”, Ver Listagem 01.

using System;using System.Collections.

Page 21: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 21

Listagem 1

Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;

Para aplicações Windows Forms usaremos algumas bibliotecas padrões.

...public delegate void MostrarMensagem();

Declaramos o “delegate”, conforme explicado anteriormente, com o modi-ficador de acesso do tipo “public” e sem nenhum retorno de entrada e de saída.

public MostrarMensagem Mensagem;

Variável pública para atribuir o “delegate” para a mesma.

public void MetodoMensagem(){ MessageBox.Show(“Este é um teste do The Club Trabalhando com ‘Delegates’”);}

Método público do tipo “void” (Sem retorno algum), o mesmo tipo de método declarado no “delegate”.

private void button1_Click(object sender, EventArgs e){ Mensagem = new MostrarMensagem(MetodoMensagem); Mensagem();}

Ao clicar no botão faremos a atribuição do método “MetodoMensagem” ao “delegate” (invocando o método em run-time) o chamando da seguinte maneira: “Mensagem()”. Teremos um resultado parecido com a Imagem 02.

Figura 02: Exemplo em modo de execução.

Exemplo 02

Para o segundo exemplo iremos criar uma classe chamada “Operacoes-Matematicas”. A partir dela criaremos os métodos para as quatro operações matemáticas, possuindo a mesma assinatura de um “delegate” base. Para criar uma classe, clicaremos em “Add/new item/Code” definindo o nome como: “OperacoesMatematicas.cs”. Ver Listagem 02.

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;

namespace BibliotecasTheClub{

Em “namespace” deixei como padrão de identificação o nome “Biblio-tecasTheClub”.

public delegate int Operacoes(int value1, int value2);

Teremos a assinatura do “delegate” como modificador de acesso “public”, com retornos de entrada e saída de dados, ambos do tipo “int”.

public class OperacoesMatematicas {

Dentro da classe implementaremos os métodos “Soma, Subtracao, Mul-tiplicacao e Divisao”.

Page 22: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201522

Listagem 2: Classe “OperacoesMatematicas.cs”.

public int Soma(int valor1, int valor2) { return valor1 + valor2; }

public int Subtracao(int valor1, int valor2) { return valor1 - valor2; }

public int Multiplicacao(int valor1, int valor2) { return valor1 * valor2; }

public int Divisao(int valor1, int valor2) { return valor1 / valor2; }

Teremos todos os métodos com a assinatura exata do delegate.

}}

Para utilizarmos esta classe, voltaremos ao Formulário criado anteriormen-te e adicionaremos mais um “Button” com os “labels” para resultado da Soma, Subtração, Multiplicação e Divisão dos métodos. Ver Imagem 03.

Figura 03: Exemplo de Formulário.

Podemos conferir a codificação na listagem 03.

public static OperacoesMatematicas ope = new OperacoesMatematicas();

Criaremos a instância da classe a qual contém os métodos que serão atribuídos aos objetos “delegates”.

Operacoes Somar = new Operacoes(ope.Soma);Operacoes Subtrair = new Operacoes(ope.Subtracao);Operacoes Multiplicar = new Operacoes(ope.Multiplicacao); Operacoes Dividir = new Operacoes(ope.Divisao);

Atribuímos os objetos “delegates” denominados “Operacoes” para os métodos “Soma, Subtracao”, Multiplicacao e Divisao”.

private void button2_Click(object sender, EventArgs e) {lblSoma.Text = “Soma: “ + Somar(4, 2).ToString();

lblSubtracao.Text = “Subtracao: “ + Subtrair(4, 2).ToString(); lblMultiplicacao.Text =”Multiplicação: “ + Multiplicar(4, 2).ToString(); lblDivisao.Text =”Divisão: “ + Dividir(4, 2).ToString(); }

No evento Click do Botão 2 executamos os métodos criados anteriormente, passando sempre dois valores por parâmetro e tendo como retorno um valor inteiro. Sempre respeitando a assinatura base do “delegate”. Ver Imagem 04.

Page 23: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 23

Figura 04: Operações Matemáticas.

Conclusões

Como foi dito ao longo do artigo e expressado através de exemplos práticos, o uso de “delegates” torna-se indispensável para todo programador, possuindo características marcantes como: passar métodos por parâmetros, definição dos métodos de chamada (Callback methods), possibilidade de encadeamento de vários métodos em um único evento, entre outras coisas.

[email protected]

Thiago Cavalheiro Montebugnoliadora aprender novas tecnologias. Formado pela Faculdade de Tecnologia de Botucatu

– SP (FATEC), já desenvolveu softwares utilizando a plataforma .NET, Delphi junto com Banco de Dados SQL Server e Firebird. Atualmente trabalha no Centro de Processamento de Dados da Prefeitura Municipal de Itaí-SP é colunista mensal da Revista The Club Megazine e é consultor Técnico do The Club. Possui as seguintes certificações: MCP - Microsoft Certified Professional, MCTS - Microsoft Certified Technology Specialist, MCAD - Microsoft Certified Application Developer e MCSD - Microsoft Certified Solution Developer.

Sobre o autor

É importante lembrar que a intenção maior deste tutorial foi de desmisti-ficar este importante recurso da linguagem C#, ficando como responsabilidade do desenvolvedor saber quando e onde implementar esta técnica.

Um forte abraço e até o mês que vem!

Page 24: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201524

Listagem 1. Código dos botões

O XE8 está aí, cheio de novidades, com muitas features novas. Veja as novidades em: http://blogs.embarcadero.com/fernandorizzato/index.php/2015/04/08/delphi-e-c-builder-xe8-todos-os-detalhes-da-nova-versao.

Neste artigo, usaremos o XE8 com uma funcionalidade VCL que recebo muitos e-mails. Como integrar Web na sua aplicação VCL. Muitos dos pedidos, indicam que o cliente não quer abrir o navegador da máquina do cliente e quer um navegador dentro do seu sistema, ou seja, dentro do Delphi.

No artigo onde criamos formulários em abas de um PageControl, mostrei o controle WebBrowser e algumas características do mesmo para simularmos um browser. Vamos conhecer o controle WebBrowser para criarmos um na-vegador no Delphi.

Podemos adicionar várias características presentes nos navegadores, como botões para avançar e voltar, impressão da página HTML, adicionar os favoritos em um menu, pesquisa de texto, entre outros.

Criando a aplicação

Vamos criar uma aplicação VCL no Delphi XE8 (File>New>VCL Forms Ap-plication). No formulário, adicione um Toolbar dentro de um Panel. Adicione botões para as seguintes funcionalidades: voltar, avançar, refresh, home e imprimir.

Adicione imagens aos botões, e adicione um Edit (esse dentro do Panel). Por fim, adicione um WebBrowser. Veja na Figura 1 como ficará nosso projeto.

Figura 1. Formulário principal do projeto

N a v e g a d o r n o Delphi XE8

Para os primeiros botões, vamos usar o código da Listagem 1.

Botão VoltarWebBrowser1.GoBack;

Botão AvançarWebBrowser1.GoForward;Botão RefreshWebBrowser1.Refresh;

Botão HomeWebBrowser1.GoHome;

Nota: poderíamos usar um ActionList e criar Actions para vincular aos botões da barra.

Veja que os métodos são simples, lembrando que o código do Home, vai abrir o site configurado como home page do seu navegador padrão (Chrome, IE, FireFox, Opera etc). Temos ainda um método chamado GoSearch que carrega a página de busca padrão configurada no navegador.

Para a navegação, o usuário irá digitar o endereço no Edit e apertar ENTER, portanto adicionaremos o seguinte código no evento OnKeyDown do Edit.

if key = VK_RETURN then WebBrowser1.Navigate(edtEndereco.Text);

Page 25: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 25

Listagem 2. Código pra opções de impressãoNota: para o evento OnKeyDown ser disparado, é necessário alterar

para True a propriedade KeyPreview do formulário.

Faça um teste, abrindo a aplicação, digitando um endereço válido na caixa de texto e aperte ENTER ou clique no botão (Figura 2).

Figura 2. Testando a aplicação

Impressão da página

Temos algumas opções para a impressão da página. Podemos visualizar a impressão, encaminhar o documento diretamente para a impressão e também abrir a tela de configuração de impressão da página. Então, vamos transformar o botão da barra para receber um menu, assim que for clicado, com essas opções.

Adicione um PopupMenu no formulário e configure as propriedades DropDownMenu para o controle recém adicionado e a propriedade Style para tbsDropDown. No menu, adicione os seguintes itens: “Configurar página”, “Visualizar impressão” e “Imprimir”. Veja na Figura 3 como fica o menu.

Figura 3. Menu com opções de impressão

Para os itens de menu, vamos usar o código da Listagem 2.

Configurar página

var vIn, vOut: OleVariant;begin WebBrowser1.ControlInterface.ExecWB(OLECMDID_PAGESETUP, OLECMDEXECOPT_PROMPTUSER, vIn, vOut);end;

Visualizarvar vIn, vOut: OleVariant;begin WebBrowser1.ControlInterface.ExecWB(OLECMDID_PRINTPREVIEW, OLECMDEXECOPT_DONTPROMPTUSER, vIn, vOut);end;

Imprimirvar vIn, vOut: OleVariant;begin WebBrowser1.ControlInterface.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, vIn, vOut);end;

Veja na Figura 4 a opção de visualização sendo usada.

Figura 4. Visualizando a impressão da página

Page 26: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201526

Listagem 3: Abrindo link usando dados da aplicaçãoRepassando dados da aplicação Win32

Que tal, utilizar o navegador para interagir com pesquisas Web usando dados da sua aplicação. Como assim? Imagine a seguinte situação. Seu sistema possui no cadastro de clientes o CNPJ do fornecedor ou CPF do cliente.

Para uma determinada pesquisa na internet, o link utiliza o CPF ou CNPJ para localizar determinados dados (falando didaticamente, por que correta-mente, não seria correto passar uma query string com o CPF ou CNPJ).

Outro exemplo, você tem o cadastro de artigos publicados em um site e podemos acessar o artigo, apenas alterando o código do mesmo, através da aplicação Delphi. Então, basta chamar o link correto, alterando o valor que temos na aplicação. Para isso, vamos criar um método no formulário, com o seguinte código:

procedure Navegar(link: string);begin WebBrowser1.Navigate(link); edtEndereco.Text := link;end;

O código é simples, onde passamos como parâmetro a URL para o We-bBrowser. Crie outro formulário, configure-o para ser o primeiro do projeto, adicione um botão e digite o código da Listagem 3.

var id: integer;begin id := 275; Form6.Navegar(‘www.lucianopimenta.com/post.aspx?id=’ + IntToStr(id)); Form6.ShowModal;end;

Nesse caso, estamos chamando um formulário especifico que tem o We-bBrowser, que serve como o browser da aplicação. Em alguns casos, o id pode vir da própria aplicação, como uma consulta web de dados da aplicação Win32.

Conclusão

Vimos neste artigo, como criar um navegador através do Delphi. Com ele, podemos utilizá-lo para aplicações que pesquisam informações em site, interagindo e abrindo links diretamente da aplicação. Podemos incrementar esse exemplo, criando nosso próprio navegador ou histórico.

Estude o WebBrowser, conhece seus eventos, você vai poder aumentar as funcionalidades do exemplo. Não deixe de conferir também as novidades do Delphi XE8. Logo, trarei novidades aqui na TheClub.

Um grande abraço a todos e sucesso em seus projetos.

www.lucianopimenta.net

Luciano PimentaLuciano Pimenta (NOVO DOMINIO: www.lucianopimenta.com) é desenvolvedor Delphi/C#

para aplicações Web com ASP.NET, Windows com Win32 e Windows Forms com .NET. Palestrante da 4ª edição da Borland Conference (BorCon) e da 1ª Delphi Conference.

É MVP Embarcadero, grupo de profissionais que ajudam a divulgar o Delphi no mundo. Atualmente é desenvolvedor da SoftDesign fábrica de softwares em Porto Alegre-RS.

Autor de mais de 90 artigos e de mais de 600 vídeos aulas publicadas em revistas e sites especializados, além de treinamentos presenciais e multimídias. É consultor da FP2 Tecnologia (www.fp2.com.br) onde ministra cursos de programação e banco de dados.

Sobre o autor

Page 27: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 27

Page 28: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015

dicas the club

Dicas Delphi XE6 – MediaPlayer

28

Neste exemplo vamos demonstrar como utilizar o componente ‘MediaPlayer’ para criarmos um player de músicas no Android.

Aplicação

Adicione os seguintes componentes ao projeto: • MediaPlayer;• ListBox;• 4 Buttons;• Layout e Image (Personalizar).

Feito isso seu ‘Form’ deve ficar conforme imagem abaixo:

Imagem 1 – Form Principal.

Veja que em nosso ‘ListBox’ temos algumas músicas já adicionadas, neste exemplo inseri os nomes manualmente pela propriedade ‘Items’ do ‘ListBox’, porém, pode utilizar um banco de dados para gravar os nomes de todas as músicas que desejar. Logo abaixo temos os 4 ‘buttons’ que serão utilizados para avançar entre as faixas e aumentar ou diminuir o volume.

Codificação

Vamos iniciar com a codificação. Neste caso vamos adicionar 3 faixas através do Deployment mas, poderemos acessar faixas de outros locais caso necessário,

Page 29: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 29

Listagem 1 – Botão Avançar.

Listagem 2 – Botão Voltar.

portanto, adicione as 3 faixas padrões do Windows, veja imagem abaixo:

Imagem 2 – Deployment.

Veja que o ‘Remote Path’ é o mesmo que utilizamos para acessar o banco de dados, ou seja, o Path interno da aplicação.A codificação dos botões deve ficar conforme Listagem abaixo:

- Botão Avançar:

procedure ButtonClick(Sender: TObject);Var S: String;begin MediaPlayer.Stop; if ListBox1.ItemIndex < 2 Then ListBox1.ItemIndex:= ListBox1.ItemIndex + 1; S:= TPath.Combine(TPath.GetDocumentsPath, ListBox1.Items[ListBox1.ItemIndex]+’.mp3’); ShowMessage(S); MediaPlayer.FileName:= S; MediaPlayer.Play;end;

- Botão Voltar:

Procedure ButtonClick(Sender: TObject);Var S: String;begin MediaPlayer.Stop; If ListBox1.ItemIndex > 0 Then ListBox1.ItemIndex:= ListBox1.ItemIndex - 1; S:= TPath.Combine(TPath.GetDocumentsPath, ListBox1.Items[ListBox1.ItemIndex]+’.mp3’); ShowMessage(S); MediaPlayer.FileName:= S; MediaPlayer.Play;end;

Note que é feito a verificação do Index do ‘ListBox’ antes de passarmos o novo Index, isso é feito por que já sabemos que são 3 faixas que podemos executar,

Page 30: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio201530

Listagem 3 – Botão Mais.

Listagem 4 – Botão Menos.

portanto, deve ser implementado de uma forma genérica caso deseje utilizar um número indeterminado de músicas.

Por fim temos os comandos do Volume, veja abaixo:

- Botão mais:

procedure ButtonClick(Sender: TObject);begin MediaPlayer.Volume:= MediaPlayer.Volume + 5;end;

- Botão menos:

procedure ButtonClick(Sender: TObject);begin MediaPlayer.Volume:= MediaPlayer.Volume - 5;end;

Conclusão

Neste pequeno exemplo vimos como criar um simples player de músicas que pode ser implementado e melhorado de diversas formas.Espero que tenham gostado desta dica e até a próxima!

Page 31: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015 05

Page 32: The Club - megazine · 2015-06-02 · OBS: Este é o padrão de Media Queries do Bootstrap, o que muda de uma framework front-end para outra. 5- Definindo como um Grid de colunas

maio2015