How do I simulate/release keyboard keys? - vb.net

I need a way to simulate keyboard keys if a certain condition is met, I also need to know if it's the simulated key that's currently pressed or the real key. This needs to work outside the main application.
This is how I would need it to work:
Dim UserDefinedKey As Keys = Keys.H
Do
If GetAsyncKeyState(UserDefinedKey) Then
Thread.Sleep(30)
'release the set key
Thread.Sleep(30)
'press/hold the set key once, continue the loop if the real key is still been held.
End If
Loop While GetAsyncKeyState(UserDefinedKey) '/ loop while real key is being held
'Real key is no longer held, release the simulated key press.
Any help would be greatly appreciated.
(This code is to automate certain things inside of a game which is why it needs to work outside the main application)
I have certain things in place to allow the user to set their own key, this was just a small example of what I need, it's just the keyboard simulating part i'm stuck with and determining if the real key is still pressed or not.

So sorry for the long wait... Simulating keyboard input via Window Messages turned out to be far much more complicated compared to simulating mouse input in the same way.
Anyway, I am finally done with it so here's a complete InputHelper class for simulating both mouse and keyboard input virtually via the mouse and keyboard input stream or via Window Messages.
Download at GitHub: https://github.com/Visual-Vincent/InputHelper/releases (source code is too long to be pasted in the answer)
Dim UserDefinedKey As Keys = Keys.H
'Using a regular While-loop is better since you won't need your If-statement then.
While InputHelper.Keyboard.IsKeyDown(UserDefinedKey)
Dim ActiveWindow As IntPtr = InputHelper.WindowMessages.GetActiveWindow()
Thread.Sleep(30)
InputHelper.WindowMessages.SendKey(ActiveWindow, UserDefinedKey, False) 'False = Key up.
Thread.Sleep(30)
InputHelper.WindowMessages.SendKey(ActiveWindow, UserDefinedKey, True) 'True = Key down.
End While
A little information about InputHelper's sub-classes:
InputHelper.Keyboard
Methods for handling and simulating physical keyboard input (i.e. input detected by GetAsyncKeyState()).
InputHelper.Mouse
Methods for handling and simulating physical mouse input.
InputHelper.WindowMessages
Methods for handling and simulating virtual keyboard and mouse input (i.e. input that is not detected by GetAsyncKeyState()).
Hope this helps!

You will need Windows API hooks for that (nothing for beginners), or third party library like MouseKeyHook

Related

How to check if VBA application is in focus when GetAsyncKeyState is pressed

I have a long running application written in VBA. Because it runs for a long time I call a sub from the main loop every iteration to check if the user has pressed the escape key. The sub is listed below. The code works great except that it is always listening, even when the VBA application does not have the focus. What's the best way to approach this? Is there an alternative to GetAsyncKeyState which only listens when the correct application is in focus, or are there system calls I can use to check that the correct window is in focus.
Private Sub checkForUserEscKeyAbort()
'Listen for escape key and exit gracefully if user aborts.
Dim abortResult As VbMsgBoxResult
If GetAsyncKeyState(vbKeyEscape) Then
abortResult = MsgBox("Escape key pressed, do you want to abort?", vbYesNo)
If abortResult = vbYes Then Call teardownSLICER
End If
End Sub
The problem is the way GetAsyncKeyState operates. It does more than just check it the key is currently down, it also checks if the key was pressed since the last time GetAsyncKeyState was called. Thus, your problem of "always listening".
You could use GetKeyState, but frankly, I'm not a fan of that option either. Your code must be well crafted to avoid a polling window that is so small that you literally have to hold the key down to ensure it isn't missed.
A viable alternative is key masking where you use a combination of keys such as Shift-Escape. There is a decent introduction to this (and many other subjects) on Chip Pearson's site. However, this is still not my preferred method.
My preference has already mentioned in the comments. Your application may best be improved with a user form. It also gives you the ability to get information in front of the user. Perhaps they wouldn't try quitting the application if a progress bar on the user form indicated 95% completion. Maybe you can add a pause button that free's some resources for a prescient need and then resumes when the user is ready. That little extra functionality on its own is enough to win me over but there is an even better reason for using a User Form - it does exactly what you asked!
User forms, and many user form controls, have Keydown, Keyup, and Keypress events that only trigger when the form (or control) have focus. This is precisely what you wanted.

detect key-sequence in vb.net application and set focus to specific field

I have a barcode scanner. Each time this barcode scanner scanns something it first types ##1 and then the code it has read. I would like my app to set focus to a specific textbox whenever it detects the sequence ##1 regardless of what is selected/active when i am scanning. (for instance the focus could be on the form itself, or on an image, or in a table or whatever..)
The only way I have found is to use a global keyhook using getasynckeystate but its not good practice since most antivirus programs see it as a keylogger. I also do not need them to be detected when the program is not in focus.. only when in focus. Is there a proper way to detect all the Keys pressed while the application is active, that does not upset the antivirus programs?

Enter Key simulate click not working for checkboxes

