[RESOLVED] do something when a form loses focus to another program?
I'd like for my program to do some things when the user goes away from it (Like clicks anywhere other than the form, like the desktop or Notepad or whatever), but I have no idea how to do it. I've tried to use Form_LostFocus but it didn't do anything. Right now I just have a Standard EXE project open with only the following code:
VB Code:
Private Sub Form_LostFocus()
Me.Caption = "AAAAAHAHAHAHAHAHHAHAHA"
End Sub
The form's caption doesn't change when I go away from it. This isn't really what I'm wanting it to do in the long run, but I just put it there to see if the LostFocus thing works. I'm eventually going to want it to call some functions instead.
Re: do something when a form loses focus to another program?
Subclassing is one option, or another simple one would be a timer and to check the window title of the active window and compare it with the caption of your form...
Re: do something when a form loses focus to another program?
This is how to subclass and catch the message...
If you are trying to catch the activation of your app when another app is switch to and back again - this subclass works...
First, need to know if you are in the IDE - cannot subclass in the IDE - causes the IDE to crash. Got this trick from MartinLiss
Code:
On Error Resume Next
Debug.Print 1 / 0
gDebugMode = (Err.Number <> 0)
Then you do this.
Code:
If Not gDebugMode Then Call Subclass(Me)
On form unload do this...
Code:
If Not gDebugMode Then Call Unsubclass
This goes into a module...
Code:
Option Explicit
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 SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hWnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Private Const GWL_WNDPROC As Long = (-4)
Private Const WM_ACTIVATEAPP = &H1C
'm_frmHooked is the form that the subclass 'listens' in on
Private m_lPrevProc As Long, m_frmHooked As Form
Public Function WndProc(ByVal hWnd As Long, _
ByVal wMsg As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
'Let the window process messages as well
WndProc = CallWindowProc(m_lPrevProc, hWnd, wMsg, wParam, lParam)
'See what message has been sent to the window
If wMsg = WM_ACTIVATEAPP Then
'It's the activateapp message so call the sub on the form
Call m_frmHooked.AppFocus(CBool(wParam))
End If
End Function
Public Sub Unsubclass()
Debug.Print "UnSubClass"
Call SetWindowLong(m_frmHooked.hWnd, GWL_WNDPROC, m_lPrevProc)
Set m_frmHooked = Nothing
End Sub
Public Sub Subclass(ByRef r_frm As Form)
Debug.Print "SubClass"
Set m_frmHooked = r_frm
m_lPrevProc = SetWindowLong(r_frm.hWnd, GWL_WNDPROC, AddressOf WndProc)
End Sub
And this is the function that gets called when the app is gains focus or loses focus. Take out my code in this function and restore the "commented" out code that changes the FORM CAPTION to HAS FOCUS and LOST FOCUS.
This will show you how nicely this works.
Code:
Public Sub AppFocus(ByVal v_bFocus As Boolean)
Dim i As Long, j As Long, k As Long, x As Long, y As Long, z As Long
Dim s1 As String, s2 As String, s3 As String, s4 As String, s5 As String
If v_bFocus Then
'App has just gained focus
'Me.Caption = "ActivateApp; has-focus with TAB...TAG=" & tabForms.SelectedItem.Tag
'Me.Caption = "ActivateApp gmodal" & gModal
If Not gModal Then
For x = 2 To Forms.Count - 1
If tabForms.SelectedItem.Tag = CStr(Forms(x).mintTabNo) Then
' Me.Caption = "ActivateApp; has-focus TXTINPUT.TAG=" & Forms(x).txtInput.Tag & " CBOINPUT.TAG=" & Forms(x).cboInput.Tag
gfrmKeyDown(Forms(x).mintTabNo) = -1
Call FocusPilot(Forms(x), 0, 0, 0, 0)
Exit For
End If
Next
End If
Else
'App has just lost focus
'Me.Caption = "ActivateApp; no-focus"
End If
End Sub
Re: do something when a form loses focus to another program?
I figured it out. I used a timer to check if the hwnd of the foreground window is the hwnd of my window. (got the idea from Manavo! Thanks!)
VB Code:
Option Explicit
Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private Sub Timer1_Timer()
If Not GetForegroundWindow = Me.hWnd Then
'My window isn't in the foreground
Call pauseeverything
Me.Caption = "Paused"
Else
Call unpauseeverything
Me.Caption = "Playing"
End If
End Sub
Re: [RESOLVED] do something when a form loses focus to another program?
And the not so good approach that will work with the timer :
VB Code:
Option Explicit
Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private Sub Form_Load()
Timer1.Interval = 50
Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()
If GetForegroundWindow = Me.hwnd Then
Me.Caption = "Active"
Else
Me.Caption = "Not Active"
End If
End Sub
Edit: You already got it, too late :(