Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

App Loses Focus (Timer vs SubClass)

Status
Not open for further replies.

RMS001

Programmer
Nov 12, 2002
45
0
0
CA
Hi - I searched the threads but I couldn't find an answer.

Obviously using subclassing is the way to tell if your VB app loses focus to another app.

If this was to be done using SetTimer/KillTimer, what would you suggest as a test in the timer loop.

GetForegroundWindow()? or something else?

Thanks, - Ron
 
Two methods.

1. Subclass your window and watch for WM_ACTIVATEAPP message. The fActive flag (wParam) tells if your application is being activated or deactivated.

2. Poll the active state using a simple timer. See below.
___
[tt]
Option Explicit
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Dim myPid As Long
Private Sub Form_Load()
myPid = GetCurrentProcessId
End Sub
Private Sub Timer1_Timer()
Dim Pid As Long
GetWindowThreadProcessId GetForegroundWindow, Pid
Caption = IIf(Pid = myPid, "Active", "Inactive")
End Sub[/tt]
 
I've certainly illustrated the WM_ACTIVATEAPP technique in forum222 - although I can't find the thread at the moment.
 
It doesn't work much better or easier than that!!!

Thanks to both of you for all your amazing help over the years.

I'd like to send you both a copy of our commercial software (it was written and is currently maintained in VB6 - even on Vista). My e_m_a_i_l is rsharp(a_t)ncf(d_o_t)ca

- Ron
 
Yet another method!

This method, not only notifies you when your application gets activated or deactivated, but also tells which window is currently active, at any time.

Following code goes in the form.
___
[tt]
Private Declare Function RegisterShellHookWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function DeregisterShellHookWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Sub Form_Load()
RegisterShellHookWindow hwnd
Call Setup
End Sub
Private Sub Form_Unload(Cancel As Integer)
DeregisterShellHookWindow hwnd
End Sub[/tt]
___

This goes in a module.
___
[tt]
Option Explicit
Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Const GWL_WNDPROC = -4
Const HSHELL_WINDOWACTIVATED = 4
Dim myPid As Long, lpWndProc As Long, WM_SHELLHOOK As Long
Sub Setup()
WM_SHELLHOOK = RegisterWindowMessage("SHELLHOOK")
lpWndProc = SetWindowLong(Form1.hwnd, GWL_WNDPROC, AddressOf WndProc)
myPid = GetCurrentProcessId
End Sub
Private Function WndProc(ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If msg = WM_SHELLHOOK Then
If wParam = HSHELL_WINDOWACTIVATED Then
Dim S As String * 100, Pid As Long
GetWindowText lParam, S, Len(S)
GetWindowThreadProcessId lParam, Pid
Form1.Caption = S
Form1.BackColor = IIf(Pid = myPid, vbGreen, vbBlack)
End If
End If
WndProc = CallWindowProc(lpWndProc, hwnd, msg, wParam, lParam)
End Function[/tt]
___

Run the program. The form gets the title of the active window. It turns green when the window is active, otherwise black.
 
Hi Hypetia - I was afraid subclassing was the only way to do it propery. The timer worked great to get the state of the app (focus/no focus), but by the time the state is determined, it's too late to run any code (if it is associated with a control, the focus gets shifted back to the original app).

Do you know of a way to run a hook that still allows debugging in the IDE?

Thanks, - Ron.
 
>Do you know of a way to run a hook that still allows debugging in the IDE?

See the SmartSubclass Library which will make your life a lot easier.

It allows you to subclass your window in a "safe" environment. You don't face any of the risks of normal subclassing technique. Your window is subclassed but the window procedure resides in an ActiveX DLL instead of being written in your own code. Message notifications are sent in the form of events from the ActiveX component.

You can break, debug and edit your code in the IDE. You can even use the filthy End statement during subclassing without any crashes!

When you finish working on your project and ready to compile it for production, you can remove this smart subclassing from your project and replace it with traditional VB subclassing if you want. This will make your program independent of this DLL and you don't need to distribute it with your application.
 
Hi Hypetia - Thanks. Trying to get our product ready to show new version at ComiCon in San Diego. 20 hour days and no time to experiment. I had a quick look and will be attempting to implement it soon. Thanks again. - Ron
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top