如何在vb.net中闪烁/闪烁任务栏图标?

4

我需要让我的vb.net应用程序在接收到应用内通知时能够闪烁以吸引用户的注意力。

就像这张图片中DW图标所做的那样:

Flashing taskbar icon

我已经搜索了一段时间,并尝试了各种代码示例,但都没有成功。

以下是我目前的进展:

    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

这段代码立即抛出以下错误:

“Me”仅在实例方法中有效

请问有人能告诉我哪里出了问题或如何实现这个功能吗?

你需要获取与任务栏按钮关联的顶级窗口的窗口句柄。你打算如何做到这一点? - David Heffernan
2个回答

10

首先,Me用于引用当前类。当该代码位于Form类中时,它有一个名为Handle的属性。在您的示例中,FlashWindow类没有Handle属性,因此无法编译。

其次,我认为您对API函数的定义有点偏差。

将此类添加到您的项目中:

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

然后可以像这样闪烁窗口 - 传递对主应用程序窗体的引用:

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

注意:

我编辑了在这里找到的代码:http://pinvoke.net/default.aspx/user32.FlashWindowEx

并使用了在此处定义的定义:Get user attention without stealing focus

这两个参考资料可能对您有用。


这段代码没有任何错误,但是当我调用flashwindow函数时,什么也没有发生。我确保在调用时窗口没有焦点,但是仍然没有反应。:(非常感谢您提供如此详细的回复 - 我们一定很接近了! - John
如果您正在 sub Main 中开始,则可能尚未创建任何窗口句柄。只有在创建第一个窗口后才能调用此函数。该函数返回什么? - Matt Wilko
我没有看到任何返回的东西 - 控制台中没有任何内容,也没有错误或其他任何信息。我的应用程序每60秒检查一次数据库,以查看是否有需要显示的警报。如果发现警报,则会显示通知栏,更新通知文本并播放声音。就在它播放声音后,我调用了flash函数。 - John
FlashWindow返回一个布尔值 - 如果成功则为True,如果失败则为False。 - Matt Wilko
啊,确实 - 我添加了 console.writeline(res) ,它返回 False :( - John
显示剩余5条评论

1

如果你正在构建一个Windows Forms应用程序,Me.Handle是一个好方法,但看起来这像是一个控制台应用程序,在这种情况下,请尝试使用Process.GetCurrentProcess().MainWindowHandle代替Me.Handle。有关详细信息,请参见this question


这不是控制台应用程序 - 它确实是一个Windows窗体应用程序。 - John
如果是Windows Forms,尝试将代码移动到主窗体的Load事件处理程序中,看看是否有效(您可能需要更新您的问题和/或标签以澄清:-)。 - Mark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接