32
fevereiro 2015

The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015

Page 2: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015

Page 3: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 03

18

Índice

Dicas The Club

30

Editorial

04

11

Autor: Hamden Vogel

05

Autor: Marlon Aparecido Branco Valentino

28

SQL Server - uso de Gatilhos para auditoria de dados

Autor: Thiago C. Montebugnoli

Autor: Jeferson Silva de Lima

Bootstrap – Pontapé inicial na utilização do Framework pelo Visual Studio

FastFile - Aplicativo Leitor MultiThread para Arquivos Grandes em Lotes

Delphi XE5 – Adicionando Recursos

Page 4: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201504

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,

Primeiramente desejo a todos boas festas neste mês de Fevereiro, pois afinal nosso país é o único onde se comemora esta grande festa, o Carnaval. Voltando ao nosso foco principal que são artigos sobre programação, neste mês, nosso consultor técnico Marlon Aparecido Branco Valentino escreveu mais um artigo sobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas configurações e dicas importantes para quem está começando a trabalhar com esta tecnologia. Nosso outro consultor, Jeferson Silva de Lima, nos ensinou como adicionar recursos em aplicativos móveis, como por exemplo: adicionar o recurso de atalho na aplicação ou até mesmo as denominadas Notificações. Implemen-tações como estas, tornam o aplicativo muito mais atraente e prático para o usuário. Já nosso colaborador Hamden Vogel redigiu o artigo “FastFile – Aplicativo Leitor MultiThread para Arquivos Grandes em Lotes” o qual ele explica detalhada-mente o funcionamento em tempo real para a leitura de um arquivo grande em pequenos lotes. Para isto ele divide proporcionalmente em tamanhos padrões e fornecido pela própria aplicação, apresentando uma abordagem alternativa para os desenvolvedores realizarem uma fácil implementação em seus sistemas. Para finalizar a revista eu utilizei o SQL Server junto com os denominados gatilhos para a auditoria de dados. Procurei ser bem prático e rápido para apresentar uma alternativa para quem procura este tipo de controle, independentemente da interface utilizada no momento.

Vou ficando por aqui,

Desejo a todos uma boa leitura e até o mês que vem!

Abraços

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

Lucas Vieira de OliveiraThiago 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 - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 05

Introdução

Continuando a matéria sobre o Framework do Twitter, agora partiremos para a criação de um aplicativo para web ou web site pelo Visual Studio, a Microsoft facilitou (e muito) esta parte, pois é possível criar um projeto pelo Visual Studio, que já vem com algumas páginas prontas para o desenvolvimen-to, com o layout no padrão do Bootstrap, desta forma você pode começar a desenvolver seu aplicativo para web ou web site de maneira mais rápida, pois não será necessário criar as páginas básicas como Home, Sobre, Contato, Login, Cadastro de Usuário, pois essas páginas já vem prontas, será apenas necessário alterar o layout do jeito que você preferir (obs: para fazer tais alterações é necessário ter conhecimento básico de HTML, CSS, JavaScript).

Criando um projeto no Visual Studio 2013

No andamento deste artigo utilizarei a versão do Visual Studio 2013 que está disponível apenas em inglês. Iremos começar criando um projeto, para acessar este recurso basta seguir o exemplo da Imagem 1, logo abaixo:

Imagem 1 Criando um Projeto

Após seguir os passos da imagem 01, o Visual Studio abrirá uma janela para

você selecionar qual linguagem deseja utilizar, para este projeto é necessário selecionar Visual C#(C Sharp), e depois clique em Web e ele lhe dará apenas uma opção, a “ASP.NET Web Application” (que significa Aplicação Web, em uma

Bootstrap - Pontapé inicial na utilização do Framework pelo Visual Studio

tradução livre) selecione esta opção e coloque o nome de seu projeto na parte inferior da tela, se restou alguma dúvida observe na Imagem 02:

Imagem 2 Janela para criação de um projeto.

Depois de selecionadas as informações corretas e dado o devido nome ao projeto, basta clicar em “OK” e logo em seguida o aparecerá outra tela para você selecionar o “template” (em tradução livre significa modelo), e para neste artigo utilizaremos o modelo “MVC” (a sigla significa Model-View-Controller, que é um padrão de arquitetura de software), observe na imagem 03 logo abaixo:

Imagem 3 Janela para seleção do modelo da aplicação da web.

Ao clicar em “OK” o Visual Studio levará alguns segundos para gerar o projeto, assim que ele terminar, para poder visualizar o projeto, compile-o em seu navegador de preferência (irei utilizar a versão para desenvolvedores do Mozilla Firefox), e terá este resultado exibido na imagem 4:

Page 6: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201506

Imagem 4 Compilando o projeto!

Este será o resultado que seu navegador exibirá após compilar o projeto:

Imagem 5 Tema padrão gerado pelo Visual Studio.

Como foi citado anteriormente, o Visual Studio gera as páginas básicas

necessárias para começar a desenvolver uma aplicação para web, que são essas exibidas na imagem 5: Home(Inicio), About(Sobre), Contact(Contato), Registro(Cadastro) e Log In(Entrar). Com estas páginas prontas basta come-çar a desenvolver sua aplicação web. Caso você não tenha gostado do tema padrão, para mudá-lo é muito fácil, o primeiro passo é entrar no site http://bootswatch.com/ e escolher um tema de sua preferência, no meu caso escolhi o tema “Yeti”, quando encontrar um tema de seu agrado clique em download e será aberta uma aba em seu navegador com o código fonte da biblioteca de estilos do bootstrap, basta pressionar atalho CTRL + A para selecionar tudo e CTRL + C para copiar o conteúdo, depois abra o Visual Studio com o seu projeto aberto e clique com o botão direito do mouse em cima da pasta “Content” e vá até a opção “Add” depois clique em ”New Item” (Caso o Visual Studio não esteja exibindo o “Solution Explorer“, que é o recurso que exibe as pastas do projeto, pressione a tecla CTRL + ALT + L).

Imagem 6 Criando um arquivo CSS para o novo tema.

Depois que clicou em “New Item”, o Visual Studio exibirá uma tela para

selecionar o tipo de arquivo que deseja que ele crie, para o tema é necessário selecionar a opção “Style Sheet” (em tradução livre significa Folha de Estilos), e na parte inferior da tela é necessário nomear o arquivo como “bootstrap--theme.css” e clique em “Add” para finalizar, se restou alguma dúvida observe como o procedimento é feito na imagem 7 logo abaixo:

Imagem 7 Adicionando o arquivo ao projeto. Apague a tag “body” que vem escrita por padrão no arquivo e cole o con-

teúdo que copiou do tema escolhido no site do “Bootswatch”, depois salve o arquivo (CTRL+S), quando feito isso, pode fechar o arquivo, em seguida dê um duplo clique na pasta “App Start” de seu projeto e faça o mesmo para abrir o arquivo “BundleConfig.cs”, o mesmo exibido na imagem 08 logo abaixo:

Imagem 8 Abrindo o arquivo BundleConfig.cs

Quando ele abrir vá até a linha de código que está declarando o Bootstrap, como é exibido na imagem 9 abaixo:

Imagem 9 Alterando a declaração do CSS referente ao tema.

Altere a declaração de “bootstrap.css” para “bootstrap-theme.css”, que é o arquivo que criamos anteriormente com o tema escolhido do bootswatch.

bundles.Add(new StyleBundle(“~/Content/css”).Include( “~/Content/bootstrap-theme.css”, “~/Content/site.css”));

Dependendo do tema escolhido, que no meu caso foi o “Yeti”, ao compi-lar o projeto o resultado que obtive será exibido na imagem 10 logo abaixo:

Page 7: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 07

Imagem 10 Novo tema. Ao observar a imagem 10, é possível perceber que a página ficou com um

design mais leve e agradável para olhos, isso faz com que o usuário consiga acessar a página durante mais tempo e a partir daí basta alimentá-lo com conteúdo e será fiel ao seu site, seja ela uma loja virtual ou site de notícias.

