keytrap and getting focus

Posted on 1998-11-20
Medium Priority
Last Modified: 2008-02-20
I am using the API GetAsyncKeystate to capture a combination of keys which then loads and perform a form.show 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.
Question by:sarahvu
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 2
  • 2
  • +3

Author Comment

ID: 1446006
Edited text of question

Author Comment

ID: 1446007
Edited text of question

Expert Comment

ID: 1446008
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.
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!


Author Comment

ID: 1446009
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.

Expert Comment

ID: 1446010
Use the code and the solution trillo gave you, that is your only possibily in this case!

Expert Comment

ID: 1446011
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.

Author Comment

ID: 1446012
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).

Author Comment

ID: 1446013
Adjusted points to 150

Expert Comment

ID: 1446014
what ever happened to form2.textbox1.setfocus??
load it.. and set its focus..then send the rest of the keys


Author Comment

ID: 1446015
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.

Author Comment

ID: 1446016
My project is located at http://marlin.utmb.edu/~kcao/cqiclient.zip.  Please, anyone, give it a shot!

Author Comment

ID: 1446017
Adjusted points to 300
LVL 15

Expert Comment

ID: 1446018
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

Accepted Solution

covington earned 1200 total points
ID: 1446019
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)

Author Comment

ID: 1446020
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 sarahvu@yahoo.com.  Thank you much.

Expert Comment

ID: 1446021
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.


Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
Most everyone who has done any programming in VB6 knows that you can do something in code like Debug.Print MyVar and that when the program runs from the IDE, the value of MyVar will be displayed in the Immediate Window. Less well known is Debug.Asse…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Suggested Courses
Course of the Month12 days, 12 hours left to enroll

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question