• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 647
  • Last Modified:

How to send multiple characters with single key-press using SendInput in vb.net

I want to send 2 or 3 characters using SendInput / kbhook to another application, while pressing a single key.
0
gawacha1
Asked:
gawacha1
  • 11
  • 5
  • 3
  • +2
2 Solutions
 
Jacques Bourgeois (James Burger)Commented:
Trap the key in your application and use Sendkeys.Send to send the keys that you want.
0
 
gawacha1Author Commented:
Dear James
i will try this and come back
Regards
0
 
gawacha1Author Commented:
Dear James
please see the attached code and suggest solution
Regards
EE.doc
0
What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

 
Mike TomlinsonMiddle School Assistant TeacherCommented:
What key sequence do you need to send?

    0061: =
    0301: ???

See SendKeys.Send():
http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send.aspx

Anyways, it will look ~something~ like this:
Private Sub kbHook_KeyDown(ByVal Key As System.Windows.Forms.Keys) Handles kbHook.KeyDown 
    If Key = 65 Then
        SendKeys.Send("SomeKeySequenceInHere")
    End If
End Sub 

Open in new window

0
 
Jacques Bourgeois (James Burger)Commented:
There is a SendKeys method in .NET. You do not need all that code and the windows API to do so. Just one line of code, as Idle_Mind example code shows.
0
 
gawacha1Author Commented:
Dear James Burger
SendKeys method in .NET does not write directly in active doc but u write in yr app and it gets transmitted to another doc. I want solution with API.
could u elaborate on Idle_Mind code
Regards
0
 
gawacha1Author Commented:
Dear Idle_Mind / james Burger
I want a solution with SendInput only, so that two characters can be sent with single keystroke
Regards
0
 
Jacques Bourgeois (James Burger)Commented:
Trap the key in your application, possibly on the KeyPress event (depending on the key you want to trap) and use Sendkeys.Send in the event to send the 2 keys that you want, as an example: Sendkeys.Send("ab")
0
 
gawacha1Author Commented:
Dear Idle_Mind / james Burger
I want a solution with SendInput API only, so that two characters can be sent with single keystroke
Regards
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Two characters can be sent with a single keystroke with SendKeys.Send().  Give more specific details about what you're trying to achieve here...
0
 
gawacha1Author Commented:
i m using SendInput API and kbhook to write in another character set. I have made a KeyboardHook.vb class which has a Public Sub TapKey(ByVal bKey As Long) function which uses SendInput(1, GInput, Marshal.SizeOf(GetType(INPUT))). Now i can send single character such as 0061 but i want to send 0061 and 0301 in sequence to wordpad application so that it results in 'a with accent mark'
Regards
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
I haven't used SendInput() very often.  To send multiple keys, you add them all to an array.  The first input to SendInput() is the number of inputs you are injecting.

For instance this sends Alt-0225 (on the numpad) to generate an "a" with an accent, as described here:
http://tlt.its.psu.edu/suggestions/international/accents/codealt.html#accent