Como utilizar máscaras em campos

Agora mudando um pouco de assunto, vamos entrar em uma parte que muitos programadores para web têm dúvidas e muitas vezes acabam perdendo muito tempo para fazer coisas simples, como por exemplo implementar o uso de máscaras. Começando pela criação de “Inputs” (campos para inserção de dados) com máscaras de dados como as de Telefone e RG, que é muito simples de se fazer, pois já existe um poderoso jQuery plugin que faz toda a parte de programação por traz chamado de “Masked Input”(em uma tradução livre significa “Máscara de entrada”), a única parte que precisamos fazer é uma função em JavaScript que define a máscara que o campo terá, enfim, mãos a obra. O primeiro passo seria obter o plugin Masked input na versão 1.4, para isso vá até o Google e pesquise “Maskedinput 1.4 download” e depois clique no segundo resultado, que o direcionará a página da Digital Bush, desenvolvedora do plugin, como é exibido na imagem 11 logo abaixo:

Imagem 11 Obtendo o plugin Masked Input, parte 1.

Ao abrir o site da Digital Bush, poderá observar que há dois links para

baixar o plugin, pode ser obtido em sua forma não comprimida que é possível compreender o código se possuir um conhecimento avançado em JavaScript, caso queira o arquivo compresso basta clicar na segunda opção que é exibida na imagem 12 logo em seguida:

Imagem 12 Obtendo o plugin Masked Input, parte 2.

Quando clicar em um dos links o site lhe direcionará ao código fonte do Masked Input, basta fazer o mesmo procedimento da troca do tema do Bootstrap, de um “Ctrl + A” e depois “Ctrl + C” e vá até o Visual Studio e com a seta do mouse sobre a pasta “Scripts” do projeto, clique com o botão direito, vá em Add e depois New Item, ao abrir a tela para selecionar o tipo do arquivo, selecione a segunda opçãpo “JavaScript File”, na parte de baixo coloque o nome do arquivo como “maskedinput-1.4” e clique em Add, como mostra a imagem 13:

Imagem 13 Adicionando o plugin ao projeto.

Quando o novo arquivo abrir, cole(Ctrl + V) o código fonte do plugin em

seguida salve-o(Ctrl + S) e feche-o. Depois de adicionado o plugin ao projeto, precisamos declará-lo no arquivo “BundlesConfig.cs”, como foi feito no tema, e neste caso estaremos declarando um pacote de “Scripts” e não de estilos, digite as seguintes linhas de código logo abaixo de onde foi declarado o tema anteriormente:

bundles.Add(new ScriptBundle(“~/bundles/maskedinputjs”).Include(“~/Scripts/maskedinput-1.4.js”));

Quando terminar de adicionar as linhas de código, salve e feche o arquivo “BundlesConfig.cs”, o próximo passo é atualizar a versão do jQuery que é gerada pelo Visual Studio, para a versão disponível no site do http://www.jquery.com, clique no menu “Download” quando ele abrir a página clique nos links para baixar a versão 1.11.2, nas versões comprimidas e não comprimidas, como é exibido na imagem 14 logo abaixo:

Imagem 14 Obtendo a versão 1.11.2 do jQuery.

Page 8: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201508

Após baixar os arquivos do jQuery, coloque-os na pasta Scripts do projeto, depois de feito isso, exclua os arquivo com os respectivos nomes: jquery--1.10.2.intellisense; jquery-1.10.2; jquery-1.10.2.min.

Depois que os arquivos antigos foram excluídos é necessário ir abrir o

Visual Studio e adiciona-los ao projeto, para fazer isso é necessário estar com a seta do mouse sobre a pasta Scripts, clicar com o botão direito do mouse, ir até a opção do “Add” e depois clicar na opção “Existing Item”(em tradução livre significa Item Existente), se houver dúvida observe a imagem 15:

Imagem 15 Adicionando os novos arquivos do jQuery ao projeto.

Quando o Visual Studio abrir o “explorer” procure os arquivos com os respectivos nomes jquery-1.11.2 e jquery-1.11.2.min, pressione a tecla “Ctrl” e selecione os dois e clique em Add, observe como é feito na imagem 16.

Imagem 16 Selecionando os arquivos do jQuery.

Quando terminar de adicioná-los ao projeto, podemos partir para a decla-

ração dos campos que iremos definir máscaras, para isso, se estiver no Visual Studio, vá até a pasta “Models”(que em tradução livre significa Modelos) e abra o arquivo “AccountViewModel” e vá até a declaração da classe chamada “RegisterViewModel”, como mostra a imagem 17 logo abaixo:

Veja a Imagem 17. Observe o código em negrito abaixo como ficará a declaração dos campos:

[DataType(DataType.Password)] [Display(Name = “Confirm password”)] [Compare(“Password”, ErrorMessage = “The password and confirmation password do not match.”)] public string ConfirmPassword { get; set; } [Display(Name = “RG”)] public string RG { get; set; } [Display(Name = “Telefone”)] public string Telefone { get; set; } }

Quando finalizar a declaração, salve e feche o arquivo e vá para o explo-rador de soluções e abra a pasta “Views”, depois “Account” e abra o arquivo “Register.cshtml”, como é mostrado na imagem 18:

Imagem 18 Acessando o arquivo de cadastros.

Imagem 17 Declarando os campos que iremos utilizar.

Page 9: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 09

Com o arquivo aberto, vai estar igual à imagem 19, vá para a parte de baixo do código como está na imagem abaixo, agora iremos criar dois “inputs” para utilizarmos as máscaras, e as linhas de código tem que ser escritas entre as “div” tags que declaram o campo de Confirmação de senha e o botão para registrar, bem no lugar onde está a linha vermelha na imagem 19, caso não saiba como criar um os campos copie o código que disponibilizarei abaixo da imagem 19.

Imagem 19 Localizando o lugar correto para criar os campos.

O código dos respectivos campos é o seguinte, observe que as variáveis

são iguais as que foram declaradas no arquivo “AccountViewModel”:

<div class=”form-group”> @Html.LabelFor(m => m.RG, new { @class = “col-md-2 control-label “}) <div class=”col-md-10”> @Html.TextBoxFor(m => m.RG, “RG”, new { @class = “form-control” }) </div> </div> <div class=”form-group”> @Html.LabelFor(m => m.Telefone, new { @class = “col-md-2 control-label “}) <div class=”col-md-10”> @Html.TextBoxFor(m => m.Telefone, “Telefone”, new { @class = “form-control” }) </div> </div>

Depois que criarmos os campos, temos que escrever o script com a

função, mas antes é necessário declarar o plugin masked input que adicio-namos ao projeto e criamos um pacote para ele anteriormente neste artigo, para adicioná-lo é simples, observe que no fim do código tem uma seção de “Scripts”, e existe dentro dela uma declaração de um validador de jQuery, essa linha não é necessária e pode ser apagada, o código com a declaração

do pacote o plugin é o seguinte:

@section Scripts { @Scripts.Render(“~/bundles/maskedinputjs”)}

Assim que declarar o plugin, podemos escrever a função, para que ele

funcione corretamente é necessário que o jQuery esteja declarado na página mestre, o nome desta página é “_Layout” e ela fica dentro do diretório “Sha-red” na pasta ”Views”, dê um duplo clique nela para abri-la, caso não tenha encontrado o arquivo, observe a imagem 20 logo abaixo:

Imagem 20 Abrindo a página mestre.

Quando aberto, observe dentro da tag <head> se o pacote do jQuery está sendo declarado, como na imagem 21:

Imagem 21 Verificando o jQuery na página mestre.

Agora que verificamos o jQuery podemos fechar a página mestre e voltar

para a página de registros e começar a escrever a função da máscara, ela tem que ser inserida logo após os códigos do formulário de registros, observe o código abaixo:

<div class=”form-group”> <div class=”col-md-offset-2 col-md-10”> <input

Page 10: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201510