I have copied and slightly modified the code found at the bottom of this post to allow tabbing between form controls on a worksheet form I have created. Here is the segment relating to the KeyCode = vbKeyEnter:
Select Case KeyCode
Case vbKeyTab
Dim Backward As Boolean
Backward = (Shift And fmShiftMask)
Call MoveFocus(Cntrl:=Cntrl, TabIndex:=TabIndex, Backward:=Backward)
Case vbKeyEnter
Select Case TypeName(Cntrl)
Case TxtBoxType
If Not (Cntrl.EnterKeyBehavior And Cntrl.MultiLine) Then
Call MoveFocus(Cntrl:=Cntrl, TabIndex:=TabIndex)
End If
Case Else
On Error Resume Next
Application.Run Sheet1.CodeName & "." & Cntrl.name & "_Click"
On Error GoTo 0
End Select
End Select
The code works fine for tabbing forward and backward between controls. However, I'm having troubles using the enter key to check and uncheck check box controls. It works for option buttons, but does not work check boxes. If I add CheckBox1.Value = True to the CheckBox1_Click event it works to check it true, but naturally won't allow it to uncheck to false. I've tried adding the following IF statement to set it to true or false depending on current value, but then nothing happens.
If CheckBox1.Value = True Then
CheckBox1.Value = False
Else
CheckBox1.Value = True
End If
Another note: When I hit enter and nothing happens to the form control it moves the active cell down the active column. Any suggestions?
This may or may not be an answer to the programming question; I will let the voters decide.Q. Enter Key simulate click not working for checkboxes
Why would you do such a thing? You are spending time and effort to intentionally 'break' a working system. The spacebar has long been the accepted keystroke for toggling a checkbox on and off, Tab and Shift+Tab are used for navigating between form controls and Enter↵ is the default for OK.
By 'working system' I mean the whole Mac/Windows/Linux GUI system and the millions of people that have trained to work within long defined standard practises. You can take the mouse away from any competent office worker and their productivity will not suffer. They can navigate through the system and applications to perform their work because everything in the system from setting the video resolution to typing workers' timecard data into a custom form works the same way.
Take a Windows user and stick them in front of their first Mac. They can use the programs and get the job done because the vast majority of operations (and particularly the ones for basic operation of an application) are the same. Take a Mac user and stick them in front of a Linux machine and you will get the same results. The basic day-to-day operation of the machine and its programs are the same.
What is the point of any prospective applicant looking for employment to come with a CV filled with office experience if you are going to create a proprietary system that takes all of their training, practise and experience and throws it out the window?
The use of the spacebar to toggle a checkbox on and off predates Windows 3.0. There is a difference between building a better mousetrap and reinventing the wheel¹.
¹ If you don't think that maintaining GUI standards is something to strive for, consider the backlash that the Office 2007 ribbon created. An entire sub-industry dedicated to producing add-ons that brought back Office 2003 functionality was spawned.

VB.Net, keep shift pressed, and release after certain function is done?

Is that possible?
I want to keep my shift pressed in an external application (such as fire fox)
and release it as I pressed it again,
I want it working just like the caps button.
to make it easier to understand,
maybe something like
shift is pressed
Keys.Shift.hold = true
and
shift is pressed again
Keys.shift.hold = false
Apologies in advance for the pseudocode; I don't know VB.net. If you're comfortable with C++, you can adapt code from this question, which I used as a reference.
You can use the SendInput Windows API. According to the function's description, it
Synthesizes keystrokes, mouse motions, and button clicks.
You will need to ensure your target program has a lower process integrity than yours - in other words, if your process isn't running as admin, don't try to feed events to an admin-level process - but since you mentioned Firefox I don't expect this to be an issue for you.
You'll want to set up a KEYBDINPUT structure like this:
wVk = VK_SHIFT
dwFlags = 0 (this will press a key. You'll want KEYEVENTF_KEYUP instead for releasing it.)
Then, set up an INPUT structure like this:
type = INPUT_KEYBOARD
ki = yourKeybdInputStruct
Now pass that whole INPUT structure to SendInput:
SendInput(1, &yourInputStruct, sizeof(yourInputStruct))
Alternately, you could try using the VB.net SendKeys class. There are some caveats that come with this class; most notably,
If your application is intended for international use with a variety of keyboards, the use of Send could yield unpredictable results and should be avoided.
Additionally, the official documentation says nothing about using a modifier key (Shift, Ctrl, Alt) by itself, nor does it appear to support holding a key down in the manner you describe, just sending a regular keystroke (keydown-keyup).
However, if you're willing to deal with those issues, this might work:
SendKeys.Send("+")

lost ability to pick up tab key in KeyDown

I'm working on an application which uses numerous panels which are swapped at runtime. The swapping of the panels is controlled by handling keydown events and examining the current "state" of the application to determine how to route the keys.
I was doing some cleanup work in the form designer moving panels and labels around and now i've somehow disabled my main form's ability to pick up the tab key in my keydown event. I still get all other keys, including enter key.
The code didn't change and was very much tested to function fine with a tab key, so I can only imagine I accidentally turned off some important property when playing in the designer.
I have keypreview turned on in my main form. Since I get other key events I do not believe that my keydown handler is working incorrectly. Somehow my form just stopped feeding tab key through. TabIndexes are sequentially numbered but they should not matter since I am using keypreview to process the event before letting tabindex determine its next jump.
I figured this might be an easy one for somebody who's been there and fought this before. I have backups with the tab key still functioning but i've made leaps today in the logic so i'm not quite ready to roll back or do a side-by-side compare of every object on the form.
That's not supposed to work. And won't when you have any controls on the form that can get the focus. The Tab key and the cursor keys are used for navigation, moving the focus from one control to another.
The KeyPreview property is a VB6 legacy compatibility property, used to implement custom shortcut keystrokes. The code that intercepts the navigation keys runs before the code that fires the form's KeyDown event. You instead should override the ProcessCmdKey() method, it runs before the navigation code so can see the Tab and cursor keys:
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
If keyData = Keys.Tab Then
'' Do something, preferably navigation related since that what the user expects
''...
Return True '' That means that the key was consumed
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
I searched for tabstop and looked for an object with this as true.
My "find" in VS didn't find anything but then I saw a listbox on the last panel I added to my project that had tabstop turned on.
Turning this off got me back to where I originally was at with my code picking up the tab key.