Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win


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.
Independent Software Vendors: 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

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

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

I’ve seen a number of people looking for examples of how to access web services from VB6.  I’ve been using a test harness I built in VB6 (using many resources I found online) that I use for small projects to work out how to communicate with web serv…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…
Suggested Courses

610 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