A way to find which (sub) window has the focus?

G

Gary

I'm trying to find a way to determin which window Within-Another-Program
currently has the focus.

THE SITUATION: (Skip down to "My Question" if you don't want the
background...)

* This is a service desk where people "check in" to use a certain facility
or area.
* The company is running an application they purchased off-the-shelf.
* The application accepts input of member numbers from a serial-port
bar-code card-scanner.
* The card scanner just pipes the swiped card data into the keyboard buffer.
Example: "/123456\"
* The application has a window, usually active, to accept member check-in
numbers.
* But it has other forms too (life for setup, member edit, etc.)
* If that particular window is not active when a member slides their
card...the input is lost.

I'm trying to write a program that will capture any keyboard input.
If it matches the format slash-######-slash -- then I know it's a member
number.
If the "Enter Member Number" form is active, I'll just pass the data on
through.
If something else is active, I'll capture this data and give them a way to
access it later.


MY QUESTION:

Using the code below, I can find out which APPLICATION is active.
But within the application, there are various windows.
Is there a way I can tell which "sub-window" has the focus?

NOTE:
I'M thinking there must be a way because...consider the ALT-PRINT-SCREEN
button.
If you press Print-Screen, it copies the entire screen to a buffer
But pressing Alt-Print-Screen, copies only the currently active sub-window
to the buffer.
So, somehow, windows knows which sub-window is active.

Of course it does. It has to. But how can I find this in VB


THANKS,
Gary


CODE I'M USING To FIND WHICH WINDOW IS ACTIVE:
(But does not tell which document / sub-window with-in the application is
active)

Private Declare Function GetForegroundWindow Lib "user32.dll" () As IntPtr

Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal
hwnd As IntPtr, ByRef lpdwProcessID As Integer) As Integer

Private Sub timerActiveWindowCheck_Tick(ByVal sender As System.Object, ByVal
e As System.EventArgs) Handles timerActiveWindowCheck.Tick

'----- Put an asterisk in the window so I know it did something.

txtActiveWindow.Text = txtActiveWindow.Text + "*" & vbCrLf

Dim hWnd As IntPtr = GetForegroundWindow()

If hWnd = IntPtr.Zero Then Exit Sub

Dim pid As Integer = 0

If 0 = GetWindowThreadProcessId(hWnd, pid) Then Exit Sub

Dim proc As Process = Process.GetProcessById(pid)

If proc Is Nothing Then Exit Sub

txtActiveWindow.Text = txtActiveWindow.Text + proc.ProcessName & " -- " &
proc.MainWindowTitle & vbCrLf

End Sub
 
G

Gary

Steve Gerrard said:
Isn't that it?

You go on to get the process that owns it, and the the main window title
of that process, but this hWnd should be the active window.

Not quite.

This returns the name of the APPLICATION.

But the application has various windows that can be open within it.

For exaple, take MS-Word.
* "MS-Word" is the application.
* You can and a user document that has focus.
* Or you have have the "Borders & Shading" tool box form open
* Of you can have the "Tools > Options" form open.

What I have above always returns just "MS-Word", no matter which
"sub form" (correct term here?) is currently active.

I need a way to know which "sub form" is open.

Thanks for taking an interest,
Gary
 
G

Gary

Steve Gerrard said:
Isn't that it?

You go on to get the process that owns it, and the the main window title
of that process, but this hWnd should be the active window.

I feel like I'm maybe very close but am just missing some obvious
parameter or something to get what I want.
 
G

Gary

Steve Gerrard said:
I think you missed my point.

I know that your code gets the application name, but look at how you get
it:

Step 1: get handle to active window.
Step 2: get process that owns that window.
Step 3: get main window of that process.

Yes indeed, Step 3 gets you MS Word, or what have you.

My point? That Step 1 (not step 2, not step 3) gets you a handle to the
*active window*. Which is what you want.

Ah, thanks Steve.

I'll go try that.

I had a feeling I was being dense.

Will report back later. Again, many thanks.
 
G

Gary

Below is the code I ended up with that works.

Thanks Steve for pointing out that, like Dorothy in the Wizard of Oz, I had
the answer all along ;-)


One other question, showing my ignorance of API calls: Why do I have to use
the
"Alise" for two of these functions, but not for the other two?

THANKS,
Gary

Private Declare Function GetForegroundWindow Lib "user32.dll" () As IntPtr

Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal
hwnd As IntPtr, ByRef lpdwProcessID As Integer) As Integer

Private Declare Function GetWindowText Lib "user32.dll" Alias
"GetWindowTextA" (ByVal hWnd As IntPtr, ByVal WinTitle As String, ByVal
MaxLength As Integer) As Integer

Private Declare Function GetWindowTextLength Lib "user32.dll" Alias
"GetWindowTextLengthA" (ByVal hwnd As Long) As Integer







Private Sub timerActiveWindowCheck_Tick(ByVal sender As System.Object, ByVal
e As System.EventArgs) Handles timerActiveWindowCheck.Tick

'----- Get the Handle to the Current Forground Window -----

Dim hWnd As IntPtr = GetForegroundWindow()

If hWnd = IntPtr.Zero Then Exit Sub

'----- Find the Length of the Window's Title -----

Dim TitleLength As Integer

TitleLength = GetWindowTextLength(hWnd)

'----- Find the Window's Title -----

Dim WindowTitle As String = StrDup(TitleLength + 1, "*")

GetWindowText(hWnd, WindowTitle, TitleLength + 1)

'----- Find the PID of the Application that Owns the Window -----

Dim pid As Integer = 0

GetWindowThreadProcessId(hWnd, pid)

If pid = 0 Then Exit Sub

'----- Get the actual PROCESS from the process ID -----

Dim proc As Process = Process.GetProcessById(pid)

If proc Is Nothing Then Exit Sub

'----- Write This Information to the Text Box -----

txtProcessID.Text = pid.ToString

txtProcessName.Text = proc.ProcessName

txtProcessTitle.Text = proc.MainWindowTitle

txtCurrentWindowTitle.Text = WindowTitle

txtTitleLength.Text = TitleLength.ToString

End Sub
 
G

Gary

Steve Gerrard said:
Alias is used when the name in the DLL is different from the name you are
using. For instance, GetWindowText can use the A or the W version, meaning
ANSI or Wide characters (its a unicode thing). As long as you say Alias
"GetWindowTextA", you could declare it as GitThatTharText if you wanted
to. :)

So there really is no "GetWindowText" in the DLL, only "GetWindowTextA" and
"GetWindowTextW" ?

Thanks Steve. Now I owe you two.

I'm a novice, but I'll try to pay back by hanging out around here and answer
any easy ones that I happen to know.
 
B

Bernadus Prihandoko

Hi,

I have same problem with this. I have to create membership application
which has two forms. First form is manager desk and the second one is
member screen. Member screen using extended monitor and manager desk
using main screen. When member slide the card and user is using another
program in main screen, it is interrupted. Focus is lost from
application that user currently working. I'd like to solve this problem
but there is problem when hooking up barcode input. Can you help me? I
need sample application which i can read from barcode scanner.

Thanks,
Bernad.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top