the club - megazinelayout bastante comum atualmente. nele, temos um menu lateral com opções para...

32
setembro 2014

Upload: others

Post on 08-Aug-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014

Page 2: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014

Page 3: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 03

19

Índice

Desafio The Club

30

Editorial

04

10

Autor: Hamden Vogel

05

Autor: Jeferson Silva de Lima

26Delphi XE6 - Como criar uma caixa de diálogo personalizada

Autor: Thiago C. Montebugnoli

Autor: Luciano Pimenta

Delphi 5: Customização

Versionamentos de Arquivos o THVCheckVersion – Parte 1

Android Studio - ParteIII

Page 4: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201404

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

pelos seus respectivos proprietários.

Thiago Montebugnoli - Editor [email protected]

Caro amigo leitor,

Estamos diante de mais uma série de artigos de nossa revista, sempre com a finalidade de envolver uma ampla diversidade de assuntos. Dentre inúmeras datas festivas deste mês de Setembro, não podemos esquecer de uma de extrema importância que é celebrada no dia 7, o Dia da Indepen-dência do Brasil, o dia em que conquistamos a autonomia política e o fim do domínio do povo Português.

Voltando ao foco principal, nesta edição nosso colaborador Luciano Pimenta, com a terceira parte do artigo sobre a ferramenta “Android Stu-dio”, ele abordou mais características de desenvolvimento de aplicativos, como por exemplo: o controle de tela. Com estas informações teremos base para começar a criar diversos tipos de aplicativos mobile. Hamden Vogel, com o artigo “Versionamentos de Arquivos: o THVCheckVersion”, nesta sua primeira parte, ele implementa a função do Windows “ReadDi-rectoryChangesW”, desempenhando um papel importante nas notificações em tempo real, adaptando o processo para o componente em questão, o “THVCheckVersion”. Esta série de artigos são consideradas importantes para termos o controle de versões no desenvolvimento de nossos softwares. Nosso consultor técnico Jeferson Silva de Lima, redigiu o artigo “Delphi XE 5 - Customização”, para sermos mais específicos ele nos ensina a customizar o visual das telas de aplicativos desenvolvidos para Android. Com o auxílio desta dica todo desenvolvedor poderá facilmente deixar seus aplicativos da forma que desejar. Quem não precisou customizar as conhecidas caixas de diálogos no Delphi? Alterar algum ícone, alguma mensagem específica ou até mesmo uma denominação de um botão? Para resolver este problema eu escrevi o artigo “Delphi XE6 – Como criar uma caixa de diálogo persona-lizada”, contendo todas as dicas necessárias para esta tarefa.

Vou ficando por aqui, um forte 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

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 - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 05

Listagem 1 – Componentes.

Introdução

Vimos anteriormente em nossos artigos a criação de aplicações com banco de dados Firebird e SQLite, além da utilização dos recursos Intents. No entanto focamos até o momento nas funcionalidades ‘internas’ e não vimos ainda à customização visual de nossas aplicações, diante disto iniciaremos nosso artigo para demonstrar algumas formas de melhorar a aparência de sua aplicação.

Aplicação

Iniciaremos criando uma simples aplicação mobile, portanto vá em:

• File/New/Firemonkey Mobile Application – Delphi

o ‘Blank Application’ Lembre-se, neste exemplo vamos mostrar apenas a parte visual de nosso

projeto!

Adicione os seguintes componentes em seu formulário:

Image1: TImage;Image2: TImage;Image3: TImage;Image4: TImage;Image5: TImage; ColorBox1: TColorBox; Layout1: TLayout; Layout2: TLayout; Button1: TButton; Button2: TButton; Button3: TButton;ListBox1: TListBox;

Delphi XE5 – Customização

ListBoxGroupHeader1: TListBoxGroupHeader; ListBoxItem1: TListBoxItem; ListBoxItem2: TListBoxItem; ListBoxItem3: TListBoxItem; ListBoxGroupFooter1: TListBoxGroupFooter;

Com os componentes adicionados em nosso projeto, podemos iniciar.

Altere a propriedade ‘Align’ do ‘Layout1’ para ‘alTop’ e do ‘Layout2’ para ‘alBottom’ assim poderemos posicionar as imagens de tal forma que tanto na vertical quanto na horizontal as informações fiquem visíveis. Insira através da paleta ‘Structure’ o componente ‘Image1’ dentro do ‘Layout1’, conforme ilustra a imagem abaixo:

Imagem 1 – Structure.

Page 6: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201406

Altere a propriedade ‘Align’ do componente ‘Image1’ para ‘alClient’ e do ‘Image2’ para ‘alTop’ neste momento poderá definir as imagens que irá utilizar em seu exemplo, veja abaixo como deve ficar o formulário.

Imagem 2 – Formulário Principal.

As três imagens restantes serão nossos botões de ‘Inserir’, ‘Deletar’ e

‘Enviar’. Para que elas fiquem centralizados na tela insira ambos no ‘Layout2’, o alinhamento do botão ‘Inserir’ será ‘alLeft’, ‘Deletar’ ‘alCenter’ e ‘Enviar’ ‘alRight’.

Abaixo do ‘Layout2’ vamos inserir nosso ‘Colorbox1’, defina o alinhamento para ‘alBottom’ e insira seu ‘Listbox’ nele, altere a propriedade ‘StyleLookup’ para ‘Transparentlistboxstyle’ para que nosso ‘Listbox1’ fique transparente e exiba a imagem ou cor que estiver ao fundo, seu alinhamento será ‘alClient’ para que corresponda ao tamanho do ‘ColorBox1’, por fim altere a cor do ‘Colorbox1’ para ’Darkorange’.

Imagem 3 – ListBox.

Veja que já temos alguns itens inseridos no Listbox, para adiciona-los acesse a propriedade ‘Item Editor...’, através do botão direito do mouse, e inclua os seguintes itens:

ListBoxGroupHeader1;ListBoxItem1; ListBoxItem2; ListBoxItem3;ListBoxGroupFooter1.

Imagem 4 – Itens Listbox.

Agora que todos os itens foram posicionados podemos alterar o plano de fundo de nosso formulário, para isso acesse a propriedade ‘Brush’ conforme imagem abaixo:

Imagem 5 – Brush.

Após definir o plano de fundo sua tela deverá ficar parecida com imagem abaixo:

Veja a Imagem 6 – Plano de Fundo.

Com o layout definido coloque os três botões inseridos anteriormente nas imagens ‘Inserir’, ‘Deletar’ e ‘Enviar’, para isso utilize a ’Structure’ e arraste os botões para dentro das imagens, altere a propriedade ‘StyleLookup’ para ‘Transparentcirclebuttonstyle’ e deixe o ‘Align’ para ‘alClient’ assim as imagens serão como os botões em sua tela.

Agora que finalizamos a customização de nosso projeto note que ao alterar a orientação da tela em tempo de execução os itens ficarão um sobre o outro. Para corrigir isto vamos utilizar o evento ‘OnResize’ do formulário.

Page 7: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 07

Listagem 2 – OnResize.

Imagem 7 – Orientação.

Adicione na Uses a Unit ‘FMX.Platform’ e no evento ‘OnResize’ insira o seguinte comando:

procedure TFrmxPrincipal.FormResize(Sender: TObject);Var STela: IFMXScreenService; Orientacao: TScreenOrientation;begin if Assigned(FrmxPrincipal) Then Begin STela:= TPlatformServices.Current.GetPlatformServi

ce(IFMXScreenService) as IFMXScreenService; Orientacao:= STela.GetScreenOrientation;

