Статус TBPF_INDETERMINATE не влияет на .NET 2.0 на панели задач Windows 7 - PullRequest
2 голосов
/ 15 апреля 2011

У меня очень странная проблема.У меня есть приложение 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;пробовал различные комбинации, такие как установка прогресса в 0 и затем вызов состояния установки для неопределенности;или как сначала установить его в нормальное состояние, а затем в неопределенное - ничего не работает.Это полная тайна - и в документации нет ни малейшего понятия, почему она не работает ...

Вот код: Реализация 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

Я даже пытался получить код HRESULT из SetProgressState и проверить, чтобы убедиться, что ни одно исключение не выдается безрезультатно: SetProgressState всегда возвращает 0 (все в порядке);и без исключений!

Любая помощь в решении вопроса будет принята с благодарностью!Я просто не могу поверить, что все работает, кроме состояния MARQUE / INDETERMINATE!

Спасибо.

1 Ответ

1 голос
/ 15 апреля 2011

Во-первых, очень странно, что ваши рабочие функции обращаются к экземпляру вашей формы с помощью этого кода:

 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

Это проверено, чтобы отлично работать на Windows 7 32-разрядных. Обратите внимание, что вы можете вызывать функции из кода внутри класса вашей формы, просто указав Me для параметра frm.

...