type=”submit” class=”btn btn-default” value=”Register” /> </div> </div> <script>

$(document).ready(function () { $(“#RG”).mask(“99.999.999-9”); $(“#Telefone”).mask(“(99)99999-9999”); }); </script> @section Scripts { @Scripts.Render(“~/bundles/maskedinputjs”)}

Observe que a função JavaScript utiliza os ID’s que declaramos nos cam-

pos, podendo assim compilar o projeto e teremos um resultado idêntico ao da imagem 22

Imagem 22 Resultado da máscara de RG e Telefone utilizando o plugin Masked Input.

Conclusão Neste artigo é possível perceber o quanto o Bootstrap juntamente com o

Visual Studio pode dar aquele pontapé inicial que estava faltando para você começar um novo projeto, com os recursos oferecidos pelo Framework é difícil negar que o nível de utilidade é realmente alto, pois ele facilita e agiliza muito o desenvolvimento. Caso já utilize o Bootstrap e desconhecia a possibilidade de obter um tema online sem ter que alterar todo o layout da sua página, a partir deste artigo procurei apresentar vários temas disponibilizados online gratuitamente para dar aquele up que faltava em seu projeto.

Page 11: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 11

Depois de tanto pesquisar sobre essa questão de como abrir um arquivo grande em Delphi para seu processamento, decidi escrever sobre este tema, um tanto delicado por ser difícil chegar a uma conclusão satisfatória e que agradassem a gregos e troianos – pois um arquivo grande poderia gerar

facilmente uma exceção do tipo “OutOfMemory” quanto travar a aplicação de forma incessantemente demorada – alternativas como file mapping, ler cada linha em readln ou carregar tudo em loadfromfile/loadfromstream utilizando stringlist´s podem não ser uma ideia tão interessante – vão demorar para processar e algumas vezes irão ocasionar o mesmo erro de falta de memória citado acima.

A ideia que venho mostrar aqui é simples mas funciona perfeitamente. Não é ideal para arquivos pequenos (onde a comparação com um dos modos tradicionais de abrir arquivos) pois o “tiro poderá sair pela culatra” – ficará mais lento do que deveria: essa interessante e eficiente técnica somente deverá ser aplicada a arquivos grandes – preferencialmente de 100 kB para cima.

O que tem que ser feito basicamente é o seguinte:

1. Obter o arquivo grande;2. Dividir este arquivo em vários mini-arquivos;3. Cada arquivo terá uma thread para sua leitura;4. Ler cada mini-arquivo isoladamente da VCL;5. Armazenar em cada instância de um objeto TMemo o resultado da

leitura;6. Acessar cada parte de um objeto TMemo através de um objeto

TClientDataSet.

Basicamente o processo é este. Vamos embarcar nessa aventura ?

Primeiros passos com a leitura MultiThread

As primeiras coisas a serem notadas na construção do nosso aplicativo é que ele próprio é “consciente” na distribuição dos arquivos temporários e sua manipulação – sem desperdiçar nenhum byte ou ser lento neste processo – todos os cálculos da administração dos tamanhos de cada arquivo bem como

FastFile – Aplicativo Leitor MultiThread para Arquivos Grandes em Lotes

o buffer redimensionado em tempo de execução serão gerenciados pelo nosso aplicativo de forma transparente para o usuário – eficiente e com componentes progressbar para que fique ciente da execução desta tarefa.

É claro que o bom-senso é fundamental para que o programa demonstre rapidez na sua resposta – um arquivo texto com mais de 500MB poderá levar até 6 minutos de espera – o que foi utilizado foi um de 500MB levando em média 3 minutos – “não podemos fazer milagre” – mas é muito útil para o gerenciamento dos lotes gerados e o retorno é bem melhor bem como a recuperação dos erros – tente a forma tradicional levar sempre uma exceção de “sem memória” e consequentemente o encerramento do aplicativo – o arquivo não será lido e o tempo que será gasto para lidar com uma solução intermediária de leitura será superior ao tempo de resposta da nossa solução aqui apresentada.

Foram experimentadas alternativas inviáveis, um tanto exploradas pela Web, mas que não trouxeram uma solução que chegasse perto a de que foi implementada aqui. Utilizar recursos de Memory Mapping Files, FileStreams, etc, podem ser bons para arquivos não tão grandes – eles vão “travar” sua aplicação porque a memória do Windows vão derrubá-los – assim como um dominó. Não gaste mais tempo contando com objetos do tipo TStringList, TList, etc; eles não vão pensar duas vezes e vão responder que não tem a memória que precisam – e vão deixar você na mão, infelizmente. O que poderá ser feito é o que foi dito inúmeras vezes acima – funciona em poucos minutos – o usuário acompanha o progresso do trabalho enquanto que o arquivo (que não queria ser lido de jeito nenhum pelo Windows) é finalmente carregado – em lotes – um por um – e sendo “printado” para a tela de sua aplicação – vemos agora que existe uma luz no fim do túnel.

Administração do Buffer

Para que o buffer seja preenchido e lido, algumas considerações são necessárias e são citadas abaixo:

1. O programa obtém o tamanho do arquivo em bytes (por exemplo, um arquivo com 2887 KB será gerado com 2955545 bytes pela nossa função de obter tamanhos de arquivos);

Page 12: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201512

2. O programa gerará um “tamanho padrão” dos arquivos em lotes a serem gerados (baseando no mesmo exemplo, este arquivo terá o tama-nho padrão de divisão dos seus arquivos em lotes de 295600 bytes, ou seja, 288,671875 KB cada um);

3. Baseado neste “tamanho padrão” o programa gerará os lotes necessários neste tamanho para cada um, até preencher todos eles com os dados do arquivo original;

4. O programa criará um objeto TFileStream para cada lote gerado;5. Assim sendo, o programa criará uma thread para cada lote a fim

de ler o conteúdo deles (poderão ser geradas várias threads de uma vez – prioridade normal);

6. O programa calculará o tamanho do buffer de leitura da thread com base no seguinte: 1024 (KB) vezes o tamanho do arquivo;

7. Cada thread criará um objeto TFileStream encarregado da leitura de cada lote corrente em que esta thread administra;

8. O buffer é preenchido com este objeto TFileStream;9. É criado um objeto TMemo que irá receber o conteúdo deste buffer;10. Este objeto TMemo será gerenciado internamente pelo programa, a

fim de ser visualizado no momento apropriado, visto que vários deles poderão ser gerados (um por lote) – sendo que alguns métodos não serão utilizados a fim de agilizar a execução deste processo de criação (como o método clear, por exemplo);

11. Será criado um objeto TClientDataSet para o gerenciamento de todos os lotes, a fim de mostrá-los disponíveis em uma grid e serem selecio-nados e visualizados pelo usuário.

Segue abaixo o trecho do código-fonte responsável pela leitura do buffer, caracter a caracter, do tipo AnsiChar. Note que foi definido um “filtro” para esta leitura. Esta procedure se encontra na nossa thread de apoio.

procedure TFileReadThread.FileRead;var Stream: TFileStream; i: integer; Buffer: array of AnsiChar; //1024 (kB) x tamanho do arquivo ... TempStr: string; const Allowed = [‘A’ .. ‘Z’, ‘a’ .. ‘z’, ‘0’ .. ‘9’, ‘_’, #13, #10, ‘-’, ‘\’, ‘”’, ‘!’, ‘@’ ,’#’, ‘$’, ‘%’, ‘¨’, ‘*’, ‘(‘, ‘)’, ‘{‘, ‘}’, ‘[‘, ‘]’, ‘<’, ‘>’, ‘.’, ‘:’, ‘;’, ‘,’ , ‘?’, ‘!’, ‘/’, ‘+’, ‘-’, ‘´’, ‘`’, ‘=’, ‘^’, ‘~’, ‘&’, ‘ ‘];begin TempStr := ‘’;

SetLength(Buffer, self.iFileSize + 1); Stream := TFileStream.

Create(self.strFileName ,fmOpenRead); try Stream.Read(Buffer[0], self.iFileSize + 1); finally Stream.Free; end;

for i := Low(Buffer) to High(Buffer) do if (Buffer[i] in Allowed) then TempStr := TempStr + Buffer[i];

Form1.memo3.Lines.Add(‘Arquivo ‘ + Self.strFileName + ‘ lido com sucesso.’); Form1.CriaMemos(Self.Id, TempStr); // Form1.strList.AddObject(TempStr, TObject(Self.Id));end;

Figura 01 – Resultado final do processo de leitura em lotes.

Figura 02 – O processo sendo lido em lotes.

Page 13: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 13

Figura 03 – Mais um exemplo de leitura em lotes – note que este arquivo proces-

sado em lotes tem 562 MB, sendo lido em 3 minutos. Foram criados 1000 lotes para sua visualização. Cada lote poderá ser processado da forma mais conveniente, em um loop ou em um evento próprio – por exemplo, para a leitura dos lotes “linha por linha” como em um readln.

Seguem abaixo trechos do código-fonte responsável para o fornecimento

do tamanho padrão de cada lote:

function TfrmMain.NumberOfPartsToDivide(const filesize: integer): integer;var denominator: integer; { In fraction, the denominator will match the amount of exact parts where the file will be divided, while the numerator is the file size. Em fração, o denominador corresponderá a quantidade de partes exatas em que será dividido o arquivo, enquanto que o numerador será o tamanho do arquivo. }begin case length(IntToStr(Round(filesize/1000))) of //convert to bytes 1: denominator := 4; 2: denominator := 8; else denominator := Round(Math.Power(10, length(IntToStr(filesize)) - Round(length(IntToStr(filesize)) / 2))); end;

Result := Round(filesize/denominator) * 100; end;

Segue abaixo a função responsável por criar os arquivos em lote e preen-chê-los com base no tamanho padrão fornecido anteriormente:

procedure TfrmMain.FileSplit(const StrFilename: String);var StrmInput, StrmOutput : TFileStream; FileNumber : Integer; FileSize: integer; SequentialFile: string;begin if (StrFilename = ‘’) then Exit; if not (FileExists(StrFilename)) then Exit; tempFolder := Biblioteca.ExtractName(SysUtils.ExtractFileName(StrFilename));

if SysUtils.DirectoryExists(LocalDirectory + tempFolder) then SysUtils.RemoveDir(LocalDirectory + tempFolder); SysUtils.CreateDir(LocalDirectory + tempFolder);

//FileSize := Round(Biblioteca.GetFileSize(StrFilename) / NumberOfParts); FileSize := NumberOfPartsToDivide(Biblioteca.GetFileSize(StrFilename));

if not clOriginalFilePath.Locate(‘FILENAME’, StrFilename, []) then begin clOriginalFilePath.Append; clOriginalFilePath.FieldByName(‘FILENAME’).AsString := StrFilename; clOriginalFilePath.FieldByName(‘SIZEFILE’).AsInteger := FileSize; clOriginalFilePath.Post; end else begin clOriginalFilePath.Edit;

Page 14: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201514

//clOriginalFilePath.FieldByName(‘FILENAME’).AsString := ExtractFileName(ffile); clOriginalFilePath.FieldByName(‘SIZEFILE’).AsInteger := FileSize; clOriginalFilePath.Post; end;

lblFileSize.Caption := IntToStr(FileSize) + ‘ bytes’; FileNumber := 1; iTotalFiles := 0; ProgressBar.Position := 0; memoLog.Clear;

StrmInput := TFileStream.Create(StrFilename,fmOpenRead or fmShareDenyNone); try while StrmInput.Position < StrmInput.Size do begin SequentialFile := ChangeFileExt((ExtractFilePath(StrFilename) + IncludeTrailingPathDelimiter(tempFolder) + ExtractFileName(StrFilename)),’.’+Format(‘%.03d’,[FileNumber]));

StrmOutput := TFileStream.Create(SequentialFile ,fmCreate); try if StrmInput.Size - StrmInput.Position < FileSize then FileSize := StrmInput.Size - StrmInput.Position;

StrmOutput.CopyFrom(StrmInput,FileSize); memoLog.Lines.Add(‘File: ‘ + ExtractFileName(SequentialFile) + ‘ created successfully.’); Application.ProcessMessages; finally StrmOutput.Free; end; Inc(FileNumber); Inc(iTotalFiles); ProgressBar.Position := ProgressBar.Position + 1;

end; finally StrmInput.Free; end; ProgressBar.Max := iTotalFiles;end;

Aplicativo para processar em lotes passo-a-passo

Inicialmente, foi concebida a ideia de realizar o processamento passo-a--passo, isto é, em vez de o nosso aplicativo anterior (FastFile) executar tudo automaticamente, o usuário poderá acompanhar mais de perto de como a coisa toda funciona.

Gerando um passo por vez poderá ter a noção de como as funções de criação de lotes e a de leitura sincronizada (através de threads com a VCL) interagem entre si e resultam harmoniosamente no elo de criação e leitura das partes de um todo, “printando” o resultado em memo´s instanciados dinamicamente (sim, não há problema desde que se tenha memória – em um teste realizado aqui, foram criados 1000 memo´s sem problema algum).

Seguem abaixo duas funções: uma para obter o conteúdo de um TMemo e a outra para checkar o seu status (ativo/destruído/não existe):

function TForm1.GetMemo(const Id: integer): String;begin if MemoExists(Id) then Result := TMemo(Self.FindComponent(‘memo_’+ IntToStr(Id))).Text else Result := ‘’;end;

procedure TForm1.CheckStatusMemo(const Id: integer);var garbage: TComponent;begin if MemoExists(Id) then begin garbage := Self.FindComponent(‘memo_’+ IntToStr(Id)); FreeAndNil(garbage); end;end;

Page 15: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 15

Figura 04 – aplicativo passo-a-passo – função para a divisão dos arquivos

Figura 05 – aplicativo passo-a-passo – função para a união dos arquivos – note que esta função não é necessária para o processo de leitura em lotes discutido no nosso tema, mas útil para ilustrar o funcionamento inverso do nosso tema também.

Figura 06 – aplicativo passo-a-passo – Memo contendo o registro das operações, como um Log.

Figura 07 – aplicativo passo-a-passo – Leitura do arquivo em Lotes.

Figura 08 – aplicativo passo-a-passo – Leitura do arquivo em Lotes, com método de pesquisa.

Essa pesquisa por lote é interessante: o usuário digita o número do lote desejado e obtém o conteúdo deste lote. Assim, pode-se pesquisar por vez, a fim de exibir (neste caso, apenas um por vez) os dados contidos nele. Todos os caracteres são os preenchidos pelo buffer das threads através de um “filtro” (já citado acima).

Segue abaixo duas linhas do fonte responsáveis por esta função:

Memo4.Clear; Memo4.Lines.Add(GetMemo(StrToIntDef(Edit1.Text, 1)));

Por fim, segue o código-fonte da thread chamada TFileReadThread:

Page 16: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201516

{ TFileReadThread }

constructor TFileReadThread.Create(CreateSuspended: Boolean; const myTempFileName: string; const myID, mySizeBuffer: integer);begin inherited Create(CreateSuspended); self.strFileName := myTempFileName; Self.Id := myID; Self.iFileSize := mySizeBuffer;

Priority := tpNormal;end;

destructor TFileReadThread.Destroy;begin inherited;end;

procedure TFileReadThread.Execute;begin inherited;

FreeOnTerminate := True; // if WaitForSingleObject(MutexHandle, INFINITE) = WAIT_OBJECT_0 then // begin Synchronize(FileRead); // end;

// ReleaseMutex(MutexHandle);

end;

procedure TFileReadThread.FileRead;var Stream: TFileStream; i: integer; // Buffer: array[0..295600] of AnsiChar; //1024 (kB) x size of the file ... Buffer: array of AnsiChar; TempStr: string; const Allowed = [‘A’ .. ‘Z’, ‘a’ .. ‘z’, ‘0’ .. ‘9’, ‘_’, #13, #10, ‘-’, ‘\’, ‘”’, ‘!’, ‘@’

,’#’, ‘$’, ‘%’, ‘¨’, ‘*’, ‘(‘, ‘)’, ‘{‘, ‘}’, ‘[‘, ‘]’, ‘<’, ‘>’, ‘.’, ‘:’, ‘;’, ‘,’ , ‘?’, ‘!’, ‘/’, ‘+’, ‘-’, ‘´’, ‘`’, ‘=’, ‘^’, ‘~’, ‘&’, ‘ ‘];begin TempStr := ‘’;

SetLength(Buffer, self.iFileSize + 1); Stream := TFileStream.Create(self.strFileName ,fmOpenRead);

try Stream.Read(Buffer[0], self.iFileSize + 1);

finally Stream.Free; end;

for i := Low(Buffer) to High(Buffer) do if (Buffer[i] in Allowed) then TempStr := TempStr + Buffer[i];

frmMain.memoLog.Lines.Add(‘File ‘ + ExtractFileName(Self.strFileName) + ‘ read successfully.’); frmMain.CreateMemos(Self.Id, TempStr); frmMain.ProgressBar.Position := frmMain.ProgressBar.Position + 1; // Form1.strList.AddObject(TempStr, TObject(Self.Id));

end;

Conclusão

Foi explicado neste artigo o funcionamento em tempo real a leitura de um arquivo grande em lotes, para isso dividindo cada um proporcionalmente em um tamanho padrão fornecido pela própria aplicação, e assim preen-chendo dados nestes lotes e trazendo estes dados temporariamente para os componentes da VCL (através da instancialização de vários objetos TMemo´s,

Page 17: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 17

TClientDataSet´s e sincronizações com um TMemo para log e um TProgressBar para acompanhamento do processo).

Cada lote poderá ser criado e personalizado de forma livre para o im-plementador – a nomenclatura padrão é o nome do arquivo original mais o sequencial formatado em três casas decimais – exemplo ArquivoTal.001, ArquivoTal.002, etc;

Foram realizados testes apenas com arquivos binários/texto, processados em todas as etapas (divisão/união/leitura temporários) sempre com fluxo de dados do tipo TStream, aproveitando assim as funcionalidades de leitura por posição através do seu método CopyFrom.

O que quis trazer aqui é uma abordagem alternativa e eficiente para a lei-tura de arquivos pesados, como arquivos de carga, por exemplo, onde sempre sobrecarregam a entrada dos aplicativos devido ao seu tamanho – por mais que existam soluções para contornar essa leitura grande, muitas oneram o processador e vive de erros de falta de memória e com tempo demasiado para o processamento linha a linha – imagina uma linha para cada insert em um banco de dados de um arquivo de carga – sendo muito grande o Delphi nem vai iniciar a função – vai abortar com erros já citados de Exception “OutOfMemory”.

Portanto, com este aplicativo os arquivos grandes SEMPRE serão lidos, desde que o Windows apresente memória para tal. Não é recomendável me-mória com até 2 GB de RAM; sempre mais do que isso a partir de 3. Foi testado com 3 GB com resultados satisfatórios. A leitura sempre funcionará e nunca deixará o usuário “na mão”. Uma última e óbvia observação é a permissão

[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

de espaço em disco e capacidade do mesmo, para permitir a leitura/escrita e a capacidade de armazenamento dos lotes dos arquivos, respectivamente.

Essa é uma maneira multithread para agilizar a leitura dos lotes de um arquivo em particular, dividindo uniformemente em tamanho seus respecti-vos lotes e consumindo seus dados para dentro do programa em si, trazendo uma forma eficiente de ler os dados de forma sequência, ordenada e prática. Bons estudos e bons projetos com este artigo ! Seguem os fontes dos projetos baseados neste nosso tema em anexo. Até o próximo artigo !

Page 18: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201518

Listagem 01: Código para criação de Triggers.

Neste mês resolvi escrever um pouco sobre o assunto Audito-ria de dados utilizando os denominados Gatinhos (Triggers) no Banco de Dados SQL Server. Explicarei e criarei toda a regra necessária para esta tarefa. Farei o uso da versão 2008 do SQL Server Express Edition, servindo também

de base para as outras versões. Utilizaremos também como ferramenta para gerenciamento de dados o “Microsoft SQL Management Studio”, versão 10. Antes de começarmos a implementar a ideia de auditoria de dados em tabelas do SQL Server, o tópico abaixo “Pré-requisitos” irá abranger um assunto con-siderado primordial para a leitura deste artigo, ressaltando que este tópico já se encontra publicado em um de nossos artigos.

Pré-Requisitos

Este tópico foi baseado no artigo “Trabalhando com o SQL Server 2008 Express Edition – Parte 2” do mês de Abril de 2011, para maiores detalhes favor realizar a leitura do artigo na íntegra.

O que seria um Gatilho?

O gatilho é um objeto que é automaticamente executado assim que efetuado um INSERT, DELETE ou UPDATE na tabela. Podemos criá-los de duas maneiras, BEFORE (antes) e AFTER (após). Os gatilhos BEFORE disparam antes das modificações da instrução serem aplicadas, e antes de qualquer restrição ser aplicada. Já os AFTER disparam após todas as restrições terem sido satis-feitas, e após todas as alterações terem sido aplicadas à tabela de destino.

Como implementar?

Uma das formas mais rápidas e práticas seria com o Microsoft SQL Ma-nagement Studio. Com o mesmo aberto deveremos clicar na tabela desejada e escolher a Opção “Gatilho” e em seguida “Novo Gatilho”, Ver Imagem 01.

SQL Server e o uso de Gatilhos para auditoria de dados

Figura 01: Criar um Gatilho.

Teremos abaixo o código base para criação das TRIGGERS e em seguida a explicação detalhada, Ver Listagem 01.

CREATE TRIGGER <Schema_Name, sysname, Schema_Name>.<Trigger_Name, sysname, Trigger_Name> ON <Schema_Name, sysname, Schema_Name>.<Table_Name, sysname, Table_Name> AFTER <Data_Modification_Statements, , INSERT,DELETE,UPDATE>AS BEGIN SET NOCOUNT ON;END

Page 19: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 19

Detalhando o código da Listagem 01.

CREATE TRIGGER <Nome do Gatilho a ser utilizado>ON <Nome da Tabela afetada>AFTER <Momento(Antes ou Depois) / da Operação (Inserir,Deletar ou Atualizar)>AS BEGIN <Código a ser programado>END

Como funcionará a auditoria dos dados em nossa tabela do SQL Server?

O exemplo se baseará na auditoria em uma tabela, por exemplo a de Clientes. Teremos todos os detalhes dos comandos de Inserção, Atualização e Exclusão dos registros. Nossos dados serão armazenados em mais outras duas tabelas, sendo a de LOGS e LOGS_DATA, um clássico relacionamento Mestre--Detalhe. Teremos os campos detalhados abaixo:

Tabela LOGS

ID_LOGS: campo auto-incremento (chave primária) para se relacionar com a tabela LOGS_DATA;

CODIGO: código do Cliente; DATA_HORA: Data/Hora da operação;OPERACAO: tipo de operação [(I)nclusão,(A)lteração, (E)xclusão];USUARIOID: código do usuário.

Tabela LOGS_DATA

ID_LOGS_DATA: campo auto-incremento (chave primária);ID_LOGS: chave estrangeira, campo resposnsável pelo relacionamento

com a tabela LOGS;NOME CAMPO: Nome do Campo da tabela de Clientes;TIPO_CAMPO: Tipo de campo utilizado;VALOR: Conteúdo do campo.

Para exemplificar melhor, veremos maiores detalhes do esquema na Imagem 02.

Os Comandos de Insert, Update e Deleteserão executados com base na tabela de CLIENTES.

O resultado da execução dos Gatilhos serão armaze-nados nas tabelas LOGS e LOGS_DATA.

Figura 02: Esquema de funcionamento.

Page 20: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201520

Listagem 02: Script da tabela Clientes.

Listagem 03: Script da tabela Logs.

Listagem 04: Script da tabela Logs_Data.

Definindo a Tabela Principal (CLIENTES)

O script de criação da tabela de clientes poderemos conferir na Listagem 02.

CREATE TABLE [dbo].[CLIENTES]( [CODIGO] [int] IDENTITY(1,1) NOT NULL, [NOME] [varchar](50) NULL, [TIPO] [int] NULL, [CIDADE] [varchar](50) NULL, [UF] [varchar](2) NULL, [DOCUMENTO] [varchar](20) NULL, [DATANASCIMENTO] [date] NULL, [SEXO] [varchar](1) NULL, [TELEFONE] [varchar](20) NULL, [OBSERVACAO] [varchar](80) NULL, [USUARIOID] [int] NULL, CONSTRAINT [PK_CLIENTES] PRIMARY KEY CLUSTERED ( [CODIGO] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]

Definindo as Tabelas de Logs (LOGS e LOGS_DATA)

Para a tabela de Logs teremos o script de criação conforme Listagem 03.

CREATE TABLE [dbo].[LOGS]( [ID_LOGS] [int] IDENTITY(1,1) NOT NULL, [CODIGO] [int] NULL, [DATA_HORA] [datetime] NULL, [OPERACAO] [varchar](1) NULL, [USUARIOID] [int] NULL, CONSTRAINT [PK_CADASTRO_UNICO_LOGS] PRIMARY KEY CLUSTERED

( [ID_LOGS] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]

Já para a tabela Detalhe Logs_Data, o script responsável pela criação da tabela poderá ser consultado na Listagem 04.

CREATE TABLE [dbo].[LOGS_DATA]( [ID_LOGS_DATA] [int] IDENTITY(1,1) NOT NULL, [ID_LOGS] [int] NULL, [NOME_CAMPO] [varchar](50) NULL, [TIPO_CAMPO] [varchar](50) NULL, [VALOR] [varchar](80) NULL, CONSTRAINT [PK_LOGS_DATA] PRIMARY KEY CLUSTERED ( [ID_LOGS_DATA] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]

Criando o Gatilho de “Insert”

O gatilho “INSERT_LOGS” fará sempre o trabalho após a inserção de algum registro, Ver código comentado na listagem 05.

CREATE TRIGGER [dbo].[INSERT_LOGS] ON [dbo].[CLIENTES]

Page 21: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 21

Listagem 05: Gatilho Insert_Logs.

AFTER INSERTAS BEGIN DECLARE @CODIGO INT DECLARE @NOME VARCHAR(50) DECLARE @TIPO INT DECLARE @CIDADE VARCHAR(50) DECLARE @UF VARCHAR(2) DECLARE @DOCUMENTO VARCHAR(20) DECLARE @DATANASCIMENTO DATE DECLARE @SEXO VARCHAR(1) DECLARE @TELEFONE varchar(20) DECLARE @OBSERVACAO varchar(80) DECLARE @USUARIOID int DECLARE @ID_LOGS int

Para cada campo a ser inserido foi necessário criar uma variável.

SELECT @CODIGO = CODIGO, @NOME = NOME, @TIPO = TIPO, @CIDADE = CIDADE, @UF = UF, @DOCUMENTO = DOCUMENTO, @DATANASCIMENTO = DATANASCIMENTO, @SEXO = SEXO, @TELEFONE = TELEFONE, @OBSERVACAO = OBSERVACAO, @USUARIOID = USUARIOID FROM Inserted

O próximo passo será de alimentar todas as variáveis com os registros inseridos na tabela de Clientes. Podemos realizar esta tarefa com o comando “Inserted”, o mesmo responsável pelo estado de inserção dos dados.

INSERT INTO LOGS (CODIGO, DATA_HORA, OPERACAO, USUARIOID) VALUES (@CODIGO,GETDATE(),’I’, @USUARIOID)

Para inserir na tabela “Mestre” denominada Logs faremos um simples

INSERT, passando por parâmetro o código oriundo da variável declarada acima, a data atual utilizando o comando “GetDate()”, a operação “I” que significa modo de inserção e o usuário ativo no momento.

SELECT @ID_LOGS = ID_LOGS FROM LOGS INSERTED

Já para inserirmos os dados na tabela “Detalhe” Logs_data o primeiro passo deveremos realizar um select usando o ID_LOGS para localizarmos o registro corrente, com o auxílio do comando “Inserted”.

IF (@CODIGO IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’CODIGO’,’INT’,@CODIGO) END

IF (@NOME IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’NOME’,’VARCHAR’,@NOME) END IF (@TIPO IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’TIPO’,’INT’,@TIPO) END IF (@CIDADE IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’CIDADE’,’VARCHAR’,@CIDADE) END

Page 22: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201522

IF (@UF IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’UF’,’VARCHAR’,@UF) END IF (@DOCUMENTO IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’DOCUMENTO’,’VARCHAR’,@DOCUMENTO) END

IF (@DATANASCIMENTO IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’DATANASCIMENTO’,’DATE’,@DATANASCIMENTO) END IF (@SEXO IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’SEXO’,’VARCHAR’,@SEXO) END IF (@TELEFONE IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’TELEFONE’,’VARCHAR’,@TELEFONE) END IF (@OBSERVACAO IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO,

VALOR) VALUES (@ID_LOGS,’OBSERVACAO’,’VARCHAR’,@OBSERVACAO) END IF (@USUARIOID IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’USUARIOID’,’INT’,@USUARIOID) ENDEND

Nos próximos passos faremos uma verificação campo a campo se os mesmos não se encontram nulos e logo em seguida executaremos um Insert na tabela Logs_data, respeitando a ordem dos campos Id_Logs, Nome, Tipo e o Valor do campo.

Criando o Gatilho de “Update”

O gatilho “UPDATE_LOGS” fará sempre o trabalho após a atualização de algum registro, Ver código comentado na listagem 06.

CREATE TRIGGER [dbo].[UPDATE_LOGS] ON [dbo].[CLIENTES] AFTER UPDATEAS BEGIN DECLARE @CODIGO INT DECLARE @NOME VARCHAR(50) DECLARE @TIPO INT DECLARE @CIDADE VARCHAR(50) DECLARE @UF VARCHAR(2) DECLARE @DOCUMENTO VARCHAR(20) DECLARE @DATANASCIMENTO DATE DECLARE @SEXO VARCHAR(1) DECLARE @TELEFONE varchar(20) DECLARE @OBSERVACAO varchar(80) DECLARE @USUARIOID int DECLARE @ID_LOGS int

Para cada campo a ser atualizado foi necessário criar uma variável.

Page 23: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 23

SELECT @CODIGO = ISNULL(CODIGO,0), @NOME = ISNULL(NOME,’ ‘), @TIPO = ISNULL(TIPO,’ ‘), @CIDADE = ISNULL(CIDADE,’ ‘), @UF = ISNULL(UF,’ ‘), @DOCUMENTO = ISNULL(DOCUMENTO,’ ‘), @DATANASCIMENTO = ISNULL(DATANASCIMENTO,’ ‘), @SEXO = ISNULL(SEXO,’ ‘), @TELEFONE = ISNULL(TELEFONE, ‘ ‘), @OBSERVACAO = ISNULL(OBSERVACAO,’ ‘), @USUARIOID = ISNULL(USUARIOID,’ ‘) FROM INSERTED

O próximo passo será de alimentar todas as variáveis com os registros atualizados na tabela de Clientes. Podemos realizar esta tarefa com o comando “Inserted” e analisando se o campo está nulo com a função “ISNULL”.

DECLARE @NOME_OLD VARCHAR(40) DECLARE @TIPO_OLD INT DECLARE @CIDADE_OLD VARCHAR(50) DECLARE @UF_OLD VARCHAR(2) DECLARE @DOCUMENTO_OLD VARCHAR(20) DECLARE @DATANASCIMENTO_OLD DATE DECLARE @SEXO_OLD VARCHAR(1) DECLARE @TELEFONE_OLD VARCHAR(20) DECLARE @OBSERVACAO_OLD VARCHAR(80) DECLARE @USUARIOID_OLD int

Nas variáveis acima deveremos armazenar todos os valores antigos dos campos que foram atualizados.

SELECT @NOME_OLD = ISNULL(NOME,’ ‘), @TIPO_OLD = ISNULL(TIPO,’ ‘), @CIDADE_OLD = ISNULL(CIDADE,’ ‘), @UF_OLD = ISNULL(UF,’ ‘), @DOCUMENTO_OLD = ISNULL(DOCUMENTO,’ ‘), @DATANASCIMENTO_OLD = ISNULL(DATANASCIMENTO,’ ‘), @SEXO_OLD = ISNULL(SEXO,’ ‘), @TELEFONE_OLD = ISNULL(TELEFONE, ‘ ‘), @OBSERVACAO_OLD = ISNULL(OBSERVACAO,’ ‘), @USUARIOID_OLD = ISNULL(USUARIOID,’ ‘) FROM DELETED

Poderemos recuperar estes campos utilizando o comando “Deleted”.

INSERT INTO LOGS (CODIGO, DATA_HORA, OPERACAO, USUARIOID) VALUES(@CODIGO,GETDATE(),’A’, @USUARIOID)

Seguindo a mesma lógica descrita anteriormente, a inserção na tabela “Mestre” denominada Logs faremos um simples INSERT, passando por parâ-metro o código oriundo da variável declarada acima, a data atual utilizando o comando “GetDate()”, a operação “A” que significa modo de atualização e o usuário ativo no momento.

SELECT @ID_LOGS = ID_LOGS FROM LOGS INSERTED

Para inserirmos os dados na tabela “Detalhe” Logs_data o primeiro passo deveremos realizar um select usando o ID_LOGS para localizarmos o registro corrente, com o auxílio do comando “Inserted”.

Page 24: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201524

Listagem 06: Gatilho Update_Logs.

IF (UPDATE(NOME) AND (@NOME <> @NOME_OLD)) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’NOME’,’VARCHAR’,@NOME) END IF (UPDATE(TIPO) AND (@TIPO <> @TIPO_OLD)) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’TIPO’,’INT’,@TIPO) END IF (UPDATE(CIDADE) AND (@CIDADE <> @CIDADE_OLD)) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’CIDADE’,’VARCHAR’,@CIDADE) END IF (UPDATE(UF) AND (@UF <> @UF_OLD)) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’UF’,’VARCHAR’,@UF) END IF (UPDATE(DOCUMENTO) AND (@DOCUMENTO <> @DOCUMENTO_OLD)) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’DOCUMENTO’,’VARCHAR’,@DOCUMENTO) END IF (UPDATE(DATANASCIMENTO)

AND (@DATANASCIMENTO <> @DATANASCIMENTO_OLD)) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’DATANASCIMENTO’,’DATE’,@DATANASCIMENTO) END IF (UPDATE(SEXO) AND (@SEXO <> @SEXO_OLD)) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’SEXO’,’VARCHAR’,@SEXO) END IF (UPDATE(TELEFONE) AND (@TELEFONE <> @TELEFONE_OLD)) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’TELEFONE’,’VARCHAR’,@TELEFONE) END IF (UPDATE(OBSERVACAO) AND (@OBSERVACAO <> @OBSERVACAO_OLD)) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’OBSERVACAO’,’VARCHAR’,@OBSERVACAO) END IF (UPDATE(USUARIOID) AND (@USUARIOID <> @USUARIOID_OLD)) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’USUARIOID’,’INT’,@USUARIOID) ENDEND