// Vertical if (Orientacao = TScreenOrientation.soPortrait) or (Orientacao = TScreenOrientation.soInvertedPortrait) then Begin Image4.Align:= TAlignLayout.alNone; Image4.Height:= 60; Image4.Align:= TAlignLayout.alTop;

Image5.Align:= TAlignLayout.alNone; Image5.Height:= 130; Image5.Align:= TAlignLayout.alTop;

Layout2.Align:= TAlignLayout.alNone; Layout2.Height:= 50; Layout2.Align:= TAlignLayout.alTop;

ColorBox1.Align:= TAlignLayout.alNone; ColorBox1.Align:= TAlignLayout.alClient; End;

// Horizontal if (Orientacao = TScreenOrientation.soLandscape) or (Orientacao = TScreenOrientation.soInvertedLandscape) then Begin Image4.Align:= TAlignLayout.alNone; Image4.Width:= FrmxPrincipal.Width; Image4.Align:= TAlignLayout.alTop;

Image5.Align:= TAlignLayout.alNone; Image5.Width:= FrmxPrincipal.Width / 2; Image5.Align:= TAlignLayout.alLeft;

Layout2.Align:=

Imagem 6 – Plano de Fundo.

Page 8: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201408

Listagem 3 – xml_Splash.

TAlignLayout.alNone; Layout2.Height:= 50; Layout2.Align:= TAlignLayout.alBottom;

ColorBox1.Align:= TAlignLayout.alNone; ColorBox1.Width:= FrmxPrincipal.Width / 2; ColorBox1.Align:= TAlignLayout.alRight; End; End;end;

Após definir as orientações os itens ficarão alinhados conforme imagem abaixo:

Imagem 8 – Alinhamento.

Observação: É necessário realizar o teste em Tablets, pois, a definição da orientação pode alternar.

Agora que concluímos nossa tela inicial, há mais um recurso interessante para melhorar a aparência de seu projeto, o chamando ‘Splash’, que consiste em uma imagem de apresentação de sua aplicação. Para adicionar este recurso vamos primeiramente criar uma pasta na raiz do projeto e nomeá-la de ‘res’. Insira nesta pasta os seguintes diretórios:

drawable;drawable-hdpi;drawable-ldpi;drawable-mdpi;drawable-xhdpi;drawable-xxhdpi;values.

Imagem 9 – Pastas.

Nestas pastas vamos encontrar as imagens que serão exibidas ao abrir nossa aplicação, portanto, acaba sendo necessário definir a mesma imagem em tamanhos diferentes para que alterne de acordo com o tamanho da tela. Segue abaixo as dimensões das imagens.

drawable-hdpi – splash.png (164x252);drawable-ldpi – splash.png (80x123);drawable-mdpi – splash.png (107x164);drawable-xhdpi – splash.png (213x327);drawable-xxhdpi – splash.png (320x492).

Vamos encontrar também dois arquivos XML nas pastas restantes (drawa-ble e values), cada xml irá conter as instruções para o funcionamento correto do Splash. Portanto em nossa primeira pasta adicione o seguinte XML:

Pasta (drawable):

‘xml_splash.xml’

Suacodificaçãoserá:

<?xml version=”1.0” encoding=”utf-8”?><layer-list xmlns:android=”http://schemas.android.com/apk/res/android” > <item> <shape xmlns:android=”http://schemas.android.com/apk/res/android” android:shape=”rectangle” android:layout_centerInParent=”true” android:layout_gravity=”center_horizontal” android:layout_width=”wrap_content” android:layout_height=”wrap_content” > <solid android:color=”#000000”

Page 9: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 09

Listagem 4 – styles.xml.

/> </shape> </item> <item> <bitmap android:src=”@drawable/splash” android:gravity=”center” /> </item></layer-list>

Este arquivo cria a interface propriamente dita, ou seja, aqui poderá definir a forma de exibição de sua imagem.

Em nosso outro XML (styles.xml) que encontra-se na pasta ‘values’ vamos definir através dele qual o tema que iremos utilizar além de definir também quais itens serão exibidos ao iniciar a tela, o que no caso é onde entra nossa imagem ‘splash’. Abaixo codificação do arquivo:

<?xml version=”1.0” encoding=”utf-8”?><resources><style name=”MyTheme.NoTitleBar.THECLUB” parent=”@android:Theme.Black”> <item name=”android:windowBackground”>@drawable/xml_splash</item> <item name=”android:windowContentOverlay”>@null</item> <item name=”android:windowNoTitle”>true</item></style></resources>

Para finalizar será necessário alterar a seguinte linha em seu arquivo ‘An-droidManifest.template.xml’ que encontra-se na raiz de seu projeto:

android:theme=”%theme%”>Altere para:android:theme=”@style/MyTheme.NoTitleBar.THECLUB”>

Feito isto basta definir em seu Deployment todos os arquivos que criamos anteriormente, veja como deve ficar conforme imagem abaixo:

Veja a Imagem 10 – Deployment.

Conclusão

Neste artigo demonstramos algumas formas de melhorar a aparência de seus projetos, fiquem à vontade para alterar e melhorar de acordo com suas necessidades.

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

Imagem 10 – Deployment.

[email protected]

Jeferson Silva de LimaConsultor The Club.

Sobre o autor

Page 10: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201410

Estamos desenvolvendo artigos sobre o Android Studio, fer-ramenta gratuita para desenvolver projetos Android. Neste artigo, vamos conhecer um pouco da codificação Java para nosso aplicativo. No artigo anterior, comentei sobre informa-ções da lentidão do Android Studio quando fazemos deploy da

aplicação no device.

Temos uma ótima noticia, isso foi otimizado, a partir da versão 0.8.2. O deploy esta muito mais rápido. A primeira execução da app demora um pouco, mas as seguintes estão rápidas, demorando segundos para aparecer no device.

Neste artigo vamos mostrar um pouco do básico para o entendimento de app Android. Controles de telas, layouts e dicas interessantes.

Conhecendo o projeto

O projeto que criamos é do template Navigation Drawer Activity, com layout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1).

Figura 1. Projeto rodando

Se quisermos mudar os valores dos itens adicionados (Section), precisamos trabalhar com resource. Resource é um arquivo XML para armazenar textos que usaremos na aplicação. Abra o arquivo values>strings.xml.

Nesse arquivo, temos algumas strings prontas, basta mudar os valores que serão alterados no menu. Faça o teste (Figura 2).

Figura 2. Alterando o texto do menu

Vamos conhecer agora, alguns controles de tela mais comuns usados em aplicativos Android. Abra o arquivo fragment_my.xml da pasta layout. Coloque no mode de design, onde aparece os controles de tela. Note que já existe um TextView.

Adicione um Button. Basta escolher o controle na lista e arrastar para a tela. Vamos fazer o famoso “Hello World”, ou seja, ao clicar no botão, será mostrada a frase no TextView. Acesse o método onCreateView da classe PlaceholderFragment no arquivo MyActivity.java da pasta Java. Esse arquivo refere-se à tela inicial da aplicação.

Digite o seguinte código:

Button botao = (Button)rootView.

Android Studio – Parte III

Page 11: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 11

findViewById(R.id.button);botao.setOnClickListener(new View.OnClickListener() {

@Overridepublic void onClick(View v) { TextView texto = (TextView)rootView.findViewById(R.id.section_label); texto.setText(“Hello World!”); }});

Nota: por vezes ao digitar algumas classes, precisar fazer o import das mesmas. O Android Studio auxilia esse trabalho, onde você coloca o cursor do mouse na classe (sempre aparece em vermelho) e aperta ALT+ENTER. Aparece um menu e a opção Import class. Basta escolher e pronto, classe importada.

