Newbie
Newbie

Reputation: 873

Eventhandler "bug" using VB.NET with windows forms

i have the following code:

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)

    Const WM_SYSCOMMAND As Integer = &H112
    Const SC_SCREENSAVE As Integer = &HF140

    MyBase.WndProc(m)
    If bloqueado = 0 Then
        If m.Msg = WM_SYSCOMMAND AndAlso m.WParam.ToInt32 = SC_SCREENSAVE Then
            Timer2.Start()
            inicio = Now
            pausa = pausa + 1
            AddHandler Application.Idle, AddressOf Application_Idle
        End If
    End If
End Sub

Private Sub Application_Idle(ByVal sender As Object, ByVal e As EventArgs)
    Dim newitem As ListViewItem
    Dim diferença As TimeSpan

    'MsgBox(Now.ToString)'
    Debug.Print(Now.ToString)
    fim = Now
    diferença = fim - inicio
    Timer2.Stop()
    newitem = New ListViewItem
    newitem.Text = pausa
    newitem.SubItems.Add(inicio.ToLongTimeString)
    newitem.SubItems.Add(fim.ToLongTimeString)
    newitem.SubItems.Add(diferença.ToString.Substring(0, 8))
    ListView1.Items.Add(newitem)
    parcial = parcial & pausa & vbTab & vbTab & inicio.ToLongTimeString & vbTab & vbTab & fim.ToLongTimeString _
         & vbTab & vbTab & diferença.ToString.Substring(0, 8) & vbTab & vbTab & "   screensaver" & System.Environment.NewLine
    RemoveHandler Application.Idle, AddressOf Application_Idle
End Sub

Basically the first part detect when screensaver activates and creates a application.idle event handler and the second part, when activity is detected a bunch of code is run and the handler removed.

It's all works fine except for one point:

As you can see i have inicio = now when screensaver becomes active and fim = now when activity is detected (when screensaver becomes inactive), so i should have 2 differente times, but if i have it like i posted the 2 datetime will be the same. If you notice i have a msgbox displaying the now (when screensaver stops) in comment, if i take it out of comment the 2 datetimes will be differente and correct (i used a cronometer to make sure of the results)

Now my questions: Why does it need the messagebox for the now to be updated and why doesn't it work it debug.print?

Is there a way to solve this problem/update the now var, without having to use a messagebox (i wouldn't like for the app to have pop-up messages)

If i really have to use msgbox for this purpose is there a way for it not to send the pop-up or to autoclick ok right after so it disappears instantly?

EDIT:

I have been searching and i found this code:

Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Public Function IsSNRunning() As Boolean
        IsSNRunning = (FindWindow("WindowsScreenSaverClass", vbNullString) <> 0)
    End Function

    Private Sub Timer3_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer3.Tick
        If IsSNRunning() Then
            'Screen Saver Is Running
        Else
            Timer3.Stop()
            code
        End If
End Sub

i used Timer3.Start() when in the part that captures the start of the screensaver, my idea being if i start the timer when i know the screensaver if on, then when i get IsSNRunning as false is when the screensaver stops running, but it doesn't work, any ideas why?

Upvotes: 0

Views: 518

Answers (2)

Newbie
Newbie

Reputation: 873

First i'll thank you guys for the help, like you said application.idle doesn't work, with you help i got this solution i VB:

Imports System
Imports Microsoft.Win32
Imports System.Windows.Forms
Imports System.Runtime.InteropServices

<DllImport("user32.dll", CharSet:=CharSet.Auto)> Public Shared Function SystemParametersInfo(uAction As UInteger, _
    uParam As UInteger, ByRef lpvParam As Boolean, fWinIni As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' Check if the screensaver is busy running.'
Public Shared Function IsScreensaverRunning() As Boolean
    Const SPI_GETSCREENSAVERRUNNING As Integer = 114
    Dim isRunning As Boolean = False

    If Not SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, isRunning, 0) Then
        ' Could not detect screen saver status...'
        Return False
    End If

    If isRunning Then
        ' Screen saver is ON.'
        Return True
    End If

    ' Screen saver is OFF.'
    Return False
End Function


Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)

    Const WM_SYSCOMMAND As Integer = &H112
    Const SC_SCREENSAVE As Integer = &HF140

    MyBase.WndProc(m)
    If bloqueado = 0 Then
        If m.Msg = WM_SYSCOMMAND AndAlso m.WParam.ToInt32 = SC_SCREENSAVE Then
            Timer2.Start()
            Timer3.Enabled = True
            Timer3.Start()
            'here we that that the screensaver started running so we start a timer'
        End If
    End If
End Sub

Private Sub Timer3_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer3.Tick

    If IsScreensaverRunning() Then
        'Screen Saver Is Running'
    Else
        Timer3.Stop()
        Timer3.Enabled = False
        'Screen Saver Is not Running'
    End If

End Sub

Because the timer only starts running when the screensaver is running we know that when you get timer3.stop is when the screensaver stopped running

Important, don't put a msgbox before the timer stop because it wont work, the pop-up will show and it wont get to the stop so innumerous pop-up will appear (yeah... i made that mistake :S)

Again, thanks for helping me and hope it will help someone in the future

Upvotes: 0

Hans Passant
Hans Passant

Reputation: 942538

Doing anything with Application.Idle is a lost cause. Not only does your app go idle immediately after the screen saver activates, you also never stop being idle while it is running. The screen saver switches the active desktop to a dedicated secure desktop, none of the running programs will ever get any input, not until it de-activates.

You can observe the desktop switch, the SystemEvents.SessionSwitch event fires.

Do note the considerable lack of practical usefulness of code like this. Curiosity is okay but there are always a lot of things to learn. The screen saver should be at the bottom of your list.

Upvotes: 1

Related Questions