Page 25: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 25

Listagem 07: Gatilho Delete_Logs.

Por final faremos uma verificação campo a campo se os mesmos estão em modo de Update e comparamos o valor antigo com o valor novo, caso encontre alguma divergência executaremos um Insert na tabela Logs_data, respeitando a ordem dos campos ID_LOGS, Nome, Tipo e o Valor do campo.

Criando o Gatilho de “Delete”

O gatilho “DELETE_LOGS” fará sempre o trabalho após a Exclusão de algum registro, Ver código comentado na listagem 07.

CREATE TRIGGER [dbo].[DELETE_LOGS] ON [dbo].[CLIENTES] AFTER DELETEAS BEGIN DECLARE @ID_LOGS INT DECLARE @CODIGO_OLD INT DECLARE @NOME_OLD VARCHAR(40) DECLARE @TIPO_OLD INT DECLARE @CIDADE_OLD VARCHAR(50) DECLARE @UF_OLD VARCHAR(2) DECLARE @DOCUMENTO_OLD VARCHAR(20) DECLARE @DATANASCIMENTO_OLD DATE DECLARE @SEXO_OLD VARCHAR(1) DECLARE @TELEFONE_OLD VARCHAR(20) DECLARE @OBSERVACAO_OLD VARCHAR(80) DECLARE @USUARIOID_OLD int