No código, usamos o método findViewById para “encontrar” o botão. Bastante semelhante ao que fazemos em JavaScript, quando precisamos acessar algum controle. Note que usamos a variável rootView (esta declarada no OnCreateView).

Isso ocorre, por que estamos em um Fragment e como podemos ver no OnCreateView, o rootView “carrega” o layout fragment_my.xml, onde adicio-namos os controles de tela. Precisamos marcar a variável rootView com “final”, para que possamos acessá-la dentro do evento OnClick do botão.

finalViewrootView=inflater.inflate(R.layout.fragment_my,container,false);

Continuando no código, pesquisamos com o findViewById para achar o TextView e atribuir valor para o mesmo. Execute a aplicação e veja o resultado (Figura 3).

Figura 3. Hello World no Android

Vamos agora, mudar o rótulo do botão. Poderíamos usar a propriedade Text, trocando no XML do fragment_my.xml:

<Button ... android:text=”New Button” android:id=”@+id/button” android:layout_below=”@+id/section_label” ... />

Como também poderíamos alterar na janela de propriedades do Android Studio (Figura 4)

Figura 4. Modificando a propriedade Text do botão

Modificar o texto assim, não é uma prática muito interessante de ser usada e por isso, aplicações no Android Studio (Android), usam arquivos de resource para organizar textos que mostramos no projeto.

Abra o arquivo strings.xml na pasta res>values. Crie um novo resource, conforme o código a seguir:

<string name=”button_name”>Hello World</string>

Para usar esse texto no botão ou outras partes do projeto, basta atribuir o mesmo em propriedades ou via código. Na propriedade Text do botão, modifique para o seguinte código:

android:text=”@string/button_name”

Basta indicar @string, e depois o nome do resource, existente no arquivo. No preeview já deve aparecer o novo texto. Execute e teste a aplicação. Volte o valor da propriedade, pois vamos fazer agora um exemplo via código.

Page 12: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201412

Novamente no OnCreateView, vamos usar o seguinte código, após o findViewById do botão:

botao.setText(R.string.button_name);

A classe R organiza todos os ids de controles, strings, imagens do projeto. Assim, temos mais facilidade para atribuir textos, imagens etc.

Nota: a classe R é gerada pela ferramenta, não pode ser editada.

Execute a aplicação para testar. Caso ainda não acredite, experimente mudar o valor do button_name.

Podemos usar o resource em quase todo o projeto. Abra o arquivo An-droidManifest.xml e veja que no item android:label é usado um resource para indicar o nome do projeto. Alterar essa propriedade ou o resource indicado nela modifica o texto em toda a aplicação que for mostrar o rótulo com o nome da app.

Criando novos forms

Temos três itens no menu lateral, assim, precisamos de três formulários/layout para abri-los na aplicação. Crie três layouts na pasta layout. Para isso, clique com o botão direito na pasta layout e escolha a opção New>Layout resource file.

Digite o nome do layout (“activity_home.xml”, “activity_parametros.xml” e “activity_configuracoes.xml”). Veja os arquivos na Figura 5.

Figura 5. Criando layouts

Dentro de cada layout, adicione um TextView e configure na propriedade Text o nome do layout. Atente para o nome do controle (propriedade id). Para abrir cada formulário, voltaremos ao OnCreateView do PlaceholderFragment. Precisamos saber, qual item do menu foi escolhido, para isso, temos a variável

ARG_SECTION_NUMBER.

Usando ela, sabemos qual item foi selecionado e assim, carregar o res-pectivo formulário. Veja no código a seguir, como ficaria:

if (getArguments().getInt(ARG_SECTION_NUMBER) == 1) { //tela homerootView=inflater.inflate(R.layout.activity_home,container,false);}else if (getArguments().getInt(ARG_SECTION_NUMBER) == 2){ //tela parâmetrosrootView=inflater.inflate(R.layout.activity_parametros,container,false);}else {//telaconfiguraçõesrootView=inflater.inflate(R.layout.activity_configuracoes,container,false);}

return rootView;

Comente o código do click do botão e remova o final da variável rootView. O código é simples, onde usamos if..elseif. Verificamos qual o item selecionado no menu e carregamos seu respectivo layout. Execute a aplicação e selecione os itens do menu, veja que o layout correspondente é carregado (Figura 6).

Figura 6. Abrindo formulários pelo menu

Estamos dentro de um fragment, todos os layouts, serão abertos no mes-mo “espaço”. Mas e quando precisamos criar outro formulário e não usar o fragment, como fazer? Precisamos então criar uma Activity para o layout. Uma Activity, basicamente, gerencia a parte UI da aplicação Android. Toda aplica-ção, começa com uma Activity (nosso template adicionou a MyActivity.java).

Page 13: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 13

Clique com o botão direito na pasta do pacote (com.nomedaaplicacao) e escolha o item New>Java class. Vamos chamado de “ActivityParametros”. Na classe criada, precisamos herdar de Activity:

public class ActivityParametros extends Activity

E declarar o método Create:

@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_parametros);}

Precisamos especificar no onCreate, qual o layout essa Activity vai carregar, usando o setContentView. No MyActivity.java para chamar essa tela, usamos o seguinte código:

//tela parâmetrosIntent formParametro = newIntent(getActivity(),ActivityParametros.class);startActivity(formParametro);

A classe Intent, recebe dois parâmetros, a Activity que estamos e para qual ela será direcionada. Como estamos em um Fragment, precisamos usar o método getActivity, senão bastaria passar NomeDaClasse.this. No segundo, chamamos o Activity criada.

Para abrir o formulário, basta chamar startActivity, passando a variável Intent. Para finalizar, precisamos declarar essa Activity no manifesto. Abra o AndroidManifest.xml e adicione o seguinte código:

<activity android:name=”.ActivityParametros” android:label=”@string/title_section2”></activity>

Adicione dentro da tag application, abaixo da activity principal. Apenas indicamos qual a Activity estamos declarando e passamos um nome para o título da mesma. Rode a aplicação para testar.

Passando dados entre formulários

E se precisássemos passar valores entre um formulário e outro? Variável global? Se você pensou isso, pensou errado. A classe Intent disponibiliza propriedades para podermos passar valores. Abra o arquivo de layout activi-ty_parametros.xml. Remova o valor da propriedade Text do TextView.

Ela será preenchida com valores oriundos de outro formulário. Na chamada do formulário de parâmetros, vamos modificar a chamada:

Intent formParametro = newIntent(getActivity(),ActivityParametros.class);formParametro.putExtra(“Name”,“Tela de parâmetros”);startActivity(formParametro);

Usamos putExtra de Intent para dar um nome e um valor. Na Activity de parâmetros, precisamos receber esse valor e atribui para o controle TextView. No onCreate da classe, usamos o seguinte código:

String name = getIntent().getExtras().get(“Name”).toString();

TextView texto = (TextView)findViewById(R.id.section_label);texto.setText(name);

Atribuímos para uma variável o valor do Intent, usando getIntent. Pegamos o TextView e colocamos na propriedade Text o valor da variável. Bem simples e fácil. Veja na Figura 7 a aplicação.

Figura 7. Passando valores entre formulários

Page 14: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201414

Lembrando, podemos passar vários parâmetros. Usamos um putExtra (com nome e valor) para cada parâmetro. Veja na Figura 8 que usamos um parâmetro para configurar o título do formulário (usamos setTitle para atribuir o valor na Activity).

Figura 8. Alterando o título do formulário

Controles de tela

