TBPF_INDETERMINATE状态在.net 2.0中对Windows 7任务栏不起作用



我有一个很奇怪的问题。我有VB。. NET 2.0应用程序,利用Windows 7任务栏按钮进度特性,即在Win7任务栏按钮中显示某些进度和应用程序状态。

一切都很好-我可以设置和更新进度,我可以将按钮设置为暂停或错误状态,我可以将其设置为无进度。除了MARQUE (Indeterminate)模式,其他都可以工作。这完全是一个谜,每当我将状态设置为TBPF_INDETERMINATE(值为0x1)时,它只是变回NOPROGRESS类型,即它从任务栏按钮中删除所有进度指示并将其设置回其默认状态-没有动画标记显示!

我已经阅读了MSDN - http://msdn.microsoft.com/en-us/library/dd391697(v=vs.85).aspx上的文档;尝试了各种组合,比如将progress设置为0,然后调用set state为indeterminate;或者先把它设为正常,然后再设为不确定——什么都不起作用。这完全是一个谜——文档中没有任何线索说明为什么它会失败…

代码如下:API实现:

    <StructLayout(LayoutKind.Sequential)> _
Public Structure RECT
    Public left As Integer
    Public top As Integer
    Public right As Integer
    Public bottom As Integer
    Public Sub New(left As Integer, top As Integer, right As Integer, bottom As Integer)
        Me.left = left
        Me.top = top
        Me.right = right
        Me.bottom = bottom
    End Sub
End Structure
Public Enum TBPFLAG
    TBPF_NOPROGRESS = 0
    TBPF_INDETERMINATE = &H1
    TBPF_NORMAL = &H2
    TBPF_ERROR = &H4
    TBPF_PAUSED = &H8
End Enum
Public Enum TBATFLAG
    TBATF_USEMDITHUMBNAIL = &H1
    TBATF_USEMDILIVEPREVIEW = &H2
End Enum
Public Enum THBMASK
    THB_BITMAP = &H1
    THB_ICON = &H2
    THB_TOOLTIP = &H4
    THB_FLAGS = &H8
End Enum
Public Enum THBFLAGS
    THBF_ENABLED = 0
    THBF_DISABLED = &H1
    THBF_DISMISSONCLICK = &H2
    THBF_NOBACKGROUND = &H4
    THBF_HIDDEN = &H8
End Enum
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Structure THUMBBUTTON
    <MarshalAs(UnmanagedType.U4)> _
    Public dwMask As THBMASK
    Public iId As UInteger
    Public iBitmap As UInteger
    Public hIcon As IntPtr
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> _
    Public szTip As String
    <MarshalAs(UnmanagedType.U4)> _
    Public dwFlags As THBFLAGS
End Structure
<ComImportAttribute()> _
<GuidAttribute("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")> _
<InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface ITaskbarList3
    ' ITaskbarList
    <PreserveSig()> _
    Sub HrInit()
    <PreserveSig()> _
    Sub AddTab(hwnd As IntPtr)
    <PreserveSig()> _
    Sub DeleteTab(hwnd As IntPtr)
    <PreserveSig()> _
    Sub ActivateTab(hwnd As IntPtr)
    <PreserveSig()> _
    Sub SetActiveAlt(hwnd As IntPtr)
    ' ITaskbarList2
    <PreserveSig()> _
    Sub MarkFullscreenWindow(hwnd As IntPtr, <MarshalAs(UnmanagedType.Bool)> fFullscreen As Boolean)
    ' ITaskbarList3
    Sub SetProgressValue(<[In]()> ByVal hwnd As IntPtr, <[In]()> ByVal ullCompleted As UInt64, <[In]()> ByVal ullTotal As UInt64) 'hwnd As IntPtr, ullCompleted As UInt64, ullTotal As UInt64)
    Sub SetProgressState(<[In]()> ByVal hwnd As IntPtr, <[In]()> ByVal tbpFlags As TBPFLAG) 'hwnd As IntPtr, tbpFlags As TBPFLAG) 'As Integer
    Sub RegisterTab(hwndTab As IntPtr, hwndMDI As IntPtr)
    Sub UnregisterTab(hwndTab As IntPtr)
    Sub SetTabOrder(hwndTab As IntPtr, hwndInsertBefore As IntPtr)
    Sub SetTabActive(hwndTab As IntPtr, hwndMDI As IntPtr, tbatFlags As TBATFLAG)
    Sub ThumbBarAddButtons(hwnd As IntPtr, cButtons As UInteger, <MarshalAs(UnmanagedType.LPArray)> pButtons As THUMBBUTTON())
    Sub ThumbBarUpdateButtons(hwnd As IntPtr, cButtons As UInteger, <MarshalAs(UnmanagedType.LPArray)> pButtons As THUMBBUTTON())
    Sub ThumbBarSetImageList(hwnd As IntPtr, himl As IntPtr)
    Sub SetOverlayIcon(hwnd As IntPtr, hIcon As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> pszDescription As String)
    Sub SetThumbnailTooltip(hwnd As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> pszTip As String)
    '[MarshalAs(UnmanagedType.LPStruct)]
    Sub SetThumbnailClip(hwnd As IntPtr, ByRef prcClip As RECT)
