Este artigo foi traduzido por máquina.

Entrada baseada em tela

Teclas na tela personalizadas com o .NET Framework

Christopher Frenz

Baixar o exemplo de código

A necessidade de desenvolver aplicações que requerem entradas baseado em tela tem crescido de forma constante nos últimos anos. Os desenvolvedores têm tradicionalmente usado na tela os dados de entrada para permitir que indivíduos que não poderiam usar um teclado de computador inserir dados ou fazer escolhas, especialmente em aplicações de quiosque.

O rápido crescimento do Tablet PC e dispositivos de computação móvel faz na tela de entrada mais penetrante e mais útil do que nunca. Um não precisa olhar o passado uma lanchonete local ou o modo de transporte público para encontrar pessoas absortos no mais recente "app" para o seu telemóvel ou dispositivo de Tablet PC. Tendo em conta as expectativas para o crescimento contínuo do mercado de computação móvel, não é difícil imaginar que uma compreensão das metodologias na tela de entrada seria de grande utilidade para qualquer desenvolvedor.

Além disso, para complementar o mercado móvel, na tela teclados são também ficando mais populares em aplicações onde a segurança é fundamental, porque os dispositivos de entrada com base em tela podem ajudar a evitar que informações usuário sejam roubados usando keyloggers baseada em hardware. Por exemplo, corretoras estoque on-line, como TradeKing exigem que os usuários inserir todas as senhas usando um teclado virtual para ajudar a aumentar a segurança. Mas mesmo que na tela teclados podem ajudar a melhorar a segurança, eles têm seus próprios potenciais riscos a considerar. Enquanto na tela teclados atenuar o risco de qualquer keyloggers baseada em hardware, eles são ainda potencialmente suscetíveis a abordagens de log de entrada baseada em software, bem como a técnica muito mais comum de "ombro surf" para exibir os botões de entrada que um usuário pressiona. Por exemplo, um aplicativo usa vídeo capturado de uma pessoa digitando em um iPad para identificar quais teclas foram digitadas, alinhando a localização das teclas pressionadas com uma imagem do teclado iPad (ver onforb.es/oobLp2).

Algumas técnicas de atenuar a eficácia do ombro surf. Um dos mais comuns é uma constante randomização de teclas para evitar que o mapeamento de keypress capturados coordenadas para qualquer chave particular. Neste artigo, vou criar um teclado virtual que usa de aleatorização chave usando o Microsoft.NET Framework. O aplicativo permite que o teclado no ecrã para serem vinculadas a determinada appli­cação para que na tela de entrada é desejável. No entanto, este artigo descreve as técnicas necessárias para construir na tela teclado e o aplicativo de exemplo é projetado para ilustrar estas técnicas, não para fornecer um aplicativo totalmente indicados: teclado.

A tela teclado GUI

O primeiro passo é esquematizar o GUI, que inclui uma "chave" para cada letra do alfabeto e cada número (ver Figura 1). Antes de começar a arrastar controles para seu formulário, no entanto, existem algumas questões a serem consideradas. Na maior parte.NET aplicativos (e outros aplicativos também), sempre que você deseja que o usuário enviar entrada clicando em algo, o controle padrão para usar seria um botão. Mas você não pode usar um controle de botão em um teclado no ecrã porque em está sendo clicado, um controle button automaticamente ganha o foco do sistema operacional Windows. Porque a entrada do teclado destina-se a ir para o aplicativo de primeiro plano ativo (isto é, o aplicativo com o foco), na tela teclado nunca deve ganhar o foco do sistema operacional. Em vez de usar controles button para chaves, vou usar controles label em vez disso, pois oferecem suporte um evento Click como botões, mas ao contrário dos botões não são permitidos para obter o foco. Rótulos, portanto, fazem uma escolha ideal, sendo capaz de responder a cliques sem iniciar uma alteração no foco do aplicativo — com um pouco de extra de codificação que você verá na próxima seção. Para fins do aplicativo de exemplo, esses rótulos serão denominados Label1 através de Label36. Um textbox, TextBox1, também é criado para comparar entradas de usuário entradas no teclado no ecrã com aqueles que aparecem no aplicativo externo (consulte Figura 1).

The Design View of the On-Screen Keyboard GUI
Figura 1 O modo de Design do na tela teclado GUI

Ficar fora de foco

Embora usando um controle como um rótulo é necessário para evitar um aplicativo receber o foco do sistema operacional, não é suficiente por si só porque na tela o aplicativo de teclado também pode receber o foco quando o próprio formulário é carregado e quando o formulário ou qualquer controle no formulário é clicado pelo mouse. Para corrigir esta situação, eu preciso adicionar algum código adicional para a aplicação de teclado.