Vamos conhecer algumas caracteristicas dos controles mais comuns usados no Android. O TextView, como já vimos, é um Label onde mostramos textos na aplicação. Vamos conhecer o EditView que é uma caixa de texto semelhante há que temos em outros sistemas operacionais.

Quais as características mais interessantes desse controle? Ele aceita al-fanuméricos, somente números, senhas, datas etc. Quando configurado para aceitar somente números o teclado do device mostra somente números, isso é bom, pois não precisamos validar se o que foi digitado é número.

No layout da tela de configurações, adicione quatro TextView. O pri-meiro deixe com as propriedades default. No segundo, mude a propriedade inputType para “number”. No terceiro, mude para textPassword e por último numberDecimal.

Dê uma olhada na propriedade inputType e veja a quantidade de opções. Abaixo o código dos quatros controles:

<EditText android:layout_width=”match_parent” android:layout_height=”wrap_content” android:id=”@+id/editText1”/>

<EditText android:layout_width=”match_parent” android:layout_height=”wrap_content” android:id=”@+id/editText2” android:inputType=”number”/>

<EditText android:layout_width=”match_parent” android:layout_height=”wrap_

content” android:id=”@+id/editText3” android:inputType=”textPassword”/>

<EditText android:layout_width=”match_parent” android:layout_height=”wrap_content” android:id=”@+id/editText4” android:inputType=”numberDecimal” android:gravity=”right”/>

Rode a aplicação (Figura 9).

Figura 9. Controles com opções de dados de entrada

No primeiro controle, podemos digitar texto e números. No segundo, aceita apenas números. No terceiro, não aparece o que foi digitado, pois é uma senha. Por fim, o último controle tem a opção de ponto (“.”) para colocar valores decimais. Eu configurei o alinhamento, para que os números fiquem alinhados a direita.

ToogleButton

Esse controle é semelhante a um RadioButton, pois tem somente dois esta-dos (on ou off). Podemos configurar seu estado e ainda um texto para quando estiver On ou Off. Adicione dois ToogleButton, um TextView e um Button.

Veja a seguir, o código dos controles:

<ToggleButton

Page 15: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 15

android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:text=”New ToggleButton” android:id=”@+id/toggleButton1” />

<ToggleButton android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:text=”New ToggleButton” android:id=”@+id/toggleButton2” android:textOn=”Sim”android:textOff=”Não” android:checked=”true”/>

<Button android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:text=”New Button” android:id=”@+id/button” android:layout_gravity=”center_horizontal” />

<TextView android:layout_width=”match_parent” android:layout_height=”wrap_content” android:id=”@+id/textView” android:layout_gravity=”center_horizontal” />

Para codificar o OnClick do botão, vamos acessar o arquivo MyActivity.java e no else if, que abre a tela de configurações, codificar o seguinte código:

finalToggleButtontoogle1= (ToggleButton)rootView.findViewById(R.id.toggleButton1);finalToggleButtontoogle2= (ToggleButton)rootView.findViewById(R.id.toggleButton2);

Button botao = (Button)rootView.findViewById(R.id.button);finalTextViewtexto=(TextView)rootView.findViewById(R.id.textView);

botao.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { StringBuffer buffer = new StringBuffer(); buffer.append(“ToggleButton1: Estado:” + toogle1.isChecked() + “ - Texto: “ + toogle1.getText()); buffer.append(“\nToggleButton2: Estado:” + toogle2.isChecked() + “ - Texto: “ + toogle2.getText());

texto.setText(buffer); }});

Criamos as variáveis dos controles de tela. Note que as variáveis que precisam ser acessadas dentro do evento onClick do botão, estão marcadas como final. No onClick, criamos uma variável para colocar um texto indicando o estado e o Text existente nos controles.

Por fim, apenas indicamos no TextView os valores. Veja na Figura 10, a aplicação em execução.

Figura 10. ToggleButton em execução

Spinner

O controle Spinner nada mais é do que um DropDownList do Android.

Page 16: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201416

Podemos populá-lo usando um adapter ou resource. Para usarmos resource, vamos usar um array. Veja no código a seguir como seria um array de resource:

<string-array name=”paises”> <item>Brasil</item> <item>Argentina</item> <item>Alemanha</item><item>França</item> <item>México</item> <item>Uruguai</item> <item>Paraguai</item></string-array>

Na propriedade entries do controle, vamos indicar o array criado no resource:

<Spinner android:layout_width=”match_parent” android:layout_height=”wrap_content” android:id=”@+id/spinner” android:entries=”@array/paises”/>

Rode a aplicação e veja o Spinner em execução. Se a lista for mais que a altura do device, é colocado um scroll para navegar entre os itens. Adicione mais um Spinner na tela, vamos usar um adapter para preenchê-lo:

Spinner drop = (Spinner)rootView.findViewById(R.id.spinner2);

List<String> lista = new ArrayList<String>();lista.add(“Item 1”);lista.add(“Item 2”);lista.add(“Item 3”);lista.add(“Item 4”);

drop.setAdapter(new ArrayAdapter<String>(getActivity(),android.R.layout.simple_spinner_item,lista));

Criamos uma lista e preenchemos. Essa lista poderia ser preenchida com dados do banco do device, JSON etc. Usamos o método setAdapter para preencher o Spinner, onde criamos um ArrayAdapter, passando a Activity como parâmetro, depois indicamos o tipo de layout que usaremos e por final a própria lista.

Execute e veja o controle preenchido com a lista que criamos. Para pegarmos o valor escolhido no Spinner, adicione um botão e um TextView e adicione o seguinte código:

Button botao = (Button)rootView.findViewById(R.id.button);finalTextViewtexto=(TextView)rootView.findViewById(R.id.textView);

botao.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { texto.setText(drop.getSelectedItem().toString()); }});

Note que a variável do TextView é final, para podermos acessá-la no evento onClick do botão. Mostramos no TextView, o valor do item selecionado no Spinner, usando o getSelectedItem. Simples e fácil (Figura 11).

Figura 11. Mostrando o item selecionado no Spinner

Caixas de mensagens

Qualquer aplicativo precisa mostrar mensagens ao usuário, seja para indicar que algo deu errado ou para mostrar que a funcionalidade foi execu-

Page 17: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 17

tada com sucesso. No Android temos caixas de mensagens com interação ou não do usuário.

O que quer dizer com interação do usuário, são caixas de mensagens onde o usuário precisa executar alguma ação, seja para fechar, ou para responder há uma pergunta. E as mensagens sem interação? No Android temos uma mensagem que fica aparecendo de acordo com um determinado tempo, depois disso, ela some.

Vamos ver um exemplo. Adicione um botão para a tela de parâmetros. Vamos fazer outra maneira de atribuir o onClick do botão (sem Listener). Vamos atribuir um valor para a propriedade onClick do botão:

android:onClick=”BotaoClick”

Agora, na Activity (ActivityParametros.java), vamos declarar um método com o mesmo nome, onde vamos colocar o código que precisamos.

public void BotaoClick(View view){ }

Dentro desse método, vamos atribuir o código necessário a ser executado, quando o usuário clicar no botão. Bem simples. Vamos mostrar agora, como mostrar uma mensagem, sem a interação do usuário. Por padrão a mensagem é sempre mostrada na parte inferior do device. Dentro do BotaoClick, digite o seguinte código:

Toast.makeText(this,“MensagemToast”,Toast.LENGTH_LONG).show();

Usamos a classe Toast, invocando o método makeText, que recebe como primeiro parâmetro o contexto do projeto (nesse caso this). No segundo parâmetro, adicionamos o texto. Aqui colocamos no código, mas como você já sabe, podemos usar resource.

