I am trying to develop an on screen keyboaard for a UMPC. I have everything built and for each button click i have code for my sendkeys, however, i have not a clue where to start when it comes to focusing the application. I need to know how to after a button press on my form, return focus to the previously focused window in the correct area so that it can then send a keypress. Any And All help is greatly appreciated as i do now know at all what to do for this. Thanks
~Matt
matt.clark.228 0 Newbie Poster
Dani AI
Generated
Short version: the click on your on‑screen key will always make the key control the event sender — so your MessageBox shows the PictureBox. The reliable pattern is (1) record which input control actually had focus before the keyboard is touched, and (2) when a keyboard button is pressed, restore that control’s focus and insert the character directly instead of relying on SendKeys where possible.
As pointed out, save a reference to the last input control — but do it in the control’s Enter/GotFocus handler (not the keyboard click). Hook Enter for all input controls once at startup, store a form‑level Control reference, and on a key click cast that reference to a TextBox/RichTextBox and insert text at the caret (SelectedText). This keeps the caret position and avoids racey SendKeys behavior.
Example (conceptual, different from earlier posts):
' form-level
Private _lastInput As Control
' attach once (recursive scan recommended)
AddHandler txt1.Enter, AddressOf Input_Entered
AddHandler txt2.Enter, AddressOf Input_Entered
Private Sub Input_Entered(sender As Object, e As EventArgs)
_lastInput = DirectCast(sender, Control)
End Sub
Private Sub OnOskKeyClick(sender As Object, e As EventArgs)
If _lastInput IsNot Nothing Then
_lastInput.Focus()
Dim tb = TryCast(_lastInput, TextBoxBase)
If tb IsNot Nothing Then
tb.SelectedText = DirectCast(sender, Control).Tag?.ToString() 'insert char
Else
SendKeys.SendWait(DirectCast(sender, Control).Tag?.ToString())
End If
End If
End Sub If the target is another application, record the foreground window handle (GetForegroundWindow) when the user touches the target and restore it with SetForegroundWindow / AttachThreadInput before sending input. That requires Win32 P/Invoke and careful error handling; Windows can block SetForegroundWindow, so SendInput or PostMessage may be needed as a fallback.
Troubleshooting: verify your Enter handlers are actually attached (use debugging to show _lastInput.Name), prefer SelectedText over SendKeys to keep caret, and only use SendKeys.SendWait if you must send to a control you cannot access directly. This approach removes the confusion where sender inside a key click will always be the key control itself.
Recommended Answers
Jump to Post— kvprajapati 1,826Have a look at http://www.daniweb.com/forums/thread208096.html
All 14 Replies
kvprajapati 1,826 Posting Genius Team Colleague
Hollandtech 0 Newbie Poster
Hi Matt,
I just faced the same issue and finally solved it. I was amazed I could not find vb.net help on the subject. Anyhow...
I declared a public variable in the highest level form (mine was a multi-document interface), and declared it as a control.
Public LastFocus as Control
Then in every click event for objects my keyboard might be used to enter data into (text boxes etc.), I put a line in saving the event sender as the new LastFocus.
LastFocus=eventsender (or just sender whichever)
After my keyboard got the focus and sent the key data to the system, I put in a line of code to return focus to the last clicked control:
LastFocus.focus
It worked like a champ. If you have trouble, you can contact me <<Email Snipped>>
Edited by kvprajapati because: Email Snipped.
matt.clark.228 0 Newbie Poster
Hi Matt,
I just faced the same issue and finally solved it. I was amazed I could not find vb.net help on the subject. Anyhow...
I declared a public variable in the highest level form (mine was a multi-document interface), and declared it as a control.
Public LastFocus as Control
Then in every click event for objects my keyboard might be used to enter data into (text boxes etc.), I put a line in saving the event sender as the new LastFocus.
LastFocus=eventsender (or just sender whichever)
After my keyboard got the focus and sent the key data to the system, I put in a line of code to return focus to the last clicked control:
LastFocus.focus
It worked like a champ. If you have trouble, you can contact me <<Email Snipped>>
Private Sub kbdA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles kbdEscape.Click
LastFocus = sender
MessageBox.Show(sender.ToString)
SendKeys.send(keys.a)
LastFocus.Focus()
End Sub this is what i have, but my messagebox keeps returning the string of the picture box in which the picture of the key is that is clicked. what in the Private Sub decelerations line do i need to put in for sender?
Thanks
~Matt C
Edited by matt.clark.228 because: n/a
Hollandtech 0 Newbie Poster
Sorry Matt, I did not make myself clear. Each control that might receive keys from the keyboard must set the variable LastFocus to point to itself so that the keyboard routine knows where to redirect the focus to. For example:
Private Sub TextBox1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.Click
LastFocus = sender
ShowKeyboard()
End Sub In my case I use a keyboard that I designed as a COM object under VB-6. The line "showkeyboard" simply makes it visible if it is hidden. It performs the sendkeys internally. In your case, you should probably put the LastFocus.Focus statement before your SendKeys statement in your keyboard routine. Here is how mine looks.
Private Sub KeyBoard1_KeyClick(ByVal eventSender As System.Object, ByVal eventArgs As AxHTControls.__KeyBoard_KeyClickEvent) Handles KeyBoard1.KeyClick
On Error Resume Next
LastFocus.Focus()
Playwave("click.wav") 'Note this is a routine that produces a key click sound.
End Sub matt.clark.228 0 Newbie Poster
i am still not understanding this. the way you have explained it, your object sender will still return a value of textbox1.click, instead of the name of the previously focused item so that the focused can then be returned back to it...
Hollandtech 0 Newbie Poster
The click event for the Textbox simply saves the "sender" as a control variable. The sender is TextBox1 in this case. TextBox1.click is an event, not an object.
Think of it as it happens. You want to enter something into TextBox1, so you click on it as you would for any application. With a touch screen you touch it, which is exactly the same as a click event.
When you do, the click event subroutine saves a pointer to TextBox1. It also puts focus on the TextBox as you can tell from the cursor appearing there.
Then you touch a key on your keyboard. You want this to put characters into the TextBox1, but the act of touching the keyboard changes the focus away from TextBox1 and to the keyboard. You can tell, because the cursor disappears out of the TextBox.
So the keyboard tries to send characters to itself. There is no command I know of to simply send focus back to the previous control. But if the keyboard can look up which control last had focus before it got it (because we saved it in LastFocus), then it can restore it to that control (in this case TextBox1). Every control that you might pipe keyboard data into will have to have such a click event.
In my case, I use the click event on the textbox to also make sure the keyboard is showing. VB6 was much easier in that you could set a control so that it would not take focus in the first place.
Hollandtech 0 Newbie Poster
Try this (assuming your keyboard code is correct):
Public LastFocus as Control
Private Sub TextBox1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.Click
LastFocus = sender
End Sub
Private Sub kbdA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles kbdEscape.Click
MessageBox.Show(sender.ToString)
LastFocus.Focus()
SendKeys.send(keys.a)
End Sub Hollandtech 0 Newbie Poster
For multiple text boxes you might use a single event like this:
Private Sub TextBoxes_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.Click,TextBox2.Click,TextBox3.Click
LastFocus = sender
End Sub Edited by Hollandtech because: n/a
matt.clark.228 0 Newbie Poster
i still do not understand this. when i do this, sender is whatever i click, could someone please post their code so i can see what i am doing wrong. thanks, Matt
Hollandtech 0 Newbie Poster
Yes Matt, that is exactly correct. You want LastFocus to be whatever you last clicked (besides the keyboard). Then when you click the keyboard and it gets the focus, the keyboard can return focus to the previous object before sending the system keys.
Sorry, I don't know how to explain it more clearly. It works for me.
matt.clark.228 0 Newbie Poster
Yes Matt, that is exactly correct. You want LastFocus to be whatever you last clicked (besides the keyboard). Then when you click the keyboard and it gets the focus, the keyboard can return focus to the previous object before sending the system keys.
Sorry, I don't know how to explain it more clearly. It works for me.
The problem i have is that the sender that it returns is the button/picturebox/textbox that i click on.
i.e.
i click on a key on my osk
Private Sub keyA_Click (Byval sender as system object) Handles kbdKeyA.click
MessageBox.show(sender.tostring)
End Sub Message Box Returns:
System.Windows.Forms.PictureBox, SizeMode: AutoSize
Hollandtech 0 Newbie Poster
The problem i have is that the sender that it returns is the button/picturebox/textbox that i click on.
i.e.
i click on a key on my oskPrivate Sub keyA_Click (Byval sender as system object) Handles kbdKeyA.click MessageBox.show(sender.tostring) End SubMessage Box Returns:
System.Windows.Forms.PictureBox, SizeMode: AutoSize
Each text box or other object where text from the keyboard is to go should capture SENDER and save it as the global object LastFocus. You ignore SENDER in your key code (because yes it will be the key you just pressed). In the key code set the focus back to the LastFocus and then send the system keys.
matt.clark.228 0 Newbie Poster
could you please post code... again this is not making any sense, or working...
Hollandtech 0 Newbie Poster
I did find that the variable name LastFocus could cause some system confusion, so I am using LastSelected.
Here is a simple application. It consists of a keyboard with only three keys made from labels. In their properties window, I initialize the text of the three labels to be "A", "B", and "C" respectively. I set the font to be 36 point to make them nice and large.
It also has three text boxes where key strokes can go. They are Textbox1, Textbox2, and Textbox3.
One clicks on one of the textboxes, and then enters any series of A, B or C into that textbox using the three keys.
Public Class Form1
Public LastSelected As Object 'This is the object that will receive any keys.
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
LastSelected = Me.TextBox1 'Initialize LastSelected to point at textbox1.
End Sub
Private Sub TextBox1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.Click, TextBox2.Click, TextBox3.Click
LastSelected = sender 'Remember this textbox as LastSelected
End Sub
Private Sub LabelA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LabelA.Click, LabelB.Click, LabelC.Click
LastSelected.focus() 'Set the focus to lastselected of the textboxes.
SendKeys.Send(sender.text) 'Extract the single letter from the label clicked (A,B or C) and send it as if it came from the console.
Beep() 'Beep to acknowledge key press.
End Sub
End Class Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.