【发布时间】:2011-08-06 03:45:59
【问题描述】:
我有一个非常奇怪的问题。我有一个 VB.NET 2.0 应用程序,它利用了 Windows 7 任务栏按钮进度功能,即在 Win7 任务栏按钮中显示某些进度和应用程序状态。
一切正常 - 我可以设置和更新进度,我可以将按钮设置为暂停或错误状态,我可以将其设置为无进度。一切正常,除了 MARQUE(不确定)模式。这完全是个谜,每当我将状态设置为 TBPF_INDETERMINATE(值为 0x1)时,它都会简单地更改回 NOPROGRESS 类型,即它会从任务栏按钮中删除所有进度指示并将其设置回默认状态 - 从来没有动画标记显示!
我已阅读 MSDN 上的文档 - http://msdn.microsoft.com/en-us/library/dd391697(v=vs.85).aspx ;尝试了各种组合,例如将进度设置为 0,然后调用 set state 来不确定;或者喜欢先将其设置为正常,然后再设置为不确定 - 没有任何效果。这完全是个谜——文档中没有任何线索说明它失败的原因......
代码如下: 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 状态之外的一切都正常!
谢谢。
【问题讨论】:
-
代码是否来自 Windows API 代码包?还是您自己根据 MSDN 上的文档编写了 p/invoke 定义?
-
两者 - 我采用了 Windows API 代码包,基本上只保留了 ITaskbarList3 以及几个额外的结构/枚举(由 ITaskbarList3 使用);然后我将那个小代码从 C# 转换为 VB.NET - 非常简单 - 我在这篇文章中包含了所有这些代码。
-
顺便说一句,这样做的原因是:1)我的应用程序是.NET 2.0,而API代码包需要.net 3.5; 2) 我真的只需要进度按钮功能 - 不需要任何其他功能。
-
非常有意义。我主要是好奇,这样我就知道需要多少代码来检查错误。我决定启动 Visual Studio 并自己进行测试会更容易。我想我现在已经发现了问题。
标签: vb.net winapi windows-7 .net-2.0 taskbar