O último parâmetro indica o tempo que a mensagem será mostrada, curto ou longo. Por fim, invocamos o show. Execute a aplicação e veja o Toast em execução (Figura 12).

Veja a Figura 12. Mostrando uma caixa de mensagem

Figura 12. Mostrando uma caixa de mensagem

Outro exemplo de caixa de mensagem, é usando a classe AlertDialog. Comente o código do Toast e adicione o seguinte código:

AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);dialogBuilder.setTitle(“Título da mensagem”);dialogBuilder.setMessage(“Mensagem da caixa de dialogo”);

AlertDialog dialog = dialogBuilder.create();dialog.show();

Nesse caso, teremos que trabalhar com duas classes: AlertDialog.Builder serve para criar a interface da caixa de mensagem e AlertDialog serve para mostrar a mesma no aplicativo. Configuramos o título da caixa e a mensagem que será mostrada.

Por fim, atribuímos as características da caixa de mensagem para o AlertDialog que vai exibir, usando o método show. Execute a aplicação e faça o teste. Note que não temos nenhum botão, apenas o título e a mensagem.

Precisamos codificar o botão, ele não tem nenhum default. Adicione o seguinte código, após configurar a mensagem:

dialogBuilder.

Page 18: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201418

setPositiveButton(“OK”,new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterfacedialog,int which) { Toast.makeText(ActivityParametros.this,“ClicouemOK”, Toast.LENGTH_LONG).show(); }});

dialogBuilder.setNegativeButton(“Não”,new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterfacedialog,int which) { Toast.makeText(ActivityParametros.this,“ClicouemNão”, Toast.LENGTH_LONG).show(); }});

O dialogBuilder disponibiliza dois métodos para configurar o botão OK e No, que são padrões. Claro, o nome dos mesmos pode ser modificado no primeiro parâmetro. Execute a aplicação e faça os testes clicando nos botões da caixa de mensagem (Figura 13).

Figura 13. Criando caixas de mensagens com AlertDialog

Podemos configurar um ícone na caixa, usando o método setIcon. Ainda podemos colocar na caixa de mensagem, itens, como se fossem ListView, bas-

tando configurar com os itens a serem mostrados, o método setItems. Nesse caso, não configuramos setMessage (código fonte disponível para download).

Figura 14. Caixa de mensagem customizada com ícone e itens

Conclusões

Vimos neste artigo, mais características de aplicativos Android com An-droid Studio. Conhecemos alguns controles de tela, usados em aplicativos. Com essas informações você tem base para começar a criar seus aplicativos Android e quem sabe ter uma idéia que irá revolucionar aplicativos mobile . O céu é o limite.

Um grande abraço a todos e até a próxima!

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 19: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 19

Hoje em dia em fábricas de software é indispensável a utili-zação de ferramentas como SubVersion, onde conseguimos fazer comparações de códigos-fonte, no que diz respeito a alterações, inclusões e remoções de suas linhas, de seus ar-quivos, enfim, de todo o controle de sua baseline, podendo

fazer merges de dois arquivos comparados para unir o fonte em um só; portanto as possibilidades são muitas. Quem já passou apuros para entregar uma build, onde a versão anterior à atual encontra-se com outro desenvolvedor, e tem que unir as versões de ambos com um merge para commitar a entrega sabe bem do que estou falando – e nem sempre dá certo – a garantia da entrega nem sempre será a garantia da execução da nova build gerada – e nesse caso porque não comparar rapidamente – localmente – as últimas alterações do arquivo em modo texto trabalhado, analisando seu histórico por data de modificação, de um jeito mais rápido do que o tradicional (fazer checkout, comparar se é ela mesma, procura outra versão, manter esse loop até encontrar a versão desejada nesse processo) – não seria uma alternativa mais eficiente a baixo custo, onde se resgataria as versões geradas automaticamente em um arquivo no diretório temporário do Windows até encontrar a versão desejada neste histórico ordenado por data de modificação? Podendo, claro, posteriormente zipar toda esta árvore de diretórios e armazenar no SubVersion, em um disco rígido externo, etc; nasce, portanto o nosso novo componente de hoje: o THVCheckVersion.

Os requisitos exigidos para o nosso framework trabalhar:

1. Versões mais recentes do Windows;2. Permissão de Administrador (ou equivalente) para acesso de leitura/

gravação nos diretórios temporários do Windows;3. Um pouco de espaço no Disco Rígido;4. O arquivo deve ser do modo texto ou binário, e deve possuir ex-

