SendKeys in WPF

在以往Windows Form的程式開發當中,當要送出鍵盤的相關資料時,會使用SendKeys的方式來處理,例如說要把一個字加到TextBox上這樣;用SendKeys的好處不用去處理當輸入的游標在文字中間的問題,會比像是
TextBox1.Text &= "1"
這樣的方式來的方便些。而到了WPF,沒有SendKeys可以用了,那麼應該怎麼辦呢?在網路上搜尋了一下,可以利用呼叫API的方式來做,可以參考一下下面 SendInput 的說明,所有需要的東西都在裡面了。動作原理大概是下面過程

紀錄要輸入的控制項在畫面上的位置
使用SendInput模擬滑鼠的動作,點擊要輸入的控制項(主要是要取得Focus)
使用SendInput模擬KeyDown的動作
使用 SendInput模擬KeyUp的動作

大概的過程是這樣子了;而我自己的使用方式有點偷懶,直接略過模擬滑鼠的部分,直接傳控制項的參考過去 XDD

下面是目前的程式碼,還沒詳細測試,大致就是上面列出的SendInput中的程式碼了,參考看看了;首先是宣告的部分

#Region "Const"
    Const INPUT_MOUSE As UInt32 = 0
    Const INPUT_KEYBOARD As Integer = 1
    Const INPUT_HARDWARE As Integer = 2
    Const KEYEVENTF_EXTENDEDKEY As UInt32 = &H1
    Const KEYEVENTF_KEYUP As UInt32 = &H2
    Const KEYEVENTF_UNICODE As UInt32 = &H4
    Const KEYEVENTF_SCANCODE As UInt32 = &H8
    Const XBUTTON1 As UInt32 = &H1
    Const XBUTTON2 As UInt32 = &H2
    Const MOUSEEVENTF_MOVE As UInt32 = &H1
    Const MOUSEEVENTF_LEFTDOWN As UInt32 = &H2
    Const MOUSEEVENTF_LEFTUP As UInt32 = &H4
    Const MOUSEEVENTF_RIGHTDOWN As UInt32 = &H8
    Const MOUSEEVENTF_RIGHTUP As UInt32 = &H10
    Const MOUSEEVENTF_MIDDLEDOWN As UInt32 = &H20
    Const MOUSEEVENTF_MIDDLEUP As UInt32 = &H40
    Const MOUSEEVENTF_XDOWN As UInt32 = &H80
    Const MOUSEEVENTF_XUP As UInt32 = &H100
    Const MOUSEEVENTF_WHEEL As UInt32 = &H800
    Const MOUSEEVENTF_VIRTUALDESK As UInt32 = &H4000
    Const MOUSEEVENTF_ABSOLUTE As UInt32 = &H8000
#End Region
 
#Region "Enums"
    Public Enum InputType As Integer
        Mouse = 0
        Keyboard = 1
        Hardware = 2
    End Enum
 
    <Flags()> _
    Public Enum MOUSEEVENTF As Integer
        MOVE = &H1
        LEFTDOWN = &H2
        LEFTUP = &H4
        RIGHTDOWN = &H8
        RIGHTUP = &H10
        MIDDLEDOWN = &H20
        MIDDLEUP = &H40
        XDOWN = &H80
        XUP = &H100
        VIRTUALDESK = &H400
        WHEEL = &H800
        ABSOLUTE = &H8000
    End Enum
 
    <Flags()> _
    Public Enum KEYEVENTF As Integer
        EXTENDEDKEY = 1
        KEYUP = 2
        [UNICODE] = 4
        SCANCODE = 8
    End Enum
#End Region
 
#Region "Structure"
    <StructLayout(LayoutKind.Explicit)> _
    Public Structure INPUT
        <FieldOffset(0)> Dim dwType As Integer
        <FieldOffset(4)> Dim mouseInput As MOUSEINPUT
        <FieldOffset(4)> Dim keyboardInput As KEYBDINPUT
        <FieldOffset(4)> Dim hardwareInput As HARDWAREINPUT
    End Structure
 
    <StructLayout(LayoutKind.Explicit)> _
    Public Structure KEYBDINPUT
        <FieldOffset(0)> Public wVk As Short
        <FieldOffset(2)> Public wScan As Short
        <FieldOffset(4)> Public dwFlags As Integer
        <FieldOffset(8)> Public time As Integer
        <FieldOffset(12)> Public dwExtraInfo As IntPtr
    End Structure
 
    <StructLayout(LayoutKind.Explicit)> _
    Public Structure HARDWAREINPUT
        <FieldOffset(0)> Public uMsg As Integer
        <FieldOffset(4)> Public wParamL As Short
        <FieldOffset(6)> Public wParamH As Short
    End Structure
 
    <StructLayout(LayoutKind.Explicit)> _
    Public Structure MOUSEINPUT
        <FieldOffset(0)> Public dx As Integer
        <FieldOffset(4)> Public dy As Integer
        <FieldOffset(8)> Public mouseData As Integer
        <FieldOffset(12)> Public dwFlags As Integer
        <FieldOffset(16)> Public time As Integer
        <FieldOffset(20)> Public dwExtraInfo As IntPtr
    End Structure
#End Region
 
    <DllImport("user32.dll", EntryPoint:="SendInput")>
    Public Shared Function SendInput(ByVal cInputs As Integer, ByRef pInputs As INPUT, ByVal cbSize As Integer) As Integer
    End Function
 
    Public Shared Sub DoKeyBoard(ByVal flags As KEYEVENTF, ByVal key As Char)
        Dim _input As New INPUT
        Dim ki As New KEYBDINPUT
        _input.dwType = InputType.Keyboard
 
        _input.keyboardInput = ki
        _input.keyboardInput.wVk = Convert.ToInt16(key)
        _input.keyboardInput.wScan = 0
        _input.keyboardInput.time = 0
        _input.keyboardInput.dwFlags = flags
        _input.keyboardInput.dwExtraInfo = IntPtr.Zero
        Dim cbSize As Integer = Marshal.SizeOf(GetType(INPUT))
        Dim result As Integer = SendInput(1, _input, cbSize)
        'If result = 0 Then Debug.WriteLine(Marshal.GetLastWin32Error)
        _input = Nothing
        ki = Nothing
    End Sub


而外面的UerControl多加了一個Property,使用方式大約會像是這樣子

Public Property FoucedCtl As TextBox
 
    Private Sub Button_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
        If Me.FoucedCtl Is Nothing Then
            Exit Sub
        End If
        Me.FoucedCtl.Focus()
        Win32Helper.DoKeyBoard(0, CType(sender, Button).Content.ToString.Chars(0))
        System.Threading.Thread.Sleep(5)
        Win32Helper.DoKeyBoard(Win32Helper.KEYEVENTF.KEYUP, CType(sender, Button).Content.ToString.Chars(0))
    End Sub

留言

這個網誌中的熱門文章

安裝部屬全攻略之─如何製作安裝檔

使用VS2005連接到CE5.0裝置發生錯誤(0x8973151A)

利用IP位置取得對方的Mac