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 IntegerByRef pInputs As INPUTByVal cbSize As IntegerAs Integer
    End Function
 
    Public Shared Sub DoKeyBoard(ByVal flags As KEYEVENTFByVal 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

留言

這個網誌中的熱門文章

開啟cshtml檔案時,出現『並未將物件參考設定為物件執行個體』的錯誤訊息

無法設定中斷點 尚未載入符號檔

DataGridView欄位計算總合