tensão. Para esta primeira versão deste programa, foi criado um array para permitir apenas 6 extensões utilizadas famosamente por desenvolvedores ( const arExtensoesValidas: array [0..7] of string = (‘.txt’, ‘.js’, ‘.java’, ‘.php’, ‘.asp’, ‘.html’, ‘.htm’, ‘.pas’);

Versionamentos de Arquivos: o THVCheckVersion – Parte 1

Considerações Iniciais

O diretório de monitoração a ser utilizado pelo nosso aplicativo é a pro-priedade DirectoryMonitoring (string) – ela é que fará o “trabalho pesado” de monitorar uma área desejada. É aí que entra a parte mais interessante do pro-cesso – nessa definição contempla-se toda a “espionagem” do comportamento de criação/gravação (alteração) dos arquivos contidos nessa monitoração. Sempre que uma alteração for detectada (sempre pelo evento do usuário) o sistema operacional sinalizará à nossa aplicação que algo ocorreu – graças à API ReadDirectoryChangesW do kernel32.dll do Windows – ela que é a “dedo--duro” da história – reportando ao emissor do processo (no caso a gente) que houve mudanças em algum lugar na nossa região de monitoração – subdire-tórios também serão verificados. Como foi mencionado, essa função será de grande valia para o componente THVCheckVersion, pois nela se baseia toda a transmissão das notificações de alterações dos arquivos – data/hora em tempo real (no momento em que um arquivo é salvo, o componente já fica sabendo – inclusive vai saber o nome do arquivo alterado também).

A função ReadDirectoryChangesW retornará diferente de zero em caso de sucesso. Na nossa implementação será chamada sempre sincronicamente (modo síncrono)

BOOL WINAPI ReadDirectoryChangesW( _In_ HANDLE hDirectory,_Out_LPVOIDlpBuffer, _In_ DWORD nBufferLength, _In_ BOOL bWatchSubtree, _In_ DWORD dwNotifyFilter, _Out_opt_ LPDWORD lpBytesReturned, _Inout_opt_ LPOVERLAPPED

Page 20: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201420

lpOverlapped, _In_opt_ LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);

Figura 01 - Declaração da função ReadDirectoryChanges.

Explicações dos Parâmetros:

hDirectory [in]Um identificador para o diretório a ser monitorado.

lpBuffer [out]Um ponteiro para o buffer (DWORD) onde os resultados são devolvidos. É

definida pela estrutura FILE_NOTIFY_INFORMATION. Pode ser preenchido de forma síncrona ou assíncrona, dependendo de como o diretório será aberto e qual o valor que é dado ao parâmetro lpOverlapped.

nBufferLength [in]O tamanho do buffer do parâmetro lpBuffer (mencionado anteriormente),

em bytes.

bWatchSubtree [in]Se verdadeiro, a função vai monitorar também os subdiretórios (do dire-

tório que é o parâmetro hDirectory). Senão, vai monitorar apenas o diretório (parâmetro hDirectory).

dwNotifyFilter [in]Permite definir os parâmetros (critérios de busca) a serem pesquisados.

Podem ser os seguintes:

FILE_NOTIFY_CHANGE_FILE_NAME Envolve mudança de nome de arquivo no diretório/subdiretório. As mu-

danças incluem renomear, criar ou excluir um arquivo.

FILE_NOTIFY_CHANGE_DIR_NAME Envolve mudança de nome de diretório/subdiretório. As mudanças incluem

a criação ou exclusão de um diretório.

FILE_NOTIFY_CHANGE_ATTRIBUTES Envolve mudanças de atributo no diretório/subdiretório monitorado.

FILE_NOTIFY_CHANGE_SIZE Envolve mudanças de tamanho dos arquivos monitorados no diretório/

subdiretório. O sistema operacional detecta uma alteração no tamanho de um arquivo somente quando o mesmo é gravado para o disco rígido dele. No caso de sistemas operacionais usando cache, a alteração será detectada somente quando o cache for totalmente liberado.

FILE_NOTIFY_CHANGE_LAST_WRITE Envolve mudanças para a última gravação de um arquivo. O sistema ope-

racional detecta uma alteração da última gravação de um arquivo somente quando o mesmo é gravado para o disco rígido dele. No caso de sistemas operacionais usando cache, a alteração será detectada somente quando o cache for totalmente liberado.

FILE_NOTIFY_CHANGE_LAST_ACCESS Envolve mudanças para o último tempo de acesso de arquivos no diretório/

subdiretório monitorado.

FILE_NOTIFY_CHANGE_CREATION Envolve mudanças no tempo de criação de arquivos no diretório/subdi-

retórios monitorados. FILE_NOTIFY_CHANGE_SECURITY Envolve mudanças relacionadas à segurança nos diretórios/subdiretórios

monitorados.

Portanto, esta função fará o papel de monitorar nosso disco-rígido, reportando historicamente (ordem cronológica dos acontecimentos) tudo o que acontece com os arquivos (comportamento); existe uma implementação interessante de domínio público na internet em que foi estudada esta função e abordada em nossa particular implementação do componente; segue abaixo uma tela de exemplo de seu funcionamento e algumas considerações:

function ReadDirectoryChangesW; external kernel32 name ‘ReadDirec-toryChangesW’;

Figura 02 – Tela de um programa Demo que utiliza a função ReadDirectoryChan-gesW para detecção de notificações de arquivos.

Esse programa de exemplo se baseia nessa função ReadDirectoryChan-

gesW, construindo uma classe chamada TFolderMon contendo os dados a serem chamados e uma classe TThread chamada TFolderMonWorker, onde de fato essa função é chamada (no método execute da thread).

Segue abaixo a declaração contida na unit FolderMon, que implementa toda a estrutura da função citada, de forma elegante e eficiente, capturando

Page 21: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 21

todos os eventos desejados relacionados aos arquivos/diretórios/subdiretórios desejados (parametrizados pelo sistema):

unit FolderMon;

interface

uses SysUtils,Classes,Windows ;

type TFolderAction = ( faNew,faRemoved,faModified,faRenamedOld,faRenamedNew );

const FOLDER_ACTION_NAMES: array[TFolderAction] of string =(‘New’,‘Removed’,‘Modified’,‘OldName’,‘Newname’);

type TFolderItemInfo=record Name : string; Action: TFolderAction; end;

TChangeType = ( ctFileName,ctDirName,ctAttr,ctSize,ctLastWriteTime,ctLastAccessTime,ctCreationTime,ctSecurityAttr );

TChangeTypes = set of TChangeType; TFolderMon=class;

TFolderChangeEvent = procedure (Sender: TFolderMon; AFolderItem: TFolderItemInfo) of object;

TFolderMon=class private FFolder: string; FWorker: TThread; FMonitoredChanges: TChangeTypes; FMonitorSubFolders: Boolean; FOnFOlderChange: TFolderChangeEvent; FOnDeactivated: TNotifyEvent; FOnActivated: TNotifyEvent; procedure SetFolder(const Value: string); function GetIsActive: Boolean; procedure SetIsActive(const Value: Boolean); procedure SetMonitoredChanges(const Value: TChangeTypes); procedure SetMonitorSubFolders(const Value: Boolean); public destructor Destroy; override;

procedure Activate; procedure Deactivate;

property Folder: string read FFolder write SetFolder; property IsActive: Boolean read GetIsActive write SetIsActive; property MonitoredChanges : TChangeTypes read FMonitoredChanges write SetMonitoredChanges; property MonitorSubFolders: Boolean read FMonitorSubFolders write SetMonitorSubFolders; property OnFolderChange: TFolderChangeEvent read FOnFOlderChange write FOnFolderChange; property OnActivated: TNotifyEvent read FOnActivated write FOnActivated; property OnDeactivated: TNotifyEvent read FOnDeactivated write FOnDeactivated; end;

implementation

Page 22: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201422

const NOTIFY_FILTERS: array[TChangeType] of DWORD = ( FILE_NOTIFY_CHANGE_FILE_NAME // ctFileName,FILE_NOTIFY_CHANGE_DIR_NAME // ctDirName,FILE_NOTIFY_CHANGE_ATTRIBUTES // ctAttr,FILE_NOTIFY_CHANGE_SIZE// ctSize,FILE_NOTIFY_CHANGE_LAST_WRITE // ctLastWriteTime,FILE_NOTIFY_CHANGE_LAST_ACCESS // ctLastAccessTime,FILE_NOTIFY_CHANGE_CREATION // ctCreationTime,FILE_NOTIFY_CHANGE_SECURITY // ctSecurityAttr );

type TFolderMonWorker=class(TThread) private Owner: TFolderMon; FFolder: THandle; FMonFilter: DWord; FFolderItemInfo: TFolderItemInfo; procedure SetUp; procedure TearDown; procedure DoFolderItemChange; protected procedure Execute; override; public constructor Create(AOwner: TFolderMon); reintroduce; end;

{ TFolderMon }

procedure TFolderMon.Activate;begin if IsActive then Exit;

if FMonitoredChanges=[] then raise Exception.Create(‘Please specify event(s)

to be monitored’); if not DirectoryExists(FFolder) then raise Exception.Create(‘Please supply valid/existing folder’);

FWorker := TFolderMonWorker.Create(Self); if Assigned(FOnActivated) then FOnActivated(Self);end;

procedure TFolderMon.Deactivate;begin if not IsActive then Exit;

with TFolderMonWorker(FWorker) do begin Owner := nil; Terminate; end; FWorker := nil; if Assigned(FOnDeactivated) then FOnDeactivated(Self);end;

destructor TFolderMon.Destroy;begin Deactivate; inherited;end;

function TFolderMon.GetIsActive: Boolean;begin Result := FWorker <> nil;end;

procedure TFolderMon.SetFolder(const Value: string);begin if LowerCase(FFolder)=LowerCase(Value) then Exit;

if IsActive then raise Exception.

Page 23: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 23

Create(‘Currently still actively monitoring a folder. Please deactivate before changing monitored folder.’);

FFolder := Value;end;

procedure TFolderMon.SetIsActive(const Value: Boolean);begin if Value then Activate else Deactivate;end;

procedure TFolderMon.SetMonitoredChanges(const Value: TChangeTypes);begin if FMonitoredChanges = Value then Exit;

if IsActive then raise Exception.Create(‘The monitor must be deactivated before changing the monitored event(s)’); FMonitoredChanges := Value;end;

procedure TFolderMon.SetMonitorSubFolders(const Value: Boolean);begin if FMonitorSubFolders=Value then Exit;

if IsActive then raise Exception.Create(‘Please deactivate the monitorfirst’);

FMonitorSubFolders := Value;end;

{ TFolderMonWorker }

constructor TFolderMonWorker.

Create(AOwner: TFolderMon);begin Owner := AOwner; if Owner=nil then raise Exception.Create(‘Reference to TFolderMon instancemustbespecified’);

inherited Create(False); FreeOnTerminate := True; SetUp;end;

const FILE_LIST_DIRECTORY = $0001;

type _FILE_NOTIFY_INFORMATION=packed record NextEntryOffset: DWORD; Action: DWORD; FileNameLength: DWORD; FileName: WideChar; end; FILE_NOTIFY_INFORMATION = _FILE_NOTIFY_INFORMATION; PFILE_NOTIFY_INFORMATION = ^FILE_NOTIFY_INFORMATION;

procedure TFolderMonWorker.DoFolderItemChange;begin if Assigned(Owner) and Assigned(Owner.FOnFolderChange) thenOwner.FOnFOlderChange(Owner,FFolderItemInfo);end;

procedure TFolderMonWorker.Execute;const cBufSize = 32 * 1024; // 32kvar B: Pointer; vCount: DWord; vOffset: DWord; vFileInfo: PFILE_NOTIFY_INFORMATION;beginGetMem(B,cBufSize); try while not Terminated do begin if Owner=nil then Exit;

Page 24: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201424

if ReadDirectoryChangesW(FFolder,B,cBufSize,Owner.MonitorSubFolders,FMonFilter,@vCount,nil,nil ) and (vCount > 0) then begin if Owner=nil then Exit;

vFileInfo := B; repeat vOffset := vFileInfo.NextEntryOffset;

FFolderItemInfo.Name := WideCharLenToString(@vFileInfo^.FileName,vFileInfo^.FileNameLength); SetLength(FFolderItemInfo.Name,vFileInfo^.FileNameLength div 2); case vFileInfo^.Action of FILE_ACTION_ADDED : FFolderItemInfo.Action := faNew; FILE_ACTION_REMOVED : FFolderItemInfo.Action := faRemoved; FILE_ACTION_MODIFIED : FFolderItemInfo.Action := faModified; FILE_ACTION_RENAMED_OLD_NAME: FFolderItemInfo.Action := faRenamedOld; FILE_ACTION_RENAMED_NEW_NAME: FFolderItemInfo.Action := faRenamedNew; end; Synchronize(DoFolderItemChange); PByte(vFileInfo) := PByte(DWORD(vFileInfo) +

vOffset); until vOffset=0; end; end;finally TearDown;FreeMem(B,cBufSize); end;end;

procedure TFolderMonWorker.SetUp;var i: TChangeType;begin FFolder := CreateFile(PChar(Owner.Folder),FILE_LIST_DIRECTORY or GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,nil,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);

FMonFilter := 0; for i := Low(TChangeType) to High(TChangeType) do if i in Owner.MonitoredChanges then FMonFilter := FMonFilter or NOTIFY_FILTERS[i];end;

Conclusão

Essa foi a primeira parte do artigo, onde vimos a implementação da função do Windows ReadDirectoryChangesW, desempenhando um papel impor-tante nas notificações em tempo real sempre que um arquivo em uma área monitorada é alterado/incluído; podendo obter inclusive o nome do arquivo afetado; isso é crucial para o processo adotado de versionamento para o nosso componente recém-criado THVCheckVersion.

No próximo artigo vamos dar continuidade ao nosso desenvolvimento da solução de versionamento, focando nessa ideia e utilizando comparações entre linhas de código-fonte entre dois arquivos (original e arquivo alterado posterior), sendo que na verdade serão comparados os inteiros ao invés de linhas (através de tabelas de hashes), desenhando no evento OnDrawCell de uma TStringGrid os eventos desejados de alteração (definidos em TChangeKind = (ckNone, ckAdd, ckDelete, ckModify);

Page 25: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 25

Figura 03 – Tela do projeto Versionador, explicado na próxima edição, juntamente com os códigos-fonte do mesmo.

Desejo ao leitor boas leituras com este componente e que possa se divertir tanto quanto eu, adicionando e alterando suas funcionalidades. O código-fonte é free, juntamente com os programas de exemplo distribuídos. Um abraço a todos 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 26: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201426

Olá amigos do The Club, neste artigo irei apresentar uma maneira fácil de criar e customizar as caixas de diálogos no Delphi XE6. No Delphi já temos pronto diversos tipos de caixas de diálogo, como por exemplo: a “ShowMessage”, “Application.MessageBox” ou a “MessageDLG”. Todas elas

nos proporcionam alguns recursos interessantes, mas como todo programador, sempre sentimos a necessidade de implementação de novos recursos. Todo o funcionamento irá se basear na criação de um formulário padrão junto com uma classe, a qual irá montar toda a estrutura necessária.

Criando a Caixa de Mensagem

Clique em File/New/VCL Form – Delphi para criarmos um formulário desde o início. Sugiro alterar algumas propriedades deste formulário, de acordo com a tabela 01 abaixo.

Propriedades ValoresBorderStyle bsDialog

BorderIcons []

Caption Mensagem

ClientHeight 222

color clBtnFace

Font Calibri

Position poScreenCenterTabela 01: Propriedades do FrmMensagem.

Dentro deste mesmo formulário iremos adicionar 3 Panels, sendo: pnlIcones (Para agrupar os ícones utilizados), pnlMensagem (Para adicionar a mensagem informativa) e pnlBotoes (Para adicionar os botões OK, Sim e Não). Ver Imagem 01.

Delphi XE6 - Como criar uma caixa de diálogo personalizada

Imagem 01: Configurações do Formulário “FrmMensagem”.

Ver abaixo as tabelas com todas as configurações detalhadas.

Item (1) - pnlIcones:

Propriedades ValoresAlign alLeft

Alignment taLeftJustify

BevelOuter bvNone

Height 178

Width 70Tabela 02: Propriedade do pnlIcones.

Dentro do “pnlIcones” devemos inserir 5 componentes do Tipo “Timage” e na sequencia adicionar os principais ícones. Deveremos alterar a propriedade “Name” de todos para: imgDeletar, imgCuidado, imgQuestao, imgErro e Im-gInformacao. As propriedades de tamanho e largura deverão ser respeitadas de acordo com a tabela 03.

Page 27: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 27

Propriedades ValoresHeight 35

Width 50Tabela 03: propriedades dos “Timages”.

Item (2): pnlMensagem.

Propriedades ValoresAlign alClient

Alignment taCenter

BevelOuter bvNone

BorderWidth 10

Height 178

Width 280Tabela 03: Propriedade do pnlMensagem.

Já no pnlMensagem adicionaremos apenas um Label (lblMensagem) para a Mensagem Informativa.

Item (3): pnlBotoes

No último painel iremos inserir três BitBtn, sendo: Ok, Sim e Não. Ver Tabela 04.

Propriedades ValoresAlign alBottom

Alignment taCenter

BevelOuter bvLowered

Height 44

Width 350Tabela 04: Propriedade do pnlBotoes.

Segue também algumas configurações necessárias para realizar nos “BitBtns”.

Propriedades ValoresDefault True

Height 38

ModalResultr mrNo

Visible False

Width 75Tabela 05: Botão OK.

Propriedades ValoresCaption &Não

Height 38

ModalResultr mrNo

Visible False

Width 75Tabela 06: Botão Sim.

O Formulário “FrmMensagem” deverá ficar idêntico ao da Figura 02.

Figura 02: Formulário Finalizado.

Codificando o formulário “FrmMensagem”

É importante salientar que iremos utilizar uma “Class Funcion” para referenciar o método “Mensagem” (O qual irá criar nossa caixa de diálogo). Este tipo de classe não se faz necessário a criação de uma instância, ou seja, podemos apenas fazer a utilização direta do método em questão. Detalharei melhor a seguir.

O primeiro passo seria criar um Tipo (type) para armazenar os botões (Sim, Não, e Ok). Esta codificação normalmente se localiza logo acima do Tipo (TfrMensagem), a classe do formulário.

TypeTMeusBotoes=(mbSim,mbNao,mbOk);

Type TFrmMensagem = class(TForm)......

Criaremos também uma class function “Mensagem” como pública. Clas-ses deste tipo não necessitam de instância, que encaixam perfeitamente no nosso tipo de utilização. Temos três parâmetros, sendo respectivamente: O texto informativo que irá aparecer na caixa de mensagem, uma variável char que identifica o tipo da Mensagem e o Array do type TMeusBotoes (tem como tarefa criar as rotinas conforme os botões escolhidos.

Private

{ Private declarations }

Public

Page 28: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201428

{ Public declarations }

class function Mensagem(Texto: String; Tipo: Char; Botoes: array of TMeusBotoes): Boolean; end;

A constante “LEFTBUTTONS” irá permitir uma realocação dos botões (Sim, Não e Ok) no formulário pela propriedade “Left”. Já a constante ”TITULO” irá entitular a caixa de diálogo.

const

LEFTBUTTONS: array[0..2] of integer=(258,178,97); TITULO: String = ‘The Club’;

Var FrmMensagem: TFrmMensagem;

Implementation

{$R *.dfm}

class function TFrmMensagem.Mensagem(Texto: String; Tipo: Char; Botoes: array of TMeusBotoes): Boolean;var i: Integer; frm :TFrmMensagem;

begin frm := TFrmMensagem.Create(nil); try frm.lblMensagem.Caption := Texto; frm.Caption := TITULO; for i:=0 to Length(Botoes)-1 do begin case (Botoes[i]) of mbOk: begin frm.BtnOK.Visible := True; frm.BtnOK.Left := LEFTBUTTONS[i]; end; mbSim: begin

frm.btnSim.Visible := True; frm.btnSim.Left := LEFTBUTTONS[i]; end;

mbNao: begin frm.BtnNao.Visible := True; frm.BtnNao.Left := LEFTBUTTONS[i]; end;

else begin frm.BtnOK.Visible := True; frm.BtnOK.Left := LEFTBUTTONS[i]; end; end; end;

frm.imgInformacao.top := 4; frm.imgDeletar.top := 4; frm.imgQuestao.top := 4; frm.imgCuidado.top := 4; frm.imgErro.top := 4;

case (Tipo) of ‘I’: frm.imgInformacao.Visible := True; ‘D’: frm.imgDeletar.Visible := True; ‘Q’: frm.imgQuestao.Visible := True; ‘C’: frm.imgCuidado.Visible := True; ‘E’: frm.imgErro.Visible := True; else frm.imgInformacao.Visible := True; end; frm.ShowModal;

case (frm.ModalResult) ofmrOk,mrYes:result:=True; else result := False; end;finally if (frm<>nil) then FreeAndNil(frm); end;end;

Page 29: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 29

Iremos instanciar a classe “TfrmMensagem”, passando como parâmetro o “nil”. Logo em seguida faremos um “try/catch” para atribuir o título na propriedade Caption e a Mensagem Informativa passada por parâmetro no componente “lblMensagem”. Faremos um “Case” para receber o retorno do array “botões” para ir setando como Visível ou não e os realocando na tela conforme a propriedade “Left” (utilizada pela constante “LEFTBUTTONS”). Na próxima etapa do código, através da propriedade “TOP” dos componentes “TImage”, deixaremos as mesmas alinhadas logo no início do formulário. O parâmetro “tipo” irá nos orientar e habilitar qual imagem deverá ficar visível conforme a necessidade (I= Informativa, D= Deletar, Q= Questionamento, C=Cuidado, E=Erro). O método “frm.ModalResult” irá nos retornar como “true” ou “false” para tratarmos na função mais adiante. Para finalizar liberaremos o “frm” da memória através do método “FreeAndNil”.

Testando a Caixa de Diálogo

Para isto crie um projeto do inície e insira alguns botões, tais como: “Information, Question, Warning, Delete, Error e Sign Out”. Ver Lay-Out na Imagem 03.

Figura 03: Testando a caixa de diálogo.

Devemos declarar a unit “Umensagens”. O uso da classe “TfrmMensagem” é muito simples pelo fato de não precisarmos instanciar nenhum objeto. Devemos apenas passar como parâmetros os seguintes itens: O Texto, o Tipo e os botões.

uses Umensagens;

Exemplo de Mensagem do tipo Informativa.

procedure TForm2.Button1Click(Sender: TObject);begin TFrmMensagem.Mensagem(‘Esta é uma Mensagem de Information!’,’I’,[mbOk]);end;

Exemplo de Mensagem do tipo Conclusiva.

procedure TForm2.Button3Click(Sender: TObject);begin TFrmMensagem.Mensagem(‘Esta é uma Mensagem de Warning!’,’C’,[mbOk]);end;

Exemplo de Mensagem de Erro.

procedure TForm2.Button5Click(Sender: TObject);begin TFrmMensagem.Mensagem(‘Esta é uma Mensagem de Error!’,’E’,[mbOk]);end;

Todas as telas serão idênticas ao da Imagem 04.

Figura 04: Mensagem Informativa.

Quando necessitamos receber o retorno de nossa “class Funcion”, pode-mos seguir os exemplos a seguir.

Exemplo de Mensagem para Exclusão.

procedure TForm2.Button4Click(Sender: TObject);begin if (TFrmMensagem.Mensagem(‘Deseja excluir o registro?’,’D’,[mbSim,mbNao]))then TFrmMensagem.Mensagem(‘Você

Page 30: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro201430

[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

clicouemSIM!’,’I’,[mbOk]) else TFrmMensagem.Mensagem(‘Você clicouemNÃO!’,’I’,[mbOk]);end;

Exemplo de Mensagem do tipo Questionativa.

procedure TForm2.Button2Click(Sender: TObject);beginif (TFrmMensagem.Mensagem(‘Esta é uma Mensagem de Question!’,’Q’,[mbSim,mbNao]))thenTFrmMensagem.Mensagem(‘Você clicouemSIM!’,’I’,[mbOk]) else TFrmMensagem.Mensagem(‘Você clicou em NÃO!’,’I’,[mbOk]);end;

Outro Exemplo de Mensagem Questionativa, para encerramento da aplicação.

procedure TForm2.Button6Click(Sender: TObject);begin if (TFrmMensagem.

Mensagem(‘Deseja encerrar a aplicação?’,’Q’,[mbOK,mbNao]))then Application.Terminate;end;

Ressaltando que todas as telas serão idênticas ao da Imagem 05.

Figura 05: Mensagem Questionativa.

Conclusões

Neste mês procurei abordar um assunto solicitado em nosso suporte técnico. Todo projeto que desenvolvemos, sempre temos a necessidade de fazer o uso de caixas de diálogos. Procurei neste artigo criar uma classe bá-sica para personalização deste recurso.É Impostante lembrar que apesar de ser desenvolvido no Delphi XE6, foram testados nas versões anteriores com sucesso. Fica aí a dica, um forte abraço e até o mês que vem!

Page 31: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014 05

Page 32: The Club - megazinelayout bastante comum atualmente. Nele, temos um menu lateral com opções para acesso a telas (Figura 1). Figura 1. Projeto rodando Se quisermos mudar os valores

setembro2014