Em primeiro lugar, para impedir que o formulário obtenham o foco quando ele é carregado pela primeira vez, eu vou adicione o seguinte código (estou usando Visual Basic.LÍQUIDO) para o aplicativo:

Private Const WS_EX_NOACTIVATE As Integer = &H8000000
Protected Overrides ReadOnly Property CreateParams() As CreateParams
  Get
    CreateParams = MyBase.CreateParams
    CreateParams.ExStyle = CreateParams.ExStyle And WS_EX_NOACTIVATE
    Return CreateParams
  End Get
End Property

Esse código substitui a CreateParams Propriedade, que é usada na criação do objeto de formulário. Ao substituir essa propriedade com o estilo de janela WS_EX_NOACTIVATE, eu evitar que o formulário da vinda para o primeiro plano ao carregamento, o que significa que o carregamento na tela teclado não vai tirar o foco de qualquer outro aplicativo foi ativo no momento do lançamento. Uma vez que este código é posto em prática, é importante avançar assegurar que o aplicativo não é possível conseguir o foco por meio de um clique do mouse. Adicionar este código realiza que:

Private Const WM_MOUSEACTIVATE As Integer = &H21
Private Const MA_NOACTIVATE As Integer = &H3
Protected Overrides Sub WndProc(ByRef m As Message)
  If (m.Msg = WM_MOUSEACTIVATE) Then
      m.Result = MA_NOACTIVATE
    Else
      MyBase.WndProc(m)
    End If
End Sub

Esse código substitui a função WndProc do formulário, que usa o formulário para receber todas as entradas do usuário. A função de substituição intercepta as mensagens WM_MOUSEACTIVATE, que são enviadas quando uma janela inativa é clicada. Ele também garante que na tela aplicação teclado não ganha o foco como resultado de um clique do mouse, definindo o valor de retorno da função para MA_NOACTIVATE. A condição de "Else" deste código assegura que todas as outras mensagens de entrada de mouse são passadas, permitindo que o aplicativo para detectar rótulo clica sem nunca ganhar o foco do teclado no ecrã.

Adicionar a funcionalidade de teclado

Neste ponto, tenho uma GUI para o aplicativo e o código para que ele permaneça livre de foco. Agora é hora de adicionar a funcionalidade de teclado real. O primeiro bit essa funcionalidade criará uma subrotina (AssignKeys) para atribuir chaves aleatórias mas exclusivas para cada rótulo (ver Figura 2).

Figura 2 atribuir chaves aleatórias, exclusivas para cada controle Label

Private Sub AssignKeys()
  Dim Character() As Char =
    {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", _
     "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", _
     "A", "S", "D", "F", "G", "H", "J", "K", "L", "Z", _
     "X", "C", "V", "B", "N", "M"}
  Dim Keys(36) As Char
  Dim I, X As Integer
  Dim Rand As New Random()
  Dim Used(36) As Integer
  Dim Unique As Boolean = False
    Used(0) = -1
    For I = 0 To 35
      Unique = False
      X = Rand.Next(0, 36)
      If Character(X) <> " " Then
        Keys(I) = Character(X)
        Character(X) = " "
      Else
        Do Until Unique = True
          X = Rand.Next(0, 36)
          If Character(X) <> " " Then
            Keys(I) = Character(X)
            Character(X) = " "
            Unique = True
          End If
        Loop
        End If
  Next
    Label1.Text = Keys(0)
    Label2.Text = Keys(1)
    Label3.Text = Keys(2)
    Label4.Text = Keys(3)
    Label5.Text = Keys(4)
    Label6.Text = Keys(5)
    Label7.Text = Keys(6)
    Label8.Text = Keys(7)
    Label9.Text = Keys(8)
    Label10.Text = Keys(9)
    Label11.Text = Keys(10)
    Label12.Text = Keys(11)
    Label13.Text = Keys(12)
    Label14.Text = Keys(13)
    Label15.Text = Keys(14)
    Label16.Text = Keys(15)
    Label17.Text = Keys(16)
    Label18.Text = Keys(17)
    Label19.Text = Keys(18)
    Label20.Text = Keys(19)
    Label21.Text = Keys(20)
    Label22.Text = Keys(21)
    Label23.Text = Keys(22)
    Label24.Text = Keys(23)
    Label25.Text = Keys(24)
    Label26.Text = Keys(25)
    Label27.Text = Keys(26)
    Label28.Text = Keys(27)
    Label29.Text = Keys(28)
    Label30.Text = Keys(29)
    Label31.Text = Keys(30)
    Label32.Text = Keys(31)
    Label33.Text = Keys(32)
    Label34.Text = Keys(33)
    Label35.Text = Keys(34)
    Label36.Text = Keys(35)
  End Sub