Para cada campo a ser atualizado foi necessário criar uma variável.

SELECT @CODIGO_OLD = CODIGO, @NOME_OLD = NOME, @TIPO_OLD = TIPO, @CIDADE_OLD = CIDADE, @UF_OLD = UF, @DOCUMENTO_OLD = DOCUMENTO, @DATANASCIMENTO_OLD =

DATANASCIMENTO, @SEXO_OLD = SEXO, @TELEFONE_OLD = TELEFONE, @OBSERVACAO_OLD = OBSERVACAO, @USUARIOID_OLD = USUARIOID FROM DELETED

O próximo passo será de alimentar todas as variáveis com os registros excluídos na tabela de Clientes. Podemos realizar esta tarefa com o comando “Deleted”.

INSERT INTO LOGS (CODIGO, DATA_HORA, OPERACAO, USUARIOID) VALUES (@CODIGO_OLD,GETDATE(),’E’, @USUARIOID_OLD)

Novamente faremos a inserção na tabela “Mestre” com o comando INSERT, passando por parâmetro o código oriundo da variável declarada acima, a data atual utilizando o comando “GetDate()”, a operação “E” que significa modo de exclusão e o usuário ativo no momento.

SELECT @ID_LOGS = ID_LOGS FROM LOGS INSERTED