End Interface
<GuidAttribute("56FDF344-FD6D-11d0-958A-006097C9A090")> _
<ClassInterfaceAttribute(ClassInterfaceType.None)> _
<ComImportAttribute()> _
Public Class CTaskbarList
End Class

下面是使用这些代码的实际过程:

 Friend Sub SetWindows7Progress(ByVal aValue As Integer)
        If Not IsWin7orLater Then Exit Sub
            If w7tb Is Nothing Then
                w7tb = CType(New CTaskbarList, ITaskbarList3)
            End If
            CType(w7tb, ITaskbarList3).SetProgressValue(My.Forms.Form1.Handle, Math.Min(Math.Max(1, aValue), 1000), 1000)
 End Sub
    Friend Sub ResetWindows7Progress()
        If Not IsWin7orLater Then Exit Sub
            If w7tb Is Nothing Then
                w7tb = CType(New CTaskbarList, ITaskbarList3)
            End If
            CType(w7tb, ITaskbarList3).SetProgressState(My.Forms.Form1.Handle, TBPFLAG.TBPF_NOPROGRESS)
    End Sub
    Friend Sub SetWindows7ProgressMon()
        If Not IsWin7orLater Then Exit Sub
            If w7tb Is Nothing Then
                w7tb = CType(New CTaskbarList, ITaskbarList3)
            End If
            CType(w7tb, ITaskbarList3).SetProgressState(My.Forms.Form1.Handle, TBPF_INDETERMINATE)
    End Sub

我甚至尝试从SetProgressState获得HRESULT代码,并检查以确保没有异常抛出无效:SetProgressState总是返回0(一切都很好);并且不会抛出异常!

任何帮助解决这个问题将是非常感激的!我简直不敢相信,除了MARQUE/INDETERMINATE状态之外,一切都正常了!

谢谢。

首先,这是非常奇怪的,你的工作函数访问你的表单的实例使用以下代码:

 My.Forms.Form1.Handle

这意味着这些函数不是在与表单相同的类中定义的(因为如果它们是,编译器会提示您使用Me)。如果是这种情况,你真的应该把窗体的句柄作为参数传递给函数。

(这样做的原因是您的函数是可重用的。如果您硬编码了对特定表单的引用,那么当您重命名该表单,或者一次在屏幕上显示它的两个实例,或者只是想在任务栏中显示不同表单的进度指示器时,会发生什么?打破的东西。将表单实例作为参数传递是一种更简洁、更可重用的方法。

第二,似乎进行了不必要的类型转换。为什么不直接将w7tb变量声明为ITaskbarList3类型,而不是在它和CTaskbarList之间来回转换呢?

第三,我不确定这是打字错误还是实际问题,但是您的SetWindows7ProgressMon函数实际上并没有引用TBPF_INDETERMINATE的正确值。当实际上是在TBPFLAG枚举中定义的时,对该标识符使用非限定引用。

所以,考虑到以上所有,我将重写你发布的第二块代码如下:

Private w7tb As ITaskbarList3
Friend Sub SetWindows7Progress(ByVal frm As Form, ByVal aValue As Integer)
    If (Not IsWin7orLater()) OrElse (frm Is Nothing) Then
        Exit Sub
    End If
    If w7tb Is Nothing Then
        w7tb = CType(New CTaskbarList, ITaskbarList3)
    End If
    w7tb.SetProgressValue(frm.Handle, Math.Min(Math.Max(1, aValue), 1000), 1000)
End Sub
Friend Sub ResetWindows7Progress(ByVal frm As Form)
    If (Not IsWin7orLater()) OrElse (frm Is Nothing) Then
        Exit Sub
    End If
    If w7tb Is Nothing Then
        w7tb = CType(New CTaskbarList, ITaskbarList3)
    End If
    w7tb.SetProgressState(frm.Handle, TBPFLAG.TBPF_NOPROGRESS)
End Sub
Friend Sub SetWindows7ProgressMon(ByVal frm As Form)
    If (Not IsWin7orLater()) OrElse (frm Is Nothing) Then
       Exit Sub
    End If
    If w7tb Is Nothing Then
        w7tb = CType(New CTaskbarList, ITaskbarList3)
    End If
    w7tb.SetProgressState(frm.Handle, TBPFLAG.TBPF_INDETERMINATE)
End Sub

经过测试,在32位的Windows 7上可以完美地工作。注意,只需为frm参数指定Me,就可以从表单类中的代码调用这些函数。

最新更新