Solved

keytrap and getting focus

Posted on 1998-11-20
16
320 Views
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:


frmMain.Hide
Do
  If (GetAsyncKeyState(VK_F12)) Then
    If (GetAsyncKeyState(VK_ALT)) Then  ' Alt-F12 pressed
      Load frmEntry
      frmEntry.Show
    End If
    kbArray.kbByte(VK_F12) = 0    
    kbArray.kbByte(VK_ALT) = 0
    SetKeyboardState kbArray
  End If
  DoEvents
  Sleep 25
Loop

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.
0
Comment
Question by:sarahvu
  • 9
  • 2
  • 2
  • +3
16 Comments
 

Author Comment

by:sarahvu
ID: 1446006
Edited text of question
0
 

Author Comment

by:sarahvu
ID: 1446007
Edited text of question
0
 
LVL 2

Expert Comment

by:trillo
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.

Notes:
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.
0
 

Author Comment

by:sarahvu
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

then

      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.
0
 
LVL 1

Expert Comment

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

Expert Comment

by:trillo
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.
Trillo
0
 

Author Comment

by:sarahvu
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).
0
 

Author Comment

by:sarahvu
ID: 1446013
Adjusted points to 150
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 3

Expert Comment

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

0
 

Author Comment

by:sarahvu
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.
0
 

Author Comment

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

Author Comment

by:sarahvu
ID: 1446017
Adjusted points to 300
0
 
LVL 15

Expert Comment

by:ameba
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
0
 
LVL 3

Accepted Solution

by:
covington earned 300 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)
0
 

Author Comment

by:sarahvu
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.
0
 
LVL 3

Expert Comment

by:covington
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.

0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Introduction I needed to skip over some file processing within a For...Next loop in some old production code and wished that VB (classic) had a statement that would drop down to the end of the current iteration, bypassing the statements that were c…
If you have ever used Microsoft Word then you know that it has a good spell checker and it may have occurred to you that the ability to check spelling might be a nice piece of functionality to add to certain applications of yours. Well the code that…
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…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…

705 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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now