A rotina na Figura 2 cria uma matriz (caracteres) que contém todos os caracteres alfanuméricos selecionados para aparecer no teclado e, em seguida, aplica-se o gerador de números aleatórios para selecionar um elemento aleatório desta matriz. Enquanto o elemento não foi previamente selecionado, o caractere armazenado em que determinado elemento da matriz é copiado para uma matriz chamada chaves. Esse processo se repete até que todos os 36 caracteres são atribuídos para a matriz de chaves, que aleatóriamente a localização de cada caractere na matriz. Uma vez que a matriz é randomizado, os elementos da matriz de chaves são atribuídos para a propriedade Text de cada rótulo para permitir que seus personagens atribuídas a ser exibido na tela. Esta sub-rotina AssignKeys denomina-se inicialmente na execução do evento Form_Load.

Agora que os personagens foram atribuídos para as respectivas chaves, preciso adicionar código que manipula conversão clica o mouse sobre o teclado virtual aplicativo para o equivalente de enviar um keypress para o aplicativo de destino. Para fazer isso, eu preciso fazer uso da API do user32. dll, que usa o Windows para lidar com muitas funções relacionadas com a interface do usuário, como manipulação de janela e outras funções de gerenciamento de janela. Para configurar o aplicativo para fazer corretamente usar essa funcionalidade API, vou acrescentar as seguintes instruções de importação de DLL para a classe de formulário:

<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function FindWindow(ByVal lpClassName As String, _
    ByVal lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As Boolean
End Function

O user32. dll API será usado toda vez que um evento Label_Click é lançado, porque cada caso se parecerá com o código em Figura 3.

Figura 3 usando o user32. dll API para eventos Label_Click

Private Sub Label1_Click(ByVal sender As System.Object,_
  ByVal e As System.EventArgs) Handles Label1.Click
  Dim X As Char
  X = CChar(Label1.Text)
  Dim theHandle As IntPtr
  theHandle = FindWindow(Nothing, "Untitled - Notepad")
  If theHandle <> IntPtr.Zero Then
    SetForegroundWindow(theHandle)
    SendKeys.Send(X)
  End If
  TextBox1.Text = TextBox1.Text & Label1.Text
  AssignKeys()
End Sub

Quando um evento de click rótulo surge, a variável "theHandle" é usada para armazenar o identificador de aplicação para o aplicativo para o qual na tela teclado vai enviar sua entrada. Neste caso, o identificador de aplicação foi definido como uma cópia recentemente carregada do bloco de notas porque é universalmente disponível em todos os sistemas Windows. Se o identificador de aplicação está presente atualmente no sistema, o aplicativo tendo esse identificador move (bloco de notas) para o primeiro plano e o caractere atribuído a esse rótulo é enviado para o aplicativo. A personagem também é acrescentada a qualquer texto encontrado dentro de textbox do aplicativo de teclado para demonstrar que os caracteres que aparecem no bloco de notas são os mesmos caracteres recebidos pelo próprio aplicativo de teclado. Como última etapa, a sub-rotina AssignKeys é chamada novamente para re-randomize as posições-chave e dificultar ainda mais o ombro surf. Este procedimento está ilustrado na Figura 4 e Figura 5, onde Figura 4 mostra uma versão recentemente carregado do aplicativo e Figura 5 demonstra na tela teclado e o bloco de notas após várias teclas pressionadas no teclado na tela.

A New Instance of the On-Screen Keyboard
Figura 4 nova instância do teclado no ecrã

The On-Screen Keyboard Sending Input to Notepad
Figura 5: O teclado no ecrã de envio de entrada para o bloco de notas

Segurança reforçada e portando móvel

Este artigo demonstrou o desenvolvimento de um teclado na tela usando o.NET Framework. Eu espero que forneceu alguns insights sobre como na tela teclados podem ser desenvolvidos para uso em melhorar a segurança de certos elementos de entrada de dados ou para uso em portar.Aplicativos NET para plataformas móveis.

Christopher M. Frenz é o autor dos livros programação, "Visual Basic e Visual Basic.NET para cientistas e engenheiros"(Apress, 2002) e"Análise Pro Perl"(Apress, 2005). Ele pode ser contatado pelo cfrenz@gmail.com.

Graças ao seguinte especialista técnico para revisão deste artigo: Robert Green