[RESOLVED] Timers go inactive after standby mode
My program is always running in the system tray. When the computer goes into standby mode, the active timers stop (along with the rest of the computer) and that's fine. The problem is when the computer gets woken back up, my timers remain dormant.
How can I detect when the computer comes out of standby mode so I can re-activate my timers?
Re: Timers go inactive after standby mode
Here is a MSDN article regarding a message you may need to subclass for. Also see this related article
Re: Timers go inactive after standby mode
That's a very interesting observation. What is the state of the timer's properties, does it switch to .Enabled = False or does Interval change?
Re: Timers go inactive after standby mode
Quote:
Originally Posted by
LaVolpe
Yep, perfect. Not to go all n00b on you, but could I get some help subclassing? I usually avoid it like the plague and so I don't have a clue what to do.
Re: Timers go inactive after standby mode
Quote:
Originally Posted by
baja_yu
That's a very interesting observation. What is the state of the timer's properties, does it switch to .Enabled = False or does Interval change?
Good question; I only know it's true from observing the behavior of compiled exes. I'll run from the IDE now and let it suspend and then see what's what.
Re: Timers go inactive after standby mode
You will have to do some research on those messages. One link mentioned having to register for notification, so some playing will have to be done. Following is the simplest form of subclassing, do not execute an END statement, nor do not hit the Stop/End button on the VB toolbar or any debug messages while subclassing else crash. Save work often ;)
Start subclassing sometime during/after form_load. Always unsubclass during/before form_unload.
Following is air code
Code:
' in a Module
Private m_WndProc As Long
Public Sub SubclassStartStop(hWnd As Long, bStart As Boolean)
If bStart Then
If m_WndProc = 0 Then
m_WndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf NewWndProc)
End If
ElseIf m_WndProc Then
SetWindowLong hWnd, GWL_WNDPROC, m_WndProc
m_WndProc = 0
End If
End Sub
Private Function NewWndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case uMsg
' ....
Case Else
End Select
NewWndProc = CallWindowProc(m_WndProc, hWnd, uMsg, wParam, lParam)
End Function
here are some delcarations
Code:
Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32.dll" 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 Const GWL_WNDPROC As Long = -4
Note: Some messages you trap, you may not want to allow to be forwarded to the window you are subclassing (maybe not the case here). In those cases, MSDN tells you what to set the return value of NewWndProc to. Also, in those cases, you obviously would not allow the CallWindowProc call to be executed.
Edited: Oops, forgot an END SELECT line. Warned you it was air code. Sorry.
Also do not place breakpoints in the NewWndProc and do not use messageboxes. Use Debug.Print statements instead for testing/troubleshooting
Re: Timers go inactive after standby mode
Sweet, LaVolpe, you rock as always. I should be able to get it going with this. (Though I'll bump if I get stuck, of course.)
Interestingly, in response to baja_yu, it turns out the timer didn't go inactive but my display is getting halted anyway. I need to do a little more research to pinpoint the exact problem, but until then the short answer is that timers handle waking up from standby just fine.
Re: Timers go inactive after standby mode
You may want to experiment with API timers and see if there is any difference. Does the O/S stop sending WM_TIMER messages during sleep? Kinda surprised that if it does, it doesn't start resending them on wakeup.
Re: Timers go inactive after standby mode
Okay, this is embarassing, but I should post my results for posterity. First, it turns out that VB's native timers work fine with standby, meaning this thread wasn't necessary. (Though I'm bookmarking this as a reference for subclassing.)
My program has a two-part system tray icon. The first is just the app's icon, and is static. The second is a hard drive indicator modelled after ZoneAlarm's indicator. Once the hard drive is (relatively) inactive for 1.5 seconds, the indicator gets replaced with the static icon, just like ZoneAlarm.
When I first wrote this, I had trouble when it came out of standby such that it left the indicator up and unchanging. I dealt with this in a temporary fashion by turning off the HD indicator whenever you put the computer to sleep. (One of the features of my utility is to run a third party disk defrag and then activate the screen saver, which I label as "sleep".)
Flash forward months (years?) to today, and I'm trying to add a battery indicator for laptops. The idea being that if you're on a laptop running on battery (not charging), it'll display a battery charge indicator instead of the static icon. The problem is that after coming out of standby, the icon stops responding until the user "resets" it by double-clicking it. Yeah, lame, but as I said it was only a temporary fix. Too bad I left it so long I forgot the temp fix and thought it was a bug in VB6.
So yeah, the reason the timer stops is because my code physically stops it. Doh! After disabling that one line of code, everything works great; it resumes out of standby mode just fine. Turns out that this new version -- which I've rewritten from the ground up since I put in the temporary fix -- no longer has any logic flaws in handling when to switch between the HD indicator and the static icon. I can only assume the original version had such a flaw, which knowing me it probably did.
Anyway, that's the whole story. Apologies for wasting your time, but thanks again for the barebones subclassing template.