基于屏幕的输入

利用 .NET Framework 自定义屏幕键盘

Christopher Frenz

下载代码示例

近年来稳步增长需要开发的应用程序需要基于屏幕的投入。 开发人员一直使用屏幕上让人无法使用电脑键盘输入的数据输入数据或做出的选择,尤其是在 kiosk 应用程序。

平板电脑和移动计算设备的快速增长使屏幕上输入更普遍和有用比以往任何时候。 一个不需要看过去的咖啡馆或者找人全神贯注在最新的"应用程序"中为他们的移动电话或平板电脑设备的公共交通模式。 鉴于对在移动计算市场持续增长的预期,不难想象理解的屏幕上输入方法将对任何开发人员很有益处。

此外,在手机市场,屏幕键盘也获得更受欢迎,在应用程序中在安全性至关重要的因为基于屏幕的输入的设备可以帮助防止用户信息被盗使用基于硬件的击键记录程序。 网上股票经纪公司,如 TradeKing 为例,要求用户输入所有密码使用屏幕键盘来帮助提高安全性。 不过,即使屏幕键盘可以帮助提高安全性,他们有自己考虑的潜在风险。 屏幕键盘减少任何基于硬件的击键记录程序的风险,但它们仍然可能容易基于软件的输入日志记录方法,以及更为常见技术"肩冲浪"以查看用户按输入按钮。 例如,一个应用程序中使用捕捉到的视频,一个人到 iPad 打字的标识哪些键输入的对齐的图像的 iPad 键盘按下的键的位置 (请参见 onforb.es/oobLp2)。

一些技术减轻肩冲浪的成效。 一个最常见的是不断的随机化的项,以防止任何特定的键来捕获的 keypress 坐标的映射。 在本文中,我将创建使用 Microsoft 的用途主要随机化的屏幕键盘。NET 框架。 应用程序将允许屏幕键盘都链接到特定的应用­屏幕上,输入是可取的阳离子。 然而,这篇文章介绍了生成所需的技术屏幕键盘和示例应用程序为了说明这些技术,不是要提供一个功能全面的键盘应用程序。

屏幕键盘图形用户界面

每个字母的字母表和每个号码的第一步铺设 GUI 上,其中包括一把"钥匙"(请参见图 1)。 在开始拖动到窗体上的控件之前,然而,有需要考虑的几个问题。 在大多数。网络应用程序 (和以及其他应用程序),每当您希望用户提交输入通过点击要使用的标准控件的东西,将一个按钮。 您不能使用的按钮控件,但因为一个按钮控件上单击,将自动获得焦点的 Windows 操作系统的屏幕键盘。 因为键盘输入打算去主动前台应用程序 (也就是说,应用焦点),屏幕键盘应该永远不会获得操作系统的焦点。 而不是使用按钮控件的密钥,我就改用标签控件,因为它们支持的 Click 事件,如按钮,但不像按钮不被允许获得焦点。 标签,因此使一个理想的选择,能够响应单击而不启动应用焦点的变化 — 带着一些额外的编码,您将看到下一节。 示例应用程序而言,这些标签将命名通过 Label36 label1 的标签。 比较用户输入,输入到文本框中,TextBox1,还会创建与外部应用程序中出现的屏幕键盘 (请参见图 1)。

The Design View of the On-Screen Keyboard GUI
图 1 设计视图的屏幕键盘图形用户界面

留出的焦点

虽然使用控件,如标签是要避免导致应用程序接收焦点的操作系统,它是不够本身因为屏幕键盘应用程序还可以接收焦点时加载窗体本身和鼠标单击窗体或窗体上的任何控件时。 为了纠正这种情况下,我需要一些额外的代码添加到键盘应用。

首先,要防止窗体获得焦点,它首次加载时,会添加下面的代码 (我使用 Visual Basic。净) 应用程序:

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