Para a tabela “Detalhe” Logs_data deveremos realizar um select usando o ID_LOGS para localizarmos o registro corrente, com o auxílio do comando “Inserted”.

IF (@CODIGO_OLD IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’CODIGO’,’INT’,@CODIGO_OLD) END IF (@NOME_OLD IS NOT NULL)

Page 26: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201526

BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’NOME’,’VARCHAR’,@NOME_OLD) END

IF (@TIPO_OLD IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’TIPO’,’INT’,@TIPO_OLD) END

IF (@CIDADE_OLD IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’CIDADE’,’VARCHAR’,@CIDADE_OLD) END

IF (@UF_OLD IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’UF’,’VARCHAR’,@UF_OLD) END

IF (@DOCUMENTO_OLD IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’DOCUMENTO’,’VARCHAR’,@DOCUMENTO_OLD) END IF (@DATANASCIMENTO_OLD IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_

LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’DATANASCIMENTO’,’DATE’,@DATANASCIMENTO_OLD) END

IF (@SEXO_OLD IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’SEXO’,’VARCHAR’,@SEXO_OLD) END

IF (@TELEFONE_OLD IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’TELEFONE’,’VARCHAR’,@TELEFONE_OLD) END

IF (@OBSERVACAO_OLD IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’OBSERVACAO’,’VARCHAR’,@OBSERVACAO_OLD) END IF (@USUARIOID_OLD IS NOT NULL) BEGIN INSERT INTO LOGS_DATA (ID_LOGS, NOME_CAMPO, TIPO_CAMPO, VALOR) VALUES (@ID_LOGS,’USUARIOID’,’INT’,@USUARIOID_OLD) END END

