
Introdução
Ao desenvolvermos aplicações comerciais, é comum utilizarmos mecanismos de controle de acesso ao sistema através de autenticação do usuário. Esta autenticação, é feita normalmente através de nome de usuário e senha, previamente cadastrados em uma base de dados.
Assim como nas aplicações para computadores, em aplicações para PDAs também é uma boa prática utilizar máscaras para esconder a senha no momento da digitação, mostrando um caracter escolhido, como por exemplo o "*", utilizado na maioria dos casos.
O controle to tipo "caixa de texto" nativo do Palm OS, não oferece este recurso de máscara, e para piorar, não oferece eventos do tipo KeyDown ou KeyPress, para que fosse possível capturar os caracteres antes de eles aparecerem para o usuário e efetuar a substituição. Dessa forma, resta-nos apenas uma última alternativa: Utilizar uma fonte customizada.
Conceito
O Palm OS nos possibilita utilizar diferentes fontes de letra nas caixas de texto e até mesmo em outros controles do sistema operacional. Através de algumas funções da API, podemos alterar a fonte apenas dos controles que desejamos, sem interferir em outros controles.
As fontes de letra, possuem em geral 256 caracteres, obedecendo a tabela ASCII (do caracter 0 (zero) até o caracter 255 (duzentos e cinquenta e cinco)), assim, tudo o que temos de fazer, é criar uma fonte customizada, com 256 caracteres, onde todos os caracteres são desenhados com um único caracter específico, como o "*", por exemplo.
Criando a Fonte Customizada
Existem diversas ferramentas que permitem a criação de fontes customizadas para Palm OS, e uma das ferramentas mais utilizadas (e gratuita) é a xFont, utilizada neste exemplo. Caso não possua a xFont, faça o download na seção de downloads do PDAExpert
Crie uma nova fonte com o xFont, desenhe o caracter que deseja que apareça para seu usuário, e repita o desenho em todos os 256 caracteres da fonte utilizando os recursos de copiar e colar do xFont. Se preferir, pode importar qualquer uma das fontes existentes no Windows, escolher o caracter desejado e novamente utilizar os recursos copiar e colar do xFont, para criar as réplicas do desenho.

Com os 256 caracteres da fonte definidos, salve seu arquivo de fonte customizada em uma pasta de seu computador. O arquivo gerado terá a extensão ".pfn", e neste exemplo, o nome do arquivo é "Password.pfn".
Adicionando a fonte no projeto
Para adicionar esta fonte customizada em nosso projeto HB++, ela precisa ser compilada em um resource binário, através do compilador de resources PilRC. Caso não possua o PilRC, faça o download na seção de downloads do PDAExpert.
Para que o PilRC possa gerar nosso resource binário, precisamos criar um pequeno arquivo texto definindo o ID da fonte customizada e informar o caminho do arquivo ".pfn". Utilize seu editor de textos favorito e crie um arquivo chamado, por exemplo, "Password.rcp", com o seguinte conteúdo:

FONT ID 1 FONTID 128 "Password.pfn"
O próximo passo, é compilar este arquivo "Password.rcp" e gerar o resource binário, que será adicionado ao nosso projeto. A compilação é feita via linha de comando, bastando executar o compilador e informar o nome do arquivo com as definições:

PilRC Password.rcp
O PilRC irá gerar um arquivo com extensão .bin, com o nome começado por "NFNT". Este é o arquivo de resource que precisamos adicionar ao projeto. Assim, abra a aplicação no ambiente do Handheld Basic, adicionar este arquivo na pasta "Binary Resources" e compilar nossa aplicação.