Example:
Imports System.Runtime.InteropServices
Public Class Form1

    Private Const KEYEVENTF_KEYDOWN As Integer = &H0
    Private Const KEYEVENTF_KEYUP As Integer = &H2
    Private Const INPUT_MOUSE As Integer = &H0
    Private Const INPUT_KEYBOARD As Integer = &H1
    Private Const INPUT_HARDWARE As Integer = &H2

    Private Structure MOUSEINPUT
        Public dx As Integer
        Public dy As Integer
        Public mouseData As Integer
        Public dwFlags As Integer
        Public time As Integer
        Public dwExtraInfo As IntPtr
    End Structure

    Private Structure KEYBDINPUT
        Public wVk As Short
        Public wScan As Short
        Public dwFlags As Integer
        Public time As Integer
        Public dwExtraInfo As IntPtr
    End Structure

    Private Structure HARDWAREINPUT
        Public uMsg As Integer
        Public wParamL As Short
        Public wParamH As Short
    End Structure

    <StructLayout(LayoutKind.Explicit)> _
    Private Structure INPUT
        <FieldOffset(0)> Public type As Integer
        <FieldOffset(4)> Public mi As MOUSEINPUT
        <FieldOffset(4)> Public ki As KEYBDINPUT
        <FieldOffset(4)> Public hi As HARDWAREINPUT
    End Structure

    Private Declare Function SendInput Lib "user32" (ByVal nInputs As Integer, ByVal pInputs() As INPUT, ByVal cbSize As Integer) As Integer

    Private Sub SendAltCode(ByVal FourDigitNumericCode As String)
        Dim inpt As INPUT
        Dim lstInputs As New List(Of INPUT)

        ' Alt key down
        inpt = New INPUT
        inpt.type = INPUT_KEYBOARD
        inpt.ki.wVk = Keys.Menu
        inpt.ki.dwFlags = KEYEVENTF_KEYDOWN
        lstInputs.Add(inpt)

        Dim digit As String
        For i As Integer = 0 To FourDigitNumericCode.Length - 1
            digit = FourDigitNumericCode.Substring(i, 1)
            Select Case digit
                Case "0" To "9"
                    inpt = New INPUT
                    inpt.type = INPUT_KEYBOARD
                    inpt.ki.wVk = Keys.NumPad0 + Convert.ToInt32(digit)
                    inpt.ki.dwFlags = KEYEVENTF_KEYDOWN
                    lstInputs.Add(inpt)

                    inpt = New INPUT
                    inpt.type = INPUT_KEYBOARD
                    inpt.ki.wVk = Keys.NumPad0 + Convert.ToInt32(digit)
                    inpt.ki.dwFlags = KEYEVENTF_KEYUP
                    lstInputs.Add(inpt)

            End Select
        Next

        ' Alt key up
        inpt = New INPUT
        inpt.type = INPUT_KEYBOARD
        inpt.ki.wVk = Keys.Menu
        inpt.ki.dwFlags = KEYEVENTF_KEYUP
        lstInputs.Add(inpt)

        SendInput(lstInputs.Count, lstInputs.ToArray, Marshal.SizeOf(GetType(INPUT)))
    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        System.Threading.Thread.Sleep(3000) ' bring window into focus manually for testing
        SendAltCode("0225")
    End Sub

End Class

Open in new window

0
 
gawacha1Author Commented:
Dear Idle_Mind

above code is working from button click. If used from keydown for two letters,  it becomes so recursive that i had to put a msgbox to check it.
please suggest solution to this

Regards
0
 
gawacha1Author Commented:
you may note that i want values 0061 and 0301 to make 'a with accent' and my purpose is not to send single code of 'a with accent' whatever that may be. single keypress has to generate 'a with accent' but by Sending 0061 and 0301.

Regards
0
 
aikimarkCommented:
@Jarmod

This is a VB.Net question.  I have removed the VB Classic zone and VBScript zones.

aikimark -- ZA
0
 
gawacha1Author Commented:
Dear jagassidurala

i m working on this

Regards
0
 
gawacha1Author Commented:
Dear Idle_Mind

above code is working from button click. If used from keydown for two letters,  it becomes so recursive that i had to put a msgbox to check it.
please suggest solution to this

Regards
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Show me your "keydown" code please...
0
 
gawacha1Author Commented:
Dear Idle_Mind
"keydown" code is attached
Regards
Idle-Mind.doc
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
" it becomes so recursive that i had to put a msgbox to check it. "

When you use SendInput(), it simulates the user pressing a key at the keyboard, so of course it will trigger the keyboard hook resulting in a infinite recursive loop!

First off, you should only be sending your key combination if a certain letter was pressed, but you are sending it for every keydown.  Change it so that it only fires when a certain letter is pressed.

Second, setup a boolean flag in your hook that you can toggle to indicate when the hook should ignore keystrokes and not fire it's event.  You can also setup a counter that knows how many keys are being injected by SendInput(), then decrement it for each key detected.  When it reaches zero you can turn off the flag and allow keystrokes thru again.

In KeyboardProc() you use "Return 1" to consume or "eat" the keystroke and prevent it from going further.  You only want to do that when the flag is set from SendInput(), otherwise you'll effectively prevent ALL keystrokes and have a dead keyboard.
0

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

  • 11
  • 5
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now