Esta etapa será idêntica aos gatilhos criados anteriormente, pois realiza-mos a verificação se o campo não encontra-se nulo realizando a inserção dos

Page 27: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 27

dados corretamente.

Poderemos conferir no Banco os objetos criados, Ver Imagem 03.

Figura 03: Objetos criados com sucesso.

Testando os gatilhos

Os gatilhos são objetos executados diretamente no Banco de Dados, de acordo com a operação desejada. Para dispará-los poderíamos utilizar qualquer interface mas para nosso teste a forma mais rápida para realizar esta tarefa seria diretamente pelo SSMSE (SQL Server Management Studio Express).

Abrindo a tabela de Clientes poderemos inserir, alterar ou excluir alguns dados e após uma consulta nas tabelas Logs e Logs_Data teremos um resultado idêntico ao da Figura 04.

Conclusões

O uso de Triggers(gatilhos) em auditoria de sistemas é uma prática muito usual, pois todo o trabalho fica a cargo do servidor, livrando a interface do lado cliente para esta tarefa. Procurei neste artigo explorar um exemplo de como deveremos implementar esta técnica utilizando o SQL Server. Fiquem a vontade para modificar e adaptar estas rotinas conforme a necessidade do momento.

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

Figura 04: Resultado final.

[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

Page 28: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201528

Listagem 1 – Uses.

Listagem 2 – Atalho.Neste artigo vamos demonstrar algumas funções básicas, mas importantes para o bom uso de seu aplicativo.

Codificação

Primeiramente vamos criar o recurso de ‘Atalho’ do seu App, ou seja, ao instalarmos o interessante é que o mesmo já seja exibido na tela inicial, portanto, vamos iniciar a codificação.

Adicione as Uses que utilizaremos nos 2 exemplos, ‘Atalho’ e ‘Notificações’.

FMX.Platform.Android,FMX.MobilePreview,FMX.Helpers.Android,Androidapi.JNI.GraphicsContentViewText,AndroidAPI.jni.OS,Androidapi.JNI.JavaTypes,AndroidApi.Jni.App,AndroidApi.JniBridge,

FMX.Notification;

Após isso vamos criar o procedimento responsável pela criação do atalho. Em um de nossos artigos:

Delphi XE5 - Trabalhando com Intents: http://theclub.com.br/Restrito/Revistas/201407/dxe51407.aspx

Vimos como trabalhar com Intents no Android, portanto, vamos repetir o mesmo processo aqui.

Delphi XE5 – Adicionando

Recursos

procedure Atalho;var Intent: JIntent; addIntent: JIntent; I : Integer; wIcone : JIntent_ShortcutIconResource;begin Intent := TJIntent.JavaClass.init(SharedActivityContext, SharedActivityContext.getClass); Intent.setAction(TJIntent.JavaClass.ACTION_MAIN);

addIntent := TJIntent.Create; addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_INTENT, TJParcelable.Wrap((Intent as ILocalObject).GetObjectID)); addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_NAME, StringToJString(Application.Title)); addIntent.setAction(StringToJString(‘com.android.launcher.action.INSTALL_SHORTCUT’));

