Desenvolvimento - Mobile

As funcionalidades esquecidas do .NET Compact Framework – Parte II (Controlando a Entrada de Dados)

Como bem sabemos, digitar textos em um celular não é uma tarefa das mais agradáveis. O pequeno teclado e as teclas que representam diferentes caracteres não foram criados para a entrada constante de dados. Nos Smartphones esse problema é minimizado devido a alguns esquemas de entrada inteligentes, sendo o mais popular o T9...

por José Antonio Leal de Farias



Introdução

Como bem sabemos, digitar textos em um celular não é uma tarefa das mais agradáveis. O pequeno teclado e as teclas que representam diferentes caracteres não foram criados para a entrada constante de dados.

Nos Smartphones esse problema é minimizado devido a alguns esquemas de entrada inteligentes, sendo o mais popular o T9, que “prediz” o texto sendo digitado pelo teclado.

Além disso, pode-se definir manualmente o formato de entrada numa certa caixa de texto. Se só vamos digitar números, fazemos com que o teclado “ecoe” apenas números, se vamos digitar um texto em maiúsculas, fazemos com que todas as letras apareçam maiúsculas, e assim por diante.

Com todas essas facilidades, qual o problema então com a entrada de dados no Smartphone? O problema não é o celular em si, mas sim o Compact Framework. Simplesmente não há como indicar, programaticamente, que certo TextBox irá conter apenas números, outro só letras e assim por diante, obrigando o usuário a fazer uma ginástica com os dedos ainda maior e tornando a usabilidade da aplicação extremamente deficitária.

Imagine uma aplicação de força de venda, como abaixo. Para o usuário digitar a quantidade de itens no formulário ele teria de pressionar bem mais teclas do que simplesmente digitar ‘1’ e ‘2’, já que o modo default de entrada é texto.

Mais uma vez vamos resolver de vez mais essa funcionalidade “esquecida” do Compact Framework. Vamos lá.

A Solução

Novamente vamos dar uma olhada na API do Smartphone. Como sempre devemos inspecionar a documentação disponível em C++ para ver como é possível fazer o que desejamos.

Em C++ essa é uma operação bastante simples. Basta setar o parâmetro GWL_STYLE de um controle, especificando o estilo (neste caso, o modo de entrada), de um TextBox. Então precisamos portar as constantes que precisamos para o C#. Isso fica como abaixo:

private const int GWL_STYLE = (-16);

private const int IM_UPPERCASE = 0x0008;

private const int IM_LOWERCASE = 0x0010;

private const int IM_NUMBER = 0x2000;

Setar um parâmetro do controle não é tão simples quanto em .NET. Precisamos usar uma função para isso, chama SetWindowLong. Novamente, convertendo-a para C# temos:

[DllImport ("coredll.dll")]

private extern static int SetWindowLong(IntPtr Hwnd, int Index, int NewIndex);

Isso é o que precisamos por enquanto. Infelizmente não basta apenas chamar essa função para que tudo funcione corretamente.

Quando usamos a função SetWindowLong especificando um certo parâmetro para o GWL_STYLE, podemos estar modificando importantes parâmetros setados previamente pelo Compact Framework neste controle. Então, é melhor setar um valor que combine o nosso parâmetro de entrada de dados com os parâmetros setados anteriormente pelo Compact Framework.

Como saber os parâmetros setados pelo Compact Framework? Isso é trabalho para a função GetWindowLong:

[DllImport("coredll.dll")]

private extern static int GetWindowLong(IntPtr Hwnd, int Index);

Tudo bem, mas ainda tem mais um problema. O primeiro parâmetro dessas funções pede o handle da janela. Para quem nunca usou a API do Windows, pode-se dizer que este handle indentifica uma janela (ou controle) na aplicação.

No Framework .NET, existe um atributo Handle dos objetos do Windows.Forms que retorna este valor. Inexplicavelmente esta propriedade não existe no Compact Framework, então temos de fazer um artifício para obtê-la, como abaixo:

[DllImport("coredll.dll")]

private extern static IntPtr GetCapture();

textBox1.Capture = true;

IntPtr hwnd = GetCapture();

textBox1.Capture = false;

A abordagem aqui é a seguinte. Existe uma função na API que retorna o handle da janela que “capturou” o mouse. Então fazemos o TextBox capturar o mouse, obtemos o handle da janela que capturou o mouse (TextBox) e depois “soltamos” o mouse.

Antes que você pergunte: “mouse” no Smartphone?? Não me pergunte. Apenas funciona.

Com o handle já recuperado, basta então fazer algo como:

int previousStyle = GetWindowLong(hwnd, GWL_STYLE);

SetWindowLong(hwnd, GWL_STYLE, previousStyle |IM_NUMBER);

E pronto. Nesse momento, o TextBox1 irá aceitar apenas números, facilitando muito a entrada de valores numéricos.

Conclusão

Meus leitores mais espertos já perceberam que o ideal seria criar um controle derivado do TextBox e usá-lo em todas as nossas aplicações. Não apenas o modo de entrada pode ser especificado nesse controle, mas outras coisas “esquecidas” do Compact Framework podem ser especificadas usando procedimentos parecidos, mas isso já é assunto para outro artigo. O importante é que o conhecimento passado aqui permite que o leitor explore um pouco mais a API do PocketPC e do Smartphone e use esse conhecimento para oferecer maiores recursos nas suas aplicações.

Até a próxima!
José Antonio Leal de Farias

José Antonio Leal de Farias - Bacharel em ciências da computação pela UFCG e atualmente é Gerente de Pesquisa e Desenvolvimento da Light Infocon S.A. É programador profissional nas linguagens C++ e C#, líder do grupo de usuários CGSharp e adora Smartphones!
Veja seu blog em
http://thespoke.net/blogs/jalf/default.aspx.