Interface Visual do AdvPL – Parte 03

Introdução

Continuando a sequência de Interface Visual do AdvPL, vamos entender um pouco mais sobre como funcionam alguns componentes básicos para permitir entrada de dados do usuário, e na sequência como persistir e consultar estes dados em uma tabela.

Caixa de Diálogo ou Janela MODAL

Quando criamos em AdvPL uma caixa de diálogo, o acionamento dos controles de interface estão restritos à janela ativa. E, não é possível ativar mais de uma janela ao mesmo tempo. A Interface MDI do AdvPL não se encaixa neste conceito, pois cada ABA da MDI possui um processo separado, veremos esta interface em mais detalhes posteriormente. Via de regra, somente temos uma Janela ou Diálogo ativo ao mesmo tempo.

A criação da janela de diálogo é acompanhada da criação dos componentes de interface que permitirão ao usuário interagir com a interface, e por fim ativamos o diálogo (comando ACTIVATE DIALOG, por exemplo), e ao tornarmos ele ativo, o programa aguarda a interação do usuário com os componentes de interface, disparando ações pré-definidas em Blocos de Código (Code-Blocks).

Criando uma janela para entrada de dados

Imagine que você quer perguntar ao usuário, qual é o seu nome. Existem várias formas de se fazer isso. Uma das formas mais simples, e inclusive reutilizável, é criar uma janela de diálogo, colocando um objeto do tipo GET, associado a uma variável de memória, que será preenchida com o texto que o usuário digitou, seguido de pelo menos dois botões: Um para confirmar a entrada, e outro para cancelar. Vamos ao exemplo:

#include 'protheus.ch'
User Function TstNome()
Local cNome 
cNome := GetNome("Insira seu nome",50,"!@")
If empty(cNome)
   MsgStop("Nenhum nome foi digitado","Nome Digitado")
Else
   MsgInfo("["+cNome+"]","Nome Digitado")
Endif
Return

/*
Funcao para perguntar um nome
Parâmetros	cTitulo = Titulo da Pergunta 
		nTam = Tamanho máximo da string de retorno \
		cPicture = Máscara de entrada de dados para o objeto GET 
Retorno		String vazia :"Nenhum nome digitado ou o duálogo 
		foi encerrado ou cancelado
*/

STATIC Function GetNome(cTitulo,nTam,cPicture)
Local oDlg
Local cGetVar := space(nTam)
Local oGet
Local oBtn1,oBtn2
Local lOk := .F. 

DEFINE DIALOG oDlg TITLE (cTitulo) ;
    FROM 0,0 TO 100,500 ;      
    COLOR CLR_BLACK, CLR_HBLUE PIXEL

@ 05,05 GET oGet VAR cGetVar  PICTURE (cPicture) 
        SIZE (nTam*4),12 OF oDlg PIXEL 

@ 25,05  BUTTON oBtn1 PROMPT "Confirmar" SIZE 40,15 ; 
         ACTION (lOk := .T. , oDlg:End()) OF oDlg PIXEL 

@ 25,50  BUTTON oBtn2 PROMPT "Voltar" SIZE 40,15 ; 
         ACTION (oDlg:End()) OF oDlg PIXEL 

ACTIVATE DIALOG oDlg CENTER

If !lOk
   cGetVar := space(nTam)
Endif

Return cGetVar

Detalhes do Exemplo

  1. Declaramos todas as variáveis a serem usadas no exemplo como “Local”
  2. Antes de ativar a Dialog criada, adicionamos nela todos os componentes visuais.
  3. Criamos o objeto do tipo “GET” informando a variável local “cGetVar“, que vai conter o valor digitado pelo usuário na interface.
  4. O programa vai permanecer em modo de interação com a interface enquanto o ACTIVATE DIALOG estiver em execução e a janela estiver aberta. Ao fechar a janela, a execução do programa continua.
  5. OS botões criados com as ações para confirmar ou para voltar, sempre chamam a finalização ou fechamento da janela de diálogo (oDlg:End), porém o botão de confirmação seta o valor da variável bOk para .T. (Verdadeiro) antes de fechar a janela.
  6. Caso o usuário não finalize a janela através do botão “Confirmar”, isto é, o usuário clicou no botão “Voltar“, ou fechou a janela, a variável bOk será .F. — o valor originalmente declarado.
  7. Após o fechamento da janela, verificamos qual o valor de bOk, e se o mesmo estiver falso, a variável de memória é limpa antes de ser retornada

Executando o programa

Após compilar o fonte, podemos executar o exemplo acima direto pelo SmartClient, chamando a função U_TstNome. Deverá ser apresentada uma tela parecida com a tela abaixo:

TstName

Após preencher o campo e clicar no botão “Confirmar”, será mostrada a mensagem informativa com o conteúdo digitado:

SeuNome

No exemplo proposto, usamos o nome obtido na interface após o fechamento da janela ou diálogo. Porém, seria possível usar o nome digitado com a interface aberta ? Sim, é possível. Vamos acrescentar mais um botão no exemplo acima, imediatamente antes da instrução de ativação do diálogo:

@ 25,95 BUTTON oBtn3 PROMPT "Mostrar" SIZE 40,15 ; 
   ACTION (MsgInfo("["+cGetVar+"]","Mostrando o Nome")) OF oDlg PIXEL 

ACTIVATE DIALOG oDlg CENTER

Agora, vamos ver o que acontece quando apertamos o botão quando digitamos algum conteúdo no campo e pressionamos o botão “Mostrar” ?

SeuNome2

COMO ASSIM ?

Até pouco tempo atrás, eu ainda não tinha entendido COMO isso poderia ser possível… Afinal, quando o botão “Mostrar” foi criado, a variável a ser mostrada (cGetVar) , além de ser uma variável de escopo LOCAL, estava com o seu conteúdo preenchido com espaços em branco! Como é que a ação do botão, que eu apertei depois de ter digitado no GET o texto “seu nome”, fez o conteúdo atual da variável parar na tela, se o botão foi criado ANTES de eu digitar esse conteúdo?

No próprio BLOG têm a resposta — no post feito sobre Codeblocks — vide links de referência no final do post — leia a parte do Exemplo 05: O uso de uma variável local dentro de um Codeblock leva no bloco de código uma referência dessa variável. Logo, mesmo que o botão tenha sido criado no momento que a variável estava preenchida apenas com espaços em branco, no momento que tiramos o foco do componente GET, usando ENTER, TAB ou mesmo clicando em um dos botões, o valor da variável local cVarGet é atualizado, e ao clicarmos no botão “Mostrar“,  a chamada da função MsgInfo() recebe o conteúdo atualizado da variável cVarGet.

COMO ASSIM , QUE CODEBLOCK ?

Isso mesmo, que Codeblock ? Ao criarmos o botão “Mostrar“, a ação a ser executada foi passada praticamente como uma string literal, inclusive ela nem precisaria estar cercada entre parênteses (força do hábito). Exatamente neste ponto existe uma declaração implícita de Codeblock, relacionada ao comando @ … BUTTON. Quando usamos diretamente a classe visual tButton do AdvPL, deve ser informado um Codeblock como ação do Botão. O que muda quando usamos diretamente a instrução @ … BUTTON, é que a expressão digitada no ACTION do botão é automaticamente declarada como um Codeblock. 

Por exemplo, para informar explicitamente um ACTION usando um CodeBlock, basta colocar  uma abertura de chave e dois pipes “{||”  e um fechamento de chave “}” englobando a expressão informada no ACTION. Por exemplo:

ACTION {|| MsgInfo(cGetVar,"Mostrando o Nome") } OF ...

Agora, quando nós não fazemos isso, e estamos usando o comando @ … BUTTON , a expressão de ACTION informada, caso não seja identificada como CodeBlock, é internamente declarada como Codeblock.

Classes de Interface encapsuladas em comandos

A documentação dos componentes e classes visuais do AdvPL documenta diretamente a classe do componente, você usa a classe diretamente no código fonte. Porém, devido ao grande número de parâmetros da classe, fica mais difícil de programar, além de dificultar a legibilidade do código. Uma vírgula a mais ou a menos, e você pode achar que está informando um CodeBlock de pré-validação do componente, quando na verdade uma vírgula a mais passou o argumento para o próximo parâmetro, que também era um Codeblock, mas este era executado na saída do componente, e não na entrada.

Os comandos ligados a interface visual do AdvPL já eram usados desde antes do Protheus, a transformação de um comando para a chamada direta da classe é feita por diretivas #command / #xcommand declaradas nos INCLUDES do Protheus. Vários comandos de interface visual estão documentados na TDN, veja nos links de referência no final do post. Existem vários comandos de interface documentados, porém a documentação os referencia como “Funções”.

Conclusão

Com este post, abrimos caminho para a utilização de componentes de interface e entrada de valores fornecidos pelo usuário. Era exatamente isso que faltava para darmos o próximo passo, um exemplo de CRUD — ou cadastro básico — em AdvPL, utilizando as funções básicas da linguagem, em breve no “Tudo em AdvPL” 😉

Desejo novamente a todos TERABYTES de sucesso !!!! 

Referências

 

 

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s