4

I need to make my vb.net application be able to flash/blink to attract a user's attention when a notification is received within the application.

Like the DW icon does in this image:

Flashing taskbar icon

I've been Googling this for a while and have tried various code examples, all with no success.

Here's what I've got so far:

    Public Class FlashWindow
        Private Declare Function FlashWindow Lib "user32" (ByVal hwnd As Long, ByVal bInvert As Long) As Long
        Shared Sub main()
        FlashWindow(Me.Handle, 1)
        End Sub
    End Class

This code throws the following error straight away:

'Me' is valid only within an instance method

Can anyone let me know where I'm going wrong or how to achieve this?

halfer
  • 19,824
  • 17
  • 99
  • 186
John
  • 755
  • 1
  • 18
  • 46
  • You need to get hold of the window handle of the top-level window associated with the button on the taskbar. How do you plan doing so? – David Heffernan May 09 '14 at 15:52

2 Answers2

10

Firstly Me is used to reference the current class. When that code is in a Form class it has a property Handle. In your example the FlashWindow class does not have a property Handle so this will not compile.

Secondly I think that your definition of the API function is a little off.

Add this class to your project:

Public Class WindowsApi
    Private Declare Function FlashWindowEx Lib "User32" (ByRef fwInfo As FLASHWINFO) As Boolean

    ' As defined by: http://msdn.microsoft.com/en-us/library/ms679347(v=vs.85).aspx
    Public Enum FlashWindowFlags As UInt32
        ' Stop flashing. The system restores the window to its original state.
        FLASHW_STOP = 0
        ' Flash the window caption.
        FLASHW_CAPTION = 1
        ' Flash the taskbar button.
        FLASHW_TRAY = 2
        ' Flash both the window caption and taskbar button.
        ' This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags.
        FLASHW_ALL = 3
        ' Flash continuously, until the FLASHW_STOP flag is set.
        FLASHW_TIMER = 4
        ' Flash continuously until the window comes to the foreground.
        FLASHW_TIMERNOFG = 12
    End Enum

    Public Structure FLASHWINFO
        Public cbSize As UInt32
        Public hwnd As IntPtr
        Public dwFlags As FlashWindowFlags
        Public uCount As UInt32
        Public dwTimeout As UInt32
    End Structure

   Public Shared Function FlashWindow(ByRef handle As IntPtr, ByVal FlashTitleBar As Boolean, ByVal FlashTray As Boolean, ByVal FlashCount As Integer) As Boolean
    If handle = Nothing Then Return False

    Try
        Dim fwi As New FLASHWINFO
        With fwi
            .hwnd = handle
            If FlashTitleBar Then .dwFlags = .dwFlags Or FlashWindowFlags.FLASHW_CAPTION
            If FlashTray Then .dwFlags = .dwFlags Or FlashWindowFlags.FLASHW_TRAY
            .uCount = CUInt(FlashCount)
            If FlashCount = 0 Then .dwFlags = .dwFlags Or FlashWindowFlags.FLASHW_TIMERNOFG
            .dwTimeout = 0 ' Use the default cursor blink rate.
            .cbSize = CUInt(System.Runtime.InteropServices.Marshal.SizeOf(fwi))
        End With

        Return FlashWindowEx(fwi)
    Catch
        Return False
    End Try
End Function
End Class

Then can flash the window like this - passing in the reference to the main application form:

Dim res = WindowsApi.FlashWindow(Process.GetCurrentProcess().MainWindowHandle, True, True, 5)

Note:

I edited the code found here: http://pinvoke.net/default.aspx/user32.FlashWindowEx

and used the definition defined here: Get user attention without stealing focus

both of which may be useful references to you

Community
  • 1
  • 1
Matt Wilko
  • 26,994
  • 10
  • 93
  • 143
  • This code is all accepted with no errors, yet when i call the flashwindow function, nothing happens. I made sure the window didnt have focus when it was called too, but nothing happens. :( Thank you for such a detailed response though - we must be close! – John May 09 '14 at 14:03
  • If you are starting in sub Main, then there may not be any window handle created yet. You can only call this after the first window is created. What does the function return? – Matt Wilko May 09 '14 at 14:04
  • I dont see anything returned - nothing in the console, no errors or anything. My application is checking a database every 60 seconds to see if there are any alerts that need to be displayed. if it finds an alert, it displays a notification bar, updates the notification text and plays a sound. it's directly after it plays the sound that i'm calling the flash function. – John May 09 '14 at 14:13
  • The FlashWindow return a boolean - True if it worked, False if it failed. – Matt Wilko May 09 '14 at 14:15
  • ahh indeed - I added console.writeline(res) and it returns False :( – John May 09 '14 at 14:19
  • Does it function when debugging the application? ie, i dont have to publish my application for this to work do i? I suspect not, I'm just clutching at straws :) – John May 09 '14 at 14:39
  • how are you calling the flash function? My 'notificationcheck' is in a backgroundworker which is kicked off by a timer every 60 seconds... – John May 09 '14 at 14:43
  • I tried this in a background worker and it worked for me – Matt Wilko May 09 '14 at 14:51
  • I don't understand where I could be going wrong then - I've simply copy and pasted what you put - there's no errors in the error list - I just get False returned. Any ideas on what might cause it to fail anyone? – John May 09 '14 at 15:04
  • @John If you are calling from a `BackgroundWorker`, make sure it's in the `RunWorkerCompleted` event, not `DoWork`, so you don't get cross-thread issues. Also, the [return value from `FlashWindowEx`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms679347%28v=vs.85%29.aspx) doesn't really tell you if it worked or not. – Mark May 09 '14 at 16:15
1

If you were building a Windows Forms application, Me.Handle would be the way to go, but that looks like a console application, in which case try using Process.GetCurrentProcess().MainWindowHandle instead of Me.Handle. See this question for further details.

Community
  • 1
  • 1
Mark
  • 8,140
  • 1
  • 14
  • 29
  • Its not a console app - it is indeed a windows form application. – John May 09 '14 at 13:22
  • If it is Windows Forms, try moving your code into the Load event handler for your main form and see if that works (and you may want to update your question and/or tags to clarify :-). – Mark May 09 '14 at 13:27