I := SharedActivity.getResources.getIdentifier(StringToJString(‘ic_launcher’), StringToJString(‘drawable’), StringToJString(‘com.embarcadero.Project1’)); wIcone := TJIntent_

Page 29: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 29

Listagem 3 – Informações do Atalho.

Listagem 4 – Permissão.

Listagem 5 - AndroidManifest.template.xml.

ShortcutIconResource.JavaClass.fromContext(SharedActivityContext, I); addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_ICON_RESOURCE, TJParcelable.Wrap((wIcone as ILocalObject).GetObjectID));

SharedActivityContext.sendBroadcast(addIntent);end;

Neste procedimento é necessário indicar o nome da imagem e de seu projeto para a criação do atalho, conforme trecho abaixo:

I := SharedActivity.getResources.getIdentifier(StringToJString(‘ic_launcher’), StringToJString(‘drawable’), StringToJString(‘com.embarcadero.Project1’));

Com toda a codificação pronta resta apenas ‘liberar’ a permissão de uso em seu ‘AndroidManifest.template.xml’, portanto, adicione a seguinte linha em seu arquivo:

<uses-permission android:name=”com.android.launcher.permission.INSTALL_SHORTCUT”/>

<?xml version=”1.0” encoding=”utf-8”?><!-- BEGIN_INCLUDE(manifest) --><manifest xmlns:android=”http://schemas.android.com/apk/res/android” package=”%package%” android:versionCode=”%versionCode%” android:versionName=”%versionName%”>

<!-- This is the platform API where NativeActivity was

introduced. --> <uses-sdk android:minSdkVersion=”%minSdkVersion%” /> <uses-permission android:name=”com.android.launcher.permission.INSTALL_SHORTCUT”/><%uses-permission%> <application android:persistent=”%persistent%” android:restoreAnyVersion=”%restoreAnyVersion%” android:label=”%label%” android:installLocation=”%installLocation%” android:debuggable=”%debuggable%” android:largeHeap=”%largeHeap%” android:icon=”%icon%” android:theme=”%theme%”> <!-- Our activity is a subclass of the built-in NativeActivity framework class. This will take care of integrating with our NDK code. --> <activity android:name=”com.embarcadero.firemonkey.FMXNativeActivity” android:label=”%activityLabel%” android:configChanges=”orientation|keyboardHidden”> <!-- Tell NativeActivity the name of our .so --> <meta-data android:name=”android.app.lib_name” android:value=”%libNameValue%” /> <intent-filter> <action android:name=”android.intent.action.MAIN” /> <category android:name=”android.intent.category.LAUNCHER” /> </intent-filter> </activity> <receiver android:name=”com.embarcadero.firemonkey.notifications.FMXNotificationAlarm” />

Page 30: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro201530

Listagem 4 – Notificação.

</application></manifest> <!-- END_INCLUDE(manifest) -->

Após finalizarmos essas configurações basta adicionar a procedure ‘Atalho’ em seu projeto e se tudo correu bem seu ícone será criado na tela inicial conforme imagem abaixo:

Imagem 1 – Atalho.

Agora vamos adicionar o segundo recurso que é utilizado por todos os aplicativos que conhecemos que são as ‘Notificações’, aquelas mensagens que são exibidas avisando se alguma mensagem chegou ou se há alguma atualização disponível.

O Delphi já possui um componente próprio para trabalharmos com este recurso, portanto, adicione em seu projeto o componente ‘TNotificationCenter’ em nosso exemplo o nomeamos de ‘Mensagem’. Para a criação e exibição da mensagem em seu aparelho podemos utilizar a procedure ‘Notificacao’, veja que indicamos 2 informações básicas.

‘AlertBody’ = É a mensagem que deseja exibir;‘FireDate’ = O momento em que deseja exibir a mensagem.

procedure Notificacao;Var Notification: TNotification;begin If Notificacao.Supported Then begin Notification := Notificacao.CreateNotification; Try Notification.AlertBody :=

‘The-Club’; Notification.FireDate := Now; Notificacao.ScheduleNotification(Notification); Finally Notification.DisposeOf; end;end;

Após isso basta chamar este procedimento, veja imagem abaixo:

Imagem 2 – Notificação.

Conclusão

Neste artigo vimos como adicionar dois recursos muito úteis ao dia-a-dia de um aplicativo móvel, os recursos apresentados podem ser melhorados e utilizados para diversas funções.

Espero que tenham gostado desta dica e até a próxima!

[email protected]

Jeferson Silva de LimaConsultor The Club.

Sobre o autor

Page 31: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015 05

Page 32: The Club - megazinesobre o assunto BootStrap denominado: “Bootstrap - Pontapé inicial na utiliza-ção do Framework pelo Visual Studio”. Desta vez ele procurou abranger algumas

fevereiro2015