keytrap and getting focus

I am using the API GetAsyncKeystate to capture a combination of keys which then loads and perform a method.  This form contains a text box which I want to have focus when the form is loaded.

This is what actually happens:  
Say my VB app name is AAA.  When I am in another active app, say BBB, I would press the key combo (alt-F12, for instance).  This would call up a form (of AAA) to show on screen.  The cursor blinks in a text box, which is the default object to get focus in this form.  However, when I start typing, the text box does not take my input, because the active app is still BBB.  If I now click on the form, I can enter text as usual.  

I want to NOT have to FIRST click on the form to get focus, but instead, start typing right away into the text box after pressing the key combo.  Preferably, this would all be done within AAA.  Please help.  

Here's a sample of some codes:

In form main:

  If (GetAsyncKeyState(VK_F12)) Then
    If (GetAsyncKeyState(VK_ALT)) Then  ' Alt-F12 pressed
      Load frmEntry
    End If
    kbArray.kbByte(VK_F12) = 0    
    kbArray.kbByte(VK_ALT) = 0
    SetKeyboardState kbArray
  End If
  Sleep 25

In frmEntry, a text box gets the focus by default.

If you think this question deserves more points, please say so!  I will increase if neccesary.
Who is Participating?
covingtonConnect With a Mentor Commented:
Take all of the code that you have in Form_Load.

Move it to Form_Activate.

Add "Me.Hide" as the first line of Form_Activate

Now you will get the results that you want.

I downloaded your project, made these changes, and compiled it. It works for me now. (VB6, Win 98)
sarahvuAuthor Commented:
Edited text of question
sarahvuAuthor Commented:
Edited text of question
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

You can use one of the following API functions
Declare Function SetActiveWindow Lib "user32" Alias "SetActiveWindow" (ByVal hwnd As Long) As Long
Declare Function SetForegroundWindow Lib "user32" Alias "SetForegroundWindow" (ByVal hwnd As Long) As Long

Pass the Handle (HWND property) of the form you want to be active.

The "SetActiveWindow" function activates a window, but not if the application is in the background. The window will be brought into the foreground (top of Z order) if the application is in the foreground when it sets the activation.
The "SetForegroundWindow" window function, on the other hand, activates a window and forces it into the foreground. An application should only call SetForegroundWindow if it needs to display critical errors or information that needs the user's immediate attention.
The SetForegroundWindow function puts the thread that created the specified window into the foreground and activates the window. Keyboard input is directed to the window, and various visual cues are changed for the user.
sarahvuAuthor Commented:
How do I get the handle of my window?

I used the API:
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

and obtain the handle by:

      nHwnd = FindWindow("AAA", vbNullString)   ' with quotes


      Call SetForegroundWindow(nHwnd)   ' where nHwnd is a variable of type long

This does not work.  Where do you find documentation for API calls anyway?  I have the MSDN library installed but can't find documentation for API calls.
Use the code and the solution trillo gave you, that is your only possibily in this case!
Two comments, one for alesh and the other for sarahvu:
1) Alesh: If the only thing you want to say is "Use the code and the solution trillo gave you, that is your only possibily in this case".... you could have posted it like a comment not like an answer.
2) Sarahvu: To obtain the handle of the window you have he right function, I don't know wahy it doesn't work, see if the handle you obtained is a valid handle.
The other possibility is using the AppActivate function, (it not and API)... maybe this is easier.
>> can't find documentation for API calls.
VB doesn't provide much information about API's. Find out if one of your friends has VC++ or BC++ builder, and I think it wouldn't be a piracy cirme to copy the help files on your machine, these are realy good helpers.
sarahvuAuthor Commented:
Yes, please do add as comment so my question won't be locked, wasting time...

Trillo, you probably didn't believe me when I said it wouldn't work (perfectly reasonable when you don't get to test the code yourself).  I can package the code and send it to you so you can try it yourself.  I'm using VB6.  I'm certain that there is no other error that is causing the problem because it works just fine when I ran the code from within VB.  When I compile it to an .exe is when the problem occurs (I don't get the focus in my text box by default).

Regarding AppActivate, this returns an error, I think because a running application trying to activate itself (tried it and forgot exact error code).
sarahvuAuthor Commented:
Adjusted points to 150
what ever happened to form2.textbox1.setfocus??
load it.. and set its focus..then send the rest of the keys

sarahvuAuthor Commented:
Nope, the text box gets the focus by default since it's the first control in the form.  In fact, the cursor blinks in the text box when activated but the focus remains in the windows explorer (where the application was started from).  I also tried call setforegroundwindow (me.hwnd) with same result.
sarahvuAuthor Commented:
My project is located at  Please, anyone, give it a shot!
sarahvuAuthor Commented:
Adjusted points to 300
sarahvu, I saw your code.
You are doing Do...Loop waiting for 'hotkey' in your Form_Load event. You should move this to Form_Activate or use timer, or if you don't want to show your startup form, start your app with Sub Main() and use your loop there.

You are using advanced APIs, but I didn't see:
code indenting, any error handling, Option Explicit!?
Regarding AppActivate, it works perfect.
Application trying to activate its active window (e.g. after sending keys to other app) can use:
    AppActivate Me
Of course, it will fail (return an error) when it cannot do its job. Simple line 'On Error Resume Next' will prevent your app from hanging (ignore error).
Hope this helps
sarahvuAuthor Commented:
Yes it works great!  I still don't understand why.  Would really appreciate an explanation, but if you can't find time, that would be fine.  My Email address is  Thank you much.
The calls to SetActiveWindow won't work if called from the Form_Load event. Since the form isn't loaded, there's no way to make it active. Call AppActivate (Me.Caption) will also fail for the same reason. Since this call fails, your app is not the foreground app, so the calls to activate the entry window also fail. By moving the code to Form_Activate, you wait until the form is loaded. The Me.Hide call is necessary to hide the form to make sure that it never gets activated again - otherwise, the code would run twice. Also, I assume that you want that form hidden. You could also guarantee that the code doesn't run twice with a static boolean variable.

If you are trying to avoid the Form_Load event, you might think that the code could move to a module. That doesn't work, either. You need a main form for the application to make active. It's probably possible to put all the code in one form, and use the static variable to make sure the initialization code only runs once. This form would be the main form for entry, and it would also contain the loop. Then you could also stop the loop and restart it as the form is shown and hidden. Instead of trying this, I chose the solution that made as few changes to your code as possible.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.