此代码将覆盖表单的 CreateParams 属性,用于创建窗体对象。 通过重写此属性为 WS_EX_NOACTIVATE 窗口样式,我阻止表单来加载,这意味着该加载时前台屏幕键盘不会把焦点从任何其他应用程序在启动时处于活动状态。 此代码到位,一旦,重要的是下一步确保应用程序不能实现通过鼠标单击的焦点。 添加此代码来实现的:

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

此代码将窗体的 WndProc 函数,它接收所有用户输入的窗体使用重写。 重写函数截获 WM_MOUSEACTIVATE 消息,非活动窗口上单击时发送。 它还能确保屏幕键盘应用不通过函数返回值设置为 MA_NOACTIVATE 获得焦点,鼠标点击的结果。 此代码"Else"条件确保所有其他鼠标输入的消息都变通过,从而使屏幕键盘应用检测标签,单击没有过获得焦点。

添加键盘功能

在这一点上,我有一个 GUI 应用程序和代码以确保它保持无焦点。 它现在是时候添加实际键盘功能。 此功能的第一位将创建要分配给每个标签的随机但唯一键的子例程 (AssignKeys) (请参见图 2)。

图 2 为每个标签控件分配随机的唯一键

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

在该例程图 2 创建的数组 (字符),其中包含所有选定要在键盘上显示的字母数字字符,然后应用随机数生成器选择随机的元素,从该数组。 只要该元素没有了以前的选择,存储在该特定元素的数组中的字符复制到数组称为键。 重复此过程,直到所有 36 字符分配到键数组中,随机在数组中的每个字符的位置。 数组随机的一旦键数组的元素分配给每个标签的 Text 属性,使其赋值的字符将显示在屏幕上。 此 AssignKeys 子例程最初呼吁执行 Form_Load 事件的影响。

现在,字符被指派到他们各自的键,我需要添加代码来处理转换鼠标点击屏幕键盘,相当于将按键发送到目标应用程序的应用。 为此,我要利用 user32.dll API,Windows 用来处理许多 UI 相关的功能,如窗口处理和其他窗口管理功能。 要正确设置应用程序使用此 API 的功能,会添加窗体类的 DLL 导入下列语句:

<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

User32.dll API 将使用每次启动时的 Label_Click 事件,因为每个此类事件中的代码类似于图 3

图 3 user32.dll API 使用 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

标签的 click 事件时,"theHandle"变量用于存储的应用程序的应用程序句柄屏幕键盘将要发送其输入。 在这种情况下,应用的句柄被设置为新鲜加载副本记事本,因为它是普遍适用于所有的 Windows 系统。 如果当前存在于系统中应用的句柄,应用程序承载该句柄 (记事本) 移动到前台和分配给该标签的字符发送到应用程序。 字符也会附加到任何发现表明在记事本中显示的字符是收到键盘应用程序本身的相同字符键盘应用程序的文本框内的文本。 作为最后一步是 AssignKeys 子例程又称 re-randomize 的重要位置,并使肩冲浪更难。 此过程所示图 4图 5,其中 图 4 显示新加载的应用程序版本和图 5 演示屏幕键盘和记事本上的几个按键后屏幕键盘。

A New Instance of the On-Screen Keyboard
图 4 新实例的屏幕键盘

The On-Screen Keyboard Sending Input to Notepad
图 5:屏幕键盘发送到记事本输入

增强的安全性和移动的移植

这篇文章展示发展的屏幕键盘使用。NET 框架。 我希望它提供一些如何在屏幕上键盘可以开发,用于提高某些元素的输入数据的安全,或用于移植的洞察。移动平台的网络应用。

Christopher M. Frenz 是作者的编程书籍,"Visual Basic 和 Visual Basic。科学家和工程师的净"(很,2002年) 和"Pro Perl 解析"(很,2005年)。他可以通过 cfrenz@gmail.com

多亏了以下技术专家审查这篇文章: Robert Green