Results 1 to 33 of 33

Thread: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc)

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    [VB6] Win7 Taskbar Features with ITaskbarList3 : overlay, progress in taskbar, etc

    ITaskbarList Demo

    Windows 7 introduced the ITaskbarList3 and ITaskbarList4 interfaces that added a number of new features to the taskbar for your program. The most commonly seen is the ability to turn the taskbar into a progress bar, and there's also the ability to add an overlay icon, add buttons below the thumbnail, and change the area the thumbnail covers among others. Like many other shell interfaces, it's available to VB either through type libraries or by directly calling the vtable. I prefer the former approach since many times internal structures and interfaces have far wider uses, so they can be put in the TLB and be accessible everywhere, not just within a class.

    Project Update
    Updated the TLB reference to point to oleexp.tlb v4.0 or higher.

    Project Update
    Project updated to fix minor bug where tooltips for custom buttons did not display.

    Requirements
    -Only works on Windows 7 and above.
    -This project uses oleexp.tlb, my Modern Shell Interfaces expansion of Edanmo's olelib.tlb. Always use the latest version from that thread, it's no longer included in the ZIP of my projects so that 6 different versions aren't around all at once. Once you've extracted everything, in the sample project, go to References and update the path. If you already work with olelib, oleexp replaces it. There's a few minor changes, but nothing major- just a few things moved to oleexp and 3 interfaces had some of their subs turned into functions. See the oleexp thread in the link above for complete details. *This project now references oleexp.tlb v4.0 or higher*


    Using ITaskbarList

    Usage is fairly simple; you generally want to use it as a module level variable in your main form;

    Code:
    Private iTBL As TaskbarList
    
    '...then in form_load:
    
    Set iTBL = New TaskbarList
    From there you can begin calling its functions, most of which are very straightforward:
    Code:
        iTBL.SetOverlayIcon Me.hWnd, hIcoOvr, "Overlay icon active."
        iTBL.SetProgressState Me.hWnd, TBPF_INDETERMINATE 'marquee 
        iTBL.SetThumbnailTooltip Me.hWnd, Text1.Text
        iTBL.SetThumbnailClip Me.hWnd, [rect]
    The only thing a little complicated is the buttons.

    Code:
    Dim pButtons() As THUMBBUTTON
    ReDim pButtons(2) 'basic 3-button setup
    
    arIcon(0) = ResIconToHICON("ICO_LEFT", 32, 32)
    arIcon(1) = ResIconToHICON("ICO_UP", 32, 32)
    arIcon(2) = ResIconToHICON("ICO_RIGHT", 32, 32)
    
    Call SubClass(Me.hWnd, AddressOf F1WndProc)
    
    With pButtons(0)
        .dwMask = THB_FLAGS Or THB_TOOLTIP Or THB_ICON
        .iid = 100
        .dwFlags = THBF_ENABLED
        Call Str2Inta("Stop", pInt)
        For i = 0 To 259
            .szTip(i) = pInt(i)
        Next i
        .hIcon = arIcon(0)
    End With
    
    [fill in the other buttons]
    
    iTBL.ThumbBarAddButtons Me.hWnd, 3, VarPtr(pButtons(0))

    Icons
    The TaskbarList interface deals with hIcons; in the sample project, they're stored in a resource file and loaded from there, but you could load them from anywhere with any method that will give you a valid hIcon.

    Subclassing
    The only thing that requires subclassing is receiving notification when a user clicks on a button below the thumbnail. If you're not going to be using that feature, then you won't need to subclass. The sample project does include a very simple subclassing module that receives the WM_COMMAND message that's sent when a button is clicked, and passes the ID of the button (the LoWord of the wParam) back to the main form.
    Attached Files Attached Files
    Last edited by fafalone; Mar 17th, 2020 at 05:31 AM. Reason: Attached project updated to reference oleexp.tlb 4.0 or higher

  2. #2
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Quote Originally Posted by fafalone View Post
    The sample project does include a very simple subclassing module ...
    There is a newer, much simpler and safer way of subclassing using ComCtl32.dll version 6.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    I'm a little tired so maybe I'm misreading, but if the subclassed object has the implement the IHookXP interface doesn't that limit it to forms/modules/classes?

    If I were to use SetWindowSubclass directly.. maybe it's because I'm unfamiliar with it, but it sure doesn't look simpler when it goes past writing the initial code to set the subclass.. what with the whole ID thing and all.
    Last edited by fafalone; Jan 20th, 2015 at 01:03 AM.

  4. #4
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Quote Originally Posted by fafalone View Post
    ... but if the subclassed object has the implement the IHookXP interface doesn't that limit it to forms/modules/classes?
    I don't see why that would be a problem. Advanced VB coders have always wanted to integrate subclassing code in the Object module being subclassed (Form/MDIForm/UserControl/PropertyPage/UserDocument) so that their code is as self-contained as possible. The idea behind the IHookXP interface was to make a generic subclasser module using the new subclassing APIs. That interface isn't necessary, though, if you'll just be subclassing 1 window. For simple cases like that, the technique shown in my 2nd link above should prove sufficient.

    Quote Originally Posted by fafalone View Post
    If I were to use SetWindowSubclass directly.. maybe it's because I'm unfamiliar with it, but it sure doesn't look simpler when it goes past writing the initial code to set the subclass.. what with the whole ID thing and all.
    The uIdSubclass parameter helps in identifying multiple subclassing code targeting the same hWnd. Any 32-bit value can be specified, although, many take this opportunity to pass a pointer to the Object module being subclassed. Depending on the parameter declaration, that pointer may be automatically cast to the desired Object inside the subclass procedure.

    To prove that using the newer subclassing APIs generally produces simpler and less lines of code, here is the rewritten modWndProc.bas:

    Code:
    Option Explicit
    
    Private Declare Function DefSubclassProc Lib "comctl32.dll" Alias "#413" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function SetWindowSubclass Lib "comctl32.dll" Alias "#410" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, Optional ByVal dwRefData As Long) As Long
    Private Declare Function RemoveWindowSubclass Lib "comctl32.dll" Alias "#412" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long) As Long
    
    Public Function Subclass(ByRef Form As VB.Form) As Boolean
        Subclass = SetWindowSubclass(Form.hWnd, AddressOf SubclassProc, ObjPtr(Form)):      Debug.Assert Subclass
    End Function
    
    Public Function UnSubclass(ByRef Form As VB.Form) As Boolean
        UnSubclass = RemoveWindowSubclass(Form.hWnd, AddressOf SubclassProc, ObjPtr(Form)): Debug.Assert UnSubclass
    End Function
    
    Private Function SubclassProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Form1, ByVal dwRefData As Long) As Long
        Const WM_COMMAND = &H111&, WM_DESTROY = &H2&
    
        Select Case uMsg
            Case WM_COMMAND
                dwRefData = LoWord(wParam)  'Avoid declaring additional variables inside window procedures!
                Select Case dwRefData       'They'll still be allocated even for messages not handled here!
                    Case 100, 101, 102
                        uIdSubclass.GotButtonClick CInt(dwRefData)
                        Exit Function
                End Select
    
            Case WM_DESTROY
                UnSubclass uIdSubclass
        End Select
    
        SubclassProc = DefSubclassProc(hWnd, uMsg, wParam, lParam)
    End Function
    
    Private Function LoWord(ByVal dwValue As Long) As Integer
        If dwValue And &H8000& Then
            LoWord = dwValue Or &HFFFF0000
        Else
            LoWord = dwValue And &HFFFF&
        End If
    End Function
    The line:

    Code:
    Call SubClass(Me.hWnd, AddressOf F1WndProc)
    in Form1.frm will have to be shortened to just:

    Code:
    Subclass Me
    in order to make that code work.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Looks good... but having every subclass go to the same wndproc gets to be unmanageable pretty quick, so I'd wind up basically having the same call to point to different wndprocs, but I definitely like the idea of being able to pass an object to a wndproc, which I've really only done with callbacks.


    Edit: I tried using it for general subclassing, and I get an error highlighting the first line (Public Function F1WndProc...). But the way VB crashes I can't get it to show the messagebo saying what error it is. I traced the problem to calling unsubclass; it seems I can't use the AddressOf function there for some reason... can you not call from inside the proc or something?

    Code:
    Public Function Subclass(hWnd As Long, lpfn As Long, Optional uID As Long = 0&, Optional dwRefData As Long = 0&) As Boolean
    If uID = 0 Then uID = hWnd
        Subclass = SetWindowSubclass(hWnd, lpfn, uID, dwRefData):      Debug.Assert Subclass
    End Function
    Public Function UnSubclass(hWnd As Long, ByVal lpfn As Long, pID As Long) As Boolean
        UnSubclass = RemoveWindowSubclass(hWnd, lpfn, pID)
    End Function
    
    Public Function F1WndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
      
      Select Case uMsg
    
        Case WM_COMMAND
            Dim lw As Integer
            lw = LoWord_B(wParam)
            Form1.GotButtonClick lw
        Case WM_DESTROY
          Call UnSubclass(hWnd, AddressOf F1WndProc, uIdSubclass)
    
          Exit Function
      
      End Select
      
      F1WndProc = DefSubclassProc(hWnd, uMsg, wParam, lParam)
    
    End Function
    Edit2: I guess you can't use AddressOf within the procedure you want the address for after all, because a loop around worked.
    Code:
          Call UnSubclass(hWnd, PtrF1WndProc, uIdSubclass)
    
    Private Function PtrF1WndProc() As Long
    PtrF1WndProc = FARPROC(AddressOf F1WndProc)
    End Function
    Private Function FARPROC(ByVal lpfn As Long) As Long
    FARPROC = lpfn
    End Function
    Before I head into it, are there any issues with subclassing multiple hwnds to the same wndproc? Would I supply a different ID?
    Last edited by fafalone; Jan 21st, 2015 at 12:01 AM.

  6. #6
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Quote Originally Posted by fafalone View Post
    ... but I definitely like the idea of being able to pass an object to a wndproc, which I've really only done with callbacks.
    Subclass, window and hook procedures are all considered callback procedures as well. Whenever a callback has provision for a pointer-size parameter, you can pass an object pointer to it and have VB automatically cast the pointer to the object itself.

    Quote Originally Posted by fafalone View Post
    ... it seems I can't use the AddressOf function there for some reason... can you not call from inside the proc or something?

    Edit2: I guess you can't use AddressOf within the procedure you want the address for after all, because a loop around worked.
    Yep, that's a known bug. The suggested workaround in the KB article PRB: Recursive Use of AddressOf Operator Fails is qualifying the procedure's name with the module's name. It'll work even if the procedure is Private and thus not shown in the IntelliSense list.

    Quote Originally Posted by fafalone View Post
    Before I head into it, are there any issues with subclassing multiple hwnds to the same wndproc? Would I supply a different ID?
    There shouldn't be any problem having multiple windows go through the same subclass procedure (well, as long as there are no Static variables being used there) because VB's internal message loop will only process 1 message at a time. It's fine for different hWnds to specify the same IDs.

    Quote Originally Posted by fafalone View Post
    ... but having every subclass go to the same wndproc gets to be unmanageable pretty quick, so I'd wind up basically having the same call to point to different wndprocs, ...
    The common subclass procedure is actually the approach recommended by MS in their KB article HOWTO: Subclass a UserControl.



    Here's some test code that might help you master the new subclassing APIs:

    Code:
    Option Explicit 'In a Form
    
    Private Const HALF As Single = 0.5!
    
    Private Declare Function DefSubclassProc Lib "comctl32.dll" Alias "#413" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function SetWindowSubclass Lib "comctl32.dll" Alias "#410" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, Optional ByVal dwRefData As Long) As Long
    Private Declare Function RemoveWindowSubclass Lib "comctl32.dll" Alias "#412" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long) As Long
    
    Private Sub Form_Load()
        Controls.Add("VB.PictureBox", "PicBox1").Visible = True
        Controls.Add("VB.PictureBox", "PicBox2").Visible = True
    
        If DoEvents Then    'See whether the 1st Form is already visible
            Show
            Move Screen.Width * HALF, (Screen.Height - Height) * HALF
        Else
            Show
            Move Screen.Width * HALF - Width, (Screen.Height - Height) * HALF
            Forms.Add(Name).Caption = "Form2"
        End If
    
       'Subclass both PictureBoxes. Different hWnds, same WndProc, same IDs.
        SetWindowSubclass Me!PicBox1.hWnd, AddressOf StaticSubclassProc, 1&, ObjPtr(Me)
        SetWindowSubclass Me!PicBox2.hWnd, AddressOf StaticSubclassProc, 1&, ObjPtr(Me)
    
       'Subclass this window twice. Same hWnd, same WndProc, different IDs.
        SetWindowSubclass hWnd, AddressOf StaticSubclassProc, 20&, ObjPtr(Me)
        SetWindowSubclass hWnd, AddressOf StaticSubclassProc, 300&, ObjPtr(Me)
    
       '2 instances of this Form will be subclassed twice.
       'Different hWnds, same WndProc, same set of different IDs.
    End Sub
    
    Private Sub Form_Resize()
        Const GAP = 75!, GAP2 = GAP + GAP
        Dim HalfHeight As Single
    
        On Error Resume Next
        HalfHeight = (ScaleHeight - (GAP + GAP2)) * HALF
        Me!PicBox1.Move ScaleLeft + GAP, ScaleTop + GAP, ScaleWidth - GAP2, HalfHeight
        Me!PicBox2.Move ScaleLeft + GAP, HalfHeight + GAP2, ScaleWidth - GAP2, HalfHeight
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        RemoveWindowSubclass Me!PicBox1.hWnd, AddressOf StaticSubclassProc, 1&
        RemoveWindowSubclass Me!PicBox2.hWnd, AddressOf StaticSubclassProc, 1&
    
       'The subclasses can be removed in any order, not just reverse
        RemoveWindowSubclass hWnd, AddressOf StaticSubclassProc, 20&
        RemoveWindowSubclass hWnd, AddressOf StaticSubclassProc, 300&
    End Sub
    
    Friend Function SubclassProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Long) As Long
        Const WM_LBUTTONDOWN = &H201&, WM_NCLBUTTONDOWN = &HA1&
    
        Select Case uMsg
            Case WM_LBUTTONDOWN, WM_NCLBUTTONDOWN   'Left-click to print uIdSubclass in Immediate Window
                Select Case hWnd
                    Case Me.hWnd:         Debug.Print Caption, uIdSubclass
                    Case Me!PicBox1.hWnd: Debug.Print Caption; "."; Me!PicBox1.Name, uIdSubclass
                    Case Me!PicBox2.hWnd: Debug.Print Caption; "."; Me!PicBox2.Name, uIdSubclass
                End Select
        End Select
    
        SubclassProc = DefSubclassProc(hWnd, uMsg, wParam, lParam)
    End Function
    Code:
    Option Explicit 'In a standard module
    
    Public Function StaticSubclassProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Form1) As Long
        StaticSubclassProc = dwRefData.SubclassProc(hWnd, uMsg, wParam, lParam, uIdSubclass)
    End Function           ' A total of 8 subclass procedures pass through here
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  7. #7

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Thanks, I'll be using this method in the future. The only reason i was hesitant was because it seemed better for object modules, and i don't like having multiple subclassing methods since i do far more subclasses for controls than for forms. New method is working fine for controls too now.

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Good old off-by-one errors...

    The Str2IntA function that this project has for the tooltips on the taskbar thumbnail buttons was:
    Code:
    Private Function Str2Inta(sz As String, iOut() As Integer) As Integer
    Dim i As Long
    ReDim iOut(259)
    For i = 1 To Len(sz)
        iOut(i) = AscW(Mid(sz, i, 1))
    Next i
    End Function
    But since strings are 1-based, this function would mean iOut(0)=0, and ITaskbarList considers the first zero as terminating. Changing it to iOut(i-1) will result in working tooltips.

    Code:
    Private Function Str2Inta(sz As String, iOut() As Integer) As Integer
    Dim i As Long
    ReDim iOut(259)
    For i = 1 To Len(sz)
        iOut(i - 1) = AscW(Mid(sz, i, 1))
    Next i
    
    End Function

  9. #9
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Quote Originally Posted by fafalone View Post
    The Str2IntA function ...
    Why is it a function? It doesn't seem to be returning anything...
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  10. #10

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    I eliminated the parts of an original function that returned a positive value with the length or a negative value (input too long or zero) since it wasn't needed for this project, but neglected to change it to a sub. Apologies, I'll fix it.

  11. #11
    Addicted Member
    Join Date
    May 2016
    Location
    China
    Posts
    197

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    How to capture the three add button click event?

  12. #12

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Through the WM_COMMAND messages; the demo shows fhe specifics.

    The command to add the buttons includes an hWnd, you subclass that hWnd (almost always the form that shows in the taskbar), and the WM_COMMAND messages are sent to the WndProc; the LoWord of the wParam is the ID of the button that was clicked, with that ID being set when you add the button.

    Code:
    Public Function F1WndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
    On Error GoTo e0
      Select Case uMsg
    
        Case WM_COMMAND
            Dim lw As Integer
            lw = LoWord_B(wParam)
            Form1.GotButtonClick lw
        Case WM_DESTROY
          Call UnSubclass(hWnd, PtrF1WndProc, uIdSubclass)
    
      End Select
      
      F1WndProc = DefSubclassProc(hWnd, uMsg, wParam, lParam)
    Exit Function
    e0:
    Debug.Print "F1WndProc.Error->" & Err.Description
    End Function
    Public Function LoWord_B(ByVal LongVal As Long) As Integer
        LoWord_B = LongVal And &HFFFF&
    End Function
    
    
    Private Sub Command3_Click()
    'Add buttons
    'There's 2 ways to do the images; either specify an hIcon in each THUMBBUTTON
    'or assign an imagelist and an index
    Dim i As Long
    Dim pInt() As Integer
    Dim pButtons() As THUMBBUTTON
    ReDim pButtons(2) 'basic 3-button setup
    
    arIcon(0) = ResIconToHICON("ICO_LEFT", 32, 32)
    arIcon(1) = ResIconToHICON("ICO_UP", 32, 32)
    arIcon(2) = ResIconToHICON("ICO_RIGHT", 32, 32)
    
    Call Subclass(Me.hWnd, AddressOf F1WndProc)
    'Call SubclassForm(Me)
    With pButtons(0)
        .dwMask = THB_FLAGS Or THB_TOOLTIP Or THB_ICON
        .iid = 100
        .dwFlags = THBF_ENABLED
        Call Str2Inta("Stop", pInt)
        For i = 0 To UBound(pInt)
            If pInt(i) <> 0 Then Debug.Print "szTip(" & i & ")=" & pInt(i)
            .szTip(i) = pInt(i) 'this doesn't seem to be working... will address in a future release
        Next i
        .hIcon = arIcon(0)
    End With
    With pButtons(1)
        .dwMask = THB_FLAGS Or THB_TOOLTIP Or THB_ICON
        .iid = 101
        .dwFlags = THBF_ENABLED
        Call Str2Inta("Play", pInt)
        For i = 0 To 259
            .szTip(i) = pInt(i)
        Next i
        .hIcon = arIcon(1)
    End With
    With pButtons(2)
        .dwMask = THB_FLAGS Or THB_TOOLTIP Or THB_ICON
        .iid = 102
        .dwFlags = THBF_ENABLED
        Call Str2Inta("Eject", pInt)
        For i = 0 To 259
            .szTip(i) = pInt(i)
        Next i
        .hIcon = arIcon(2)
    End With
    
    iTBL.ThumbBarAddButtons Me.hWnd, 3, VarPtr(pButtons(0))
    
    
    End Sub


    Also, project attachment updated to change the reference to oleexp3.tlb. Previously it referenced the ancient setup of oleexp.tlb+olelib.tlb, from before I combined those both into oleexp3. The reference switch is the only change so a re-dl isn't really needed.
    Last edited by fafalone; Jul 28th, 2016 at 01:51 AM.

  13. #13
    Addicted Member
    Join Date
    May 2016
    Location
    China
    Posts
    197

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Thank you, but the code does not respond to any information, I use the system is windows 10

  14. #14

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Are you running the sample directly or using it on your own form? Do the buttons appear at all?

    There's nothing in there that's incompatible with Win10.

  15. #15
    Addicted Member
    Join Date
    May 2016
    Location
    China
    Posts
    197

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Has found the reason: you need to compile, can not be in the IDE state.

  16. #16
    Addicted Member
    Join Date
    May 2016
    Location
    China
    Posts
    197

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    The problem is solved: as long as the compiler can, in the IDE state is no effect.

  17. #17

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Advanced VBA programming has always wanted subclassing code integrated in the module object.

  18. #18

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    I'm not following; are you saying this won't work in VBA because the subclassing code is in a module instead of the class/form?

  19. #19
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    I wonder if he has his IDE manifested.

  20. #20
    New Member
    Join Date
    Feb 2019
    Posts
    1

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Dear Fafalone,

    Sorry to bother you but I have a few questions if you don't mind. I would very much like to call SetTabOrder from ITaskBarList3. I understand you have implemented the above by way of referencing to your oleexp.tlb extension. Unfortunately I don't think I am unable to implement or distribute this on my employers system, which is heavily locked down. I can put code in the VBA editor in word/excel, sign it, and run it that way, make use of whatever references are already available, but that's it.

    I wonder if it is reasonable to attempt to access ITLB3's in this way. I am able to access ITaskBarList using Philipp Stiefel's code from http://codekabinett.com/rdumps.php?L...w-itaskbarlist which uses only Private Declare PtrSafe Function in a class module and some kind of offset system he has worked out. Although I can follow his explanation well enough and sometimes work out how to implement a dll call from Microsoft's mainly C based explanations I have no experience of referencing extension(s) to methods and VBA doesn't seem to offer much in the way of error handling or debugging this kind of thing (other than last dll error).

    Do you think it would be possible to extend Mr Stiefel's code, or code a similar method to access SetTabOrder or am I barking up the wrong tree? Could you give any thoughts of point me in the right direction? Thanks for your time.

    Also on the off chance anyone knows a better way to achieve what attempting I'm open to ideas! Basically I want to force one particular excel workbook to appear first in the tab order within excel, and although I open it first in the first place it has some macros which wait for other programs to respond, which cause it to display 'not responding' for a few seconds, and after which excel moves it to the last tab position. As I understand it it is a similar process in windows as recovering from a crash, and explorer just put's the tabs back in 'z-order'. Further info or insights appreciated!

    Thanks Robin

  21. #21

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    aatz, the TLB is a requirement for the IDE only. Once your program is compiled, it no longer needs the TLB. You can put the exe on computers without it and it will run, because everything that's used is compiled directly into the exe.

    The TLB can be used in VBA but it would have to be present, as there's no way to compile VBA code into an executable.

    If neither of those options are possible, yes you can use code like you linked to, only creating 3/4 instead of the base. Or there's calling the vtable directly: I'm not aware of a VB/VBA example for ITaskbarList, but you can learn the general technique from LaVolpe's IFileDialog project (good for comparison too as I have a TLB version of using it).

    ps - No need to apologize, I'm always happy to help anyone with my projects. Ask all the questions you need to
    Last edited by fafalone; Feb 15th, 2019 at 04:03 PM.

  22. #22
    Hyperactive Member
    Join Date
    Aug 2017
    Posts
    380

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Quote Originally Posted by fafalone View Post
    ... I'm not aware of a VB/VBA example for ITaskbarList, ...
    Olaf posted a VB6 example for ITaskbarList3 a few years back.

  23. #23
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Hi fafalone,

    Does this work only with non-owned windows ?

    I have applied the ITaskBarList3 functionality to a vba userform (vba userforms are owned to the host excel application main window)

    Result:
    It doesn't actually display a sperate taskbar button for the userform ... It only shows a preview popup of the form's window when mouse-hovering the Excel button in the taskbar ..I am Using Windows 10

    Regards.

    LATE EDIT:
    Just realised the groupig of taskbar buttons is a taskbar setting which can be enabled\disabled via the local group policy editor (gpedit.msc). See here : https://www.tenforums.com/tutorials/...s-windows.html

    Now, the question becomes :
    Does the ITaskbarList3 interface offer a method for overrinding this setting so that owned windows can have their own seperate taskbar buttons regardless of the user's default taskbar configuration?
    Last edited by JAAFAR; Feb 5th, 2020 at 03:59 PM.

  24. #24
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Ok- I have done some research (Found very little info for VB6\VBA) but I have found: https://docs.microsoft.com/en-us/win...storeforwindow

    The SHGetPropertyStoreForWindow API accepts the window hwnd and can give you a pointer to the IPropertyStore interface so you can then call the SetValue Method in order to control the application's taskbar grouping.

    I have somehow managed to add a sperate taskbar button for the userform (Using the above mentioned SHGetPropertyStoreForWindow API and the ITaskbarList3 Interface) but i am not sure I fully understand the PROPVARIANT structure and how to use it correctly... If someone who knows can explain this to me, I would much appreciate it.

    Also, I have found that the PROPERTYKEY ID value that works for ungrouping taskbar buttons happens to be 5 ... Is there some documentation on these Key IDs ?

    Regards.

  25. #25

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Look through the sample projects on the oleexp page, there's tons of examples of using PROPVARIANTs with IPropertyStore values.

    Basically, for a simple number, you can use an unmodified Variant type. .SetValue(5), or if it's in say a Long, .SetValue(CVar(lngVar))

  26. #26
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Quote Originally Posted by fafalone View Post
    Look through the sample projects on the oleexp page, there's tons of examples of using PROPVARIANTs with IPropertyStore values.

    Basically, for a simple number, you can use an unmodified Variant type. .SetValue(5), or if it's in say a Long, .SetValue(CVar(lngVar))
    Thanks, I'll take a look.

  27. #27
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    The overlay icon not shown in Windows 10.

  28. #28

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Can you provide more details about your Windows 10 version, and whether you're using the demo or your own code with a different icon? It works on Win10 for me:


  29. #29
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    I found the problem. I use small icons in taskbar (there is an option, the caption for that is in my language Greek, but the meaning is that, use of small icons was On). So change that to normal I see the heart..
    Windows 10 Pro
    21H2
    Last edited by georgekar; Feb 13th, 2023 at 04:05 PM.

  30. #30

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    I'm not seeing the overlay when using small icons in Windows 7 either; were you seeing different or just Win10 was in small icons but 7 wasn't for you?

  31. #31
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Currently I have Windows 10 Pro and the code I run was the example you provide. That's all. So if the user (like me which I had the icons small to let them have more space) do the same then the "overlay" has "gone", and have no gain for the user. When I change the icon size on my taskbar I found a +99 on windows Mail app (which I have on taskbar like other applications, in specific position). So that moment I feel bad because I miss information, so I change to normal size. But I think that the size of icons can be evaluated from registry, and if it is small then the info has to go somewhere else (change the icon maybe and place data on a tooltip).

  32. #32
    Lively Member
    Join Date
    Sep 2016
    Posts
    94

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Hi fafalone,
    Like georgekar i use small icons in Win7 taskbar.
    The overlay icon appear only with normal icons.
    Regards

  33. #33

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] Win7 Taskbar Features with ITaskbarList3 (overlay, progress in taskbar, etc

    Ok so it seems you would just have to change the icon itself to a custom one. You could, in principle, dynamically create it, if you didn't want to e.g. make 99 separate ones.

    In any case, to change the main icon during runtime you'd send WM_SETICON to your main form's hwnd.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width