Importante:
1-) Este exemplo assume que o arquivo gerado pelo xFont (.pfn) está na mesma pasta do arquivo ".rcp". Caso o arquivo ".pfn" esteja em uma pasta diferente, é necesário informar o caminho completo deste arquivo, utilizando-se o caracter "\" (barra invertida) duplicado, como por exemplo:
FONT ID 1 FONTID 128 "C:\\Sistemas\\MeuSistema\\Arquivos\\Password.pfn"
2-) O FONTID deve ser sempre um numero igual ou maior que 128, pois os números menores que 128 são reservados para fontes já existentes no sistema operacional Palm OS.
3-) Podemos compilar diversas fontes customizadas em um único arquivo binário de resource, basta definir IDs diferentes para cada uma, e informar os arquivos correspondentes, como por exemplo:
FONT ID 1 FONTID 128 "Password.pfn" FONT ID 2 FONTID 129 "Arial.pfn" FONT ID 3 FONTID 130 "Verdana.pfn" FONT ID 4 FONTID 131 "Tahoma.pfn"
Programação
Com a fonte compilada em um resource binário e adicionada em nosso projeto. Precisamos carregá-la na memória antes da utilização, e definir quais controles irão utilizar a fonte customizada. O Palm OS possui uma função API chamada FntDefineFont, responsável em carregar fontes em memória a partir do ID e do arquivo de resource. Assim, o primeiro passo é criar a declaração da função API em um módulo do projeto:
'Declaração da API FntDefineFont, responsável em carregar a fontes customizadas em memória Public Declare Function FntDefineFont(ByVal fontId As Byte, ByVal fontPtr as Long) As Integer Trap &HA321
Em seguida, no formulário onde a fonte será utilizada, declaramos as variáveis que serão utilizadas para acessar o arquivo de resource a partir de nossa aplicação:
'Código de identificação de fonte customizada 'Nota: hbFontCustomBase é igual a 128 Protected Const fntPasswordFontID As Integer = hbFontCustomBase 'Variáveis de acesso à fonte customizada Protected m_passwordFontRes As StreamMemory Protected m_passwordFontPtr As Long
Com as variáveis de acesso declaradas no formulário, devemos carregar a fonte em memória no evento Form_Load, que é o evento executado antes do formulário ser mostrado na tela.
Private Sub Form_Load()
'Obtém o resource da fonte customizada
Set m_passwordFontRes = App.Resource("NFNT", 1)
'Trava o rssource e obtém um ponteiro de acesso protegido
m_passwordFontPtr = Lock(m_passwordFontRes)
Dim lErro As Long
'Carrega a fonte em memória para ser utilizada
lErro = FntDefineFont(fntPasswordFontID, m_passwordFontPtr)
'Se conseguiu carregar a fonte, lErro é igual a zero
If lErro = 0 Then
txtSenha.Font = fntPasswordFontID
Else
'Não conseguiu carregar a fonte...
'Libera o ponteiro de acesso
If Not m_passwordFontRes Is Nothing Then
Unlock(m_passwordFontRes)
End If
'Libera a memória utilizada
Set m_passwordFontRes = Nothing
'Mostra mensagem de erro
MsgBox "Não foi possível carregar a fonte customizada", hbMsgBoxError
End If
'Define o cursor de foco na caixa
'de texto do nome do usuário
Set Focus = txtUsuario
End Sub
A associação da fonte customizada ao controle de caixa de texto é feita através da propriedade Font da caixa de texto. No exemplo, o código txtSenha.Font = fntPasswordFontID altera o valor da propriedade Font para 128, que corresponde ao ID da fonte customizada adicionada ao projeto.
Ao deixarmos de utilizar a fonte, precisamos liberar a memória por ela utilizada. Assim, no evento Form_Unload, evento executado apenas quando o formulário for fechado, efetuamos a liberação da memória:
Private Sub Form_Unload()
'Formulário está sendo fechado...
'Libera o ponteiro de acesso.
If Not m_passwordFontRes Is Nothing Then
Unlock(m_passwordFontRes)
End If
'Libera a memória utilizada
Set m_passwordFontRes = Nothing
End Sub
O resultado, é uma caixa de texto com máscara de senha, que impede que os caracteres digitados apareçam na caixa de texto.
Solução Alternativa Utilizando o Evento Form_KeyPress
Existe uma solução alternativa à utilização de fontes customizadas, adotada por alguns desenvolvedores, e que de certa forma produz um efeito semelhante, embora possua alguns pontos negativos. Como apontado no inicio do artigo, o controle to tipo "caixa de texto" nativo do Palm OS, não oferece eventos do tipo KeyDown ou KeyPress, para que fosse possível capturar os caracteres antes de eles aparecerem para o usuário e efetuar a substituição. No entanto, o formulário em si possui um evento KeyPress, onde são capturados todos os caracteres digitados em qualquer controle deste formulário, permitindo, então, controlar os caracteres que aparecem para o usuário. Veja este exemplo:
Private Sub Form_KeyPress(ByRef iChar As Integer, ByRef iKeyCode As Integer, ...)
'Verifica se o foco (cursor) está na caixa de texto da senha
If Me.Focus Is Control(txtSenha) Then
'Verifica se o caracter digitado está na faixa a...z, A...Z
If iChar >= 32 And iChar <= 128 Then
'Armazena o caracter digitado na propriedade Tag da caixa de texto
txtSenha.Tag = txtSenha.Tag & Chr(iChar)
'Cancela a exibição do caracter para o usuário
bForward = False
'Varifica se o caracter digitado é o backspace
ElseIf iChar = 8 And Len(txtSenha.Tag) > 0 Then
'Simula um backspace, apagando o ultimo caracter digitado
txtSenha.Tag = Left(txtSenha.Tag, Len(txtSenha.Tag) -1)
'Cancela a exibição do caracter para o usuário
bForward = False
End If
'Mostra o caracter "*" de acordo com a quantidade
'de caracteres digitados pelo usuário
txtSenha.Text = String(Len(txtSenha.Tag), "*")
End If
End Sub
Embora aparentemente o exemplo acima produza os mesmos efeitos da utilização de uma fonte customizada, ele apresenta pelo menos dois pontos negativos:
- Mudança de Comportamento da Caixa de Texto - A propriedade
Textda caixa de texto perde sua funcionalidade padrão, pois ela não mais conterá os caracteres digitados pelo usuário, e sim, o caracter utilizado como máscara. Neste exemplo, a propriedadeTextpossuirá diversos caracteres "*", apenas. A senha real precisa ser armazenada em outro lugar do programa, como por exemplo na propriedadeTag, como no exemplo de código acima, ou em uma variável do formulário. - Não Funciona com o Teclado Virtual - Uma vez que a caixa de texto perde seu comportamento padrão, o teclado virtual não consegue detectar o texto digitado pelo usuário, e mostra o conteúdo real da caixa de texto, composto por diversos caracteres "*", e se o usuário digitar outros caracteres com o teclado virtual, estes não serão substituidos, pois o evento
KeyPressnão é executado durante a exibição do teclado virtual.
Pelos motivos descritos acima, esta solução alternativa utilizando o evento KeyPress do formulário, não é considerada a melhor solução, devendo o desenvolvedor optar pela utilização de uma fonte customizada, sempre que possível.
Histórico
- 09/05/2007 - Primeira versão deste artigo.
- 08/07/2007 - Inclusão de solução alternativa, utilizando o evento
Form_KeyPress.
Agradecimentos à Ana Maria pela sugestão da solução alternativa, utilizando o evento KeyPress do formulário.
Sobre o Autor
Caio Proiete é Arquiteto de Soluções, especialista em desenvolvimento de softwares para PDAs e telefones celulares, principalmente nas plataformas Palm OS, Windows Mobile e Symbian OS.
Atualmente suas principais ferramentas/tecnologias de trabalho incluem CodeWarrior C++, Handheld Basic, eMbedded Visual C++, .NET Compact Framework, C# .NET, e Carbide.c++.
Possui extensa experiência em arquitetura e desenvolvimento de sistemas baseados em web e smart-clients, gerenciamento de projetos e treinamento, e atua também como instrutor oficial Microsoft em centros de treinamentos (CLPS), e é detentor das seguintes certificações:
- MCT - Microsoft Certified Trainer;
- MCSD - Microsoft Certified Solution Developer;
- MCDBA - Microsoft Certified Database Administrator;
- MCAD .NET - Microsoft Certified Application Developer;
- MCSD .NET - Microsoft Certified Solution Developer for .NET;
- MCTS - Microsoft Certified Technology Specialist for Windows Mobile.
Veja o todos os artigos publicados por Caio Proiete no PDAExpert.
Artigos Relacionados
3 Comentários »
Comentários via RSS TrackBack URI
-
Rafael - TreoClub em 17/07/2007 12:53
Caio, parabéns pelas matérias. Abraço !
-
Rodrigo Kravetz de Oliveira em 08/08/2007 17:45
Sua metodologia de ensino é muito boa. Parabéns.
O artigo é agradável e o aprendizado é fácil.
Digno de um instrutor MS. -
Caio Proiete em 08/08/2007 18:41
Obrigado pelos elogios, Rafael e Rodrigo.
Estou me esforçando para escrever cada vez mais e melhor.Abraços,
Caio Proiete


Envie seu comentário
ATENÇÃO: A área de comentários deve ser utilizada apenas para dúvidas sobre este artigo. Para dúvidas não relacionadas a este artigo, utilize o Fórum PDAExpert.net.