Results 1 to 9 of 9

Thread: [twinBASIC/VB6/VBA7] TaskDialogIndirect: cTaskDialog universal implementation x86/x64

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,243

    [twinBASIC/VB6/VBA7] TaskDialogIndirect: cTaskDialog universal implementation x86/x64

    cTaskDialog64 v1.2.4


    Updated on 23 Nov 2022


    This is a version of my cTaskDialog 1.2R2 project that uses conditional compilation to support both VB6/VBA6 and twinBASIC/VBA7 in either x86 or x64. See that page for complete project description and numerous more pictures and examples.
    Notably, people have had difficulty calling this API in VBA7 64bit, because it expects a structure without packing that on 32bit, doesn't happen, but does on 64bit. In twinBASIC, there's the PackingAlignment attribute. For VBA7x64, this project implements a workaround that copies the packed structure (since the attribute is conditionally only applied in tB) into a structure consisting of just the 160 raw bytes the API expects. It does this by copying each individual member to the correct offset, which is done for the button arrays too with the pointer for those set to the workaround ones.

    Since people have asked about using this in VBA, it goes back to the earlier method of using a module to help with subclassing, as the self-subclass code in the last VB6 version only works in VB6, and while twinBASIC supports AddressOf on class members, VBA7 does not. Note that there's a bug in the self-sub version that changes the way multiple pages are handled, sending all events through the first page class. So if you use multiple paged Task Dialogs, you'll now need to relocate events for the other pages to their own event Subs (the Demo does this with it's multi-page Demos).

    LongPtr in VB6/VBA?
    You'll need to add LongPtr support to use this codebase in VB6/VBA6. This thread provides two methods: via a typelib with an alias, or via an enum. For simplicity this project currently uses the Enum method (defined in modHelper.bas).

    In the ZIP
    The zip contains the .twinproj for twinBASIC, and an export directory with the project sources. You don't need the images in other projects, but you might need the manifest. The images in the root folder are just for the demo too.

    IMPORTANT: For full compatibility with all platforms, the class relies on external module to help with subclassing, so you must additionally add mTDHelper.bas to any project you add cTaskDialog.cls to (you do not need mTDSample for other projects, it's just for the Demo app).

    For twinBASIC, this projects requires Beta 108 or newer, although the latest Beta 154 is recommended to avoid an issue with an erroneous error saying GetSystemImageList is ambiguous (if you do wish to use an earlier version, restarting the compiler will get rid of that).

    Note for users of the previous VB6 version
    For multi-page Task Dialogs, it was actually a bug that all pages had their events raised in the first page's class. This version doesn't have the bug, and events will fire in the actual class of each page. So if you use multi-page dialogs, keep that in mind when switching to this version.


    UPDATED: Version 1.2.4 fixes improper VarPtr calls in the VBA7x64 routines in ShowDialog and NavigatePage.

    Version 1.2.3 fixes a repositioning issue on system with certain visual effects disabled. When min/max animation was disabled, the main window was resized immediately, so when it checked for a difference from the old value, there was none.

    Version 1.2.2 fixes the font scaling issues on some systems, the logo position/transparency issue, an issue with the dialog resizing too small after unexpanding an expando, the Long instead of LongPtr in one unused Sub, and a bug with different behavior in a page of a multi-page task dialog if you navigate back to it after loading another. Also adds a default date/time (Now) for disabled check datetimes, and the twinBASIC Logo Demo shows querying the class for current DPI to load a larger image if needed.



    This project can be downloaded from it's repository on GitHub, if you want to use that to report bugs or make feature requests (you can still do it here too). I'm no longer maintaining two separate points of download, gotta be honest they'll just get out of sync.
    Last edited by fafalone; May 2nd, 2023 at 01:40 PM.

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,243

    Re: [twinBASIC/VBA7/VB6] TaskDialogIndirect: cTaskDialog universal implementation x86

    As a comparison, here's an x86-only twinBASIC version that's just a direct import of the VB6 project with the subclassing/callback method changed to use tB's AddressOf on class members instead of the incompatible ASM thunks in the VB6 version. Other than that it works with no changes.
    Attached Files Attached Files

  3. #3
    New Member
    Join Date
    Sep 2021
    Location
    Braselton, GA
    Posts
    2

    Re: [twinBASIC/VBA7/VB6] TaskDialogIndirect: cTaskDialog universal implementation x86

    You might want to mention what version(Beta#) of twinBasic this is good for/as-of.

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,243

    Re: [twinBASIC/VB6] TaskDialogIndirect: cTaskDialog dual implementation x86/x64

    Any recent version should be fine... looking back, I'd say Beta 108 is probably when support starts, because it uses the PackingAlignment attribute. If you have 153 or earlier you might get an erroneous 'GetSystemImageList is ambiguous' error that goes away if you restart the compiler.

    (Which btw, I forgot about, I've temporarily removed the download while I fix it)
    Last edited by fafalone; Oct 21st, 2022 at 08:30 PM.

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,243

    Re: [twinBASIC/VB6/VBA7] TaskDialogIndirect: cTaskDialog universal implementation x86

    Ok, project updated. The PackingAlignment attribute is inside a conditional compilation argument only for twinBASIC. In VB6 and 32bit VBA, it doesn't matter. For 64bit VBA7, I've implemented imo a rather clever workaround...

    Code:
    #If VBA7 Then
    	
        #If (Win64 <> 0) And (TWINBASIC = 0) Then
        	
            'VBA7 does not support the packing alignment attribute that makes calling this easy in twinBASIC; x64 inserts padding this particular API doesn't expect.
        	Private Type TASKDIALOG_BUTTON_VBA7
                data(11) As byte
            End Type
            Private m_uButtons_VBA7() As TASKDIALOG_BUTTON_VBA7
            Private m_uRadioButtons_VBA7() As TASKDIALOG_BUTTON_VBA7
            Private Type TASKDIALOGCONFIG_VBA7
                data(159) As Byte
            End Type
            Private uTDC_VBA7 As TASKDIALOGCONFIG_VBA7
            Private Declare PtrSafe Function TaskDialogIndirect_VBA7 Lib "comctl32.dll" Alias "TaskDialogIndirect" (pTaskConfig As TASKDIALOGCONFIG_VBA7, _
                                                                            pnButton As Long, _
                                                                            pnRadioButton As Long, _
                                                                            pfVerificationFlagChecked As Long) As Long
        #End If
    The correct structure size is 160 bytes; declaring it like that avoids the insertion of alignment bytes, which will cause the API to fail because VBA7 doesn't support manually aligned structures if the members are separate.
    But the main structure is used everywhere, it must be a mess, right? Nope... the only place the alternate is used is right where the API is called, so only in the ShowDialog and Navigate procedures... there, I copy each individual member from the (in VBA7x64) incorrectly aligned structure to the correct offset in the byte field of the alternate:

    Code:
    #If (VBA7 <> 0) And (TWINBASIC = 0) And (Win64 <> 0) Then
    'Special handling for 64bit VBA7, which doesn't support our manually aligned structure.
        ReDim m_uButtons_VBA7(uTDC.cButtons)
        Dim i As Long
        If uTDC.cButtons Then
            For i = 0 to uTDC.cButtons - 1
                CopyMemory m_uButtons_VBA7(i).data(0), m_uButtons(i).nButtonID, 4
                CopyMemory m_uButtons_VBA7(i).data(4), m_uButtons(i).pszButtonText, 8
            next i
        End If
        ReDim m_uRadioButtons_VBA7(uTDC.cRadioButtons)
        If uTDC.cRadioButtons Then
            For i = 0 To uTDC.cRadioButtons - 1
                CopyMemory m_uRadioButtons_VBA7(i).data(0), m_uRadioButtons(i).nButtonID, 4
                CopyMemory m_uRadioButtons_VBA7(i).data(4), m_uRadioButtons(i).pszButtonText, 8
            next i
        End If
        Dim ptrBtn As LongPtr, ptrRbn As LongPtr
        ptrBtn = VarPtr(m_uButtons_VBA7(0)): ptrRbn = VarPtr(m_uRadioButtons_VBA7(0))
        CopyMemory uTDC_VBA7.data(0), uTDC.cbSize, 4: CopyMemory uTDC_VBA7.data(4), uTDC.hWndParent, 8: CopyMemory uTDC_VBA7.data(12), uTDC.hInstance, 8
        CopyMemory uTDC_VBA7.data(16), uTDC.dwFlags, 4: CopyMemory uTDC_VBA7.data(20), uTDC.dwCommonButtons, 4: CopyMemory uTDC_VBA7.data(24), uTDC.pszWindowTitle, 8
        CopyMemory uTDC_VBA7.data(32), uTDC.pszMainIcon, 8: CopyMemory uTDC_VBA7.data(40), uTDC.pszMainInstruction, 8: CopyMemory uTDC_VBA7.data(48), uTDC.pszContent, 8
        CopyMemory uTDC_VBA7.data(56), uTDC.cButtons, 4: CopyMemory uTDC_VBA7.data(60), ptrBtn, 8: CopyMemory uTDC_VBA7.data(68), uTDC.nDefaultButton, 4
        CopyMemory uTDC_VBA7.data(72), uTDC.cRadioButtons, 4: CopyMemory uTDC_VBA7.data(76), ptrRbn, 8: CopyMemory uTDC_VBA7.data(84), uTDC.nDefaultRadioButton, 4
        CopyMemory uTDC_VBA7.data(88), uTDC.pszVerificationText, 8: CopyMemory uTDC_VBA7.data(96), uTDC.pszExpandedInformation, 8: CopyMemory uTDC_VBA7.data(104), uTDC.pszExpandedControlText, 8
        CopyMemory uTDC_VBA7.data(112), uTDC.pszCollapsedControlText, 8: CopyMemory uTDC_VBA7.data(120), uTDC.pszFooterIcon, 8: CopyMemory uTDC_VBA7.data(128), uTDC.pszFooter, 8
        CopyMemory uTDC_VBA7.data(136), uTDC.pfCallback, 8: CopyMemory uTDC_VBA7.data(144), uTDC.lpCallbackData, 8: CopyMemory uTDC_VBA7.data(156), uTDC.CXWidth, 4
    
        hr = TaskDialogIndirect_VBA7(uTDC_VBA7, pnButton, pnRadButton, pfVerify)    
    #Else
    hr = TaskDialogIndirect(uTDC, pnButton, pnRadButton, pfVerify)
    #End If
    Then something similar in Navigate.

    Let me know if there's any issues with this.

    Note: I originally uploaded the wrong version which has a simple typo in the VBA7 loop, missing = 0. I fixed it after 10 minutes but a couple people already grabbed it, if that's you, sorry
    Last edited by fafalone; Nov 23rd, 2022 at 03:12 PM.

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,243

    Re: [twinBASIC/VB6/VBA7] TaskDialogIndirect: cTaskDialog universal implementation x86


    UPDATED:
    Version 1.2.2 fixes the font scaling issues on some systems, the logo position/transparency issue, an issue with the dialog resizing too small after unexpanding an expando, the Long instead of LongPtr in one unused Sub, and a bug with different behavior in a page of a multi-page task dialog if you navigate back to it after loading another. Also adds a default date/time (Now) for disabled check datetimes, and the twinBASIC Logo Demo shows querying the class for current DPI to load a larger image if needed.

  7. #7

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,243

    Re: [twinBASIC/VB6/VBA7] TaskDialogIndirect: cTaskDialog universal implementation x86

    UPDATED: Version 1.2.3 fixes a repositioning issue on system with certain visual effects disabled. When min/max animation was disabled, the main window was resized immediately, so when it checked for a difference from the old value, there was none.

    Special thanks to Wayne Phillips for figuring this out!

  8. #8
    New Member
    Join Date
    Nov 2022
    Posts
    1

    Re: [twinBASIC/VB6/VBA7] TaskDialogIndirect: cTaskDialog universal implementation x86

    Quote Originally Posted by fafalone View Post
    cTaskDialog64 v1.2.3



    This is a version of my cTaskDialog 1.2R2 project that uses conditional compilation to support both VB6/VBA6 and twinBASIC/VBA7 in either x86 or x64. See that page for complete project description and numerous more pictures and examples.
    Notably, people have had difficulty calling this API in VBA7 64bit, because it expects a structure without packing that on 32bit, doesn't happen, but does on 64bit. In twinBASIC, there's the PackingAlignment attribute. For VBA7x64, this project implements a workaround that copies the packed structure (since the attribute is conditionally only applied in tB) into a structure consisting of just the 160 raw bytes the API expects. It does this by copying each individual member to the correct offset, which is done for the button arrays too with the pointer for those set to the workaround ones.

    Since people have asked about using this in VBA, it goes back to the earlier method of using a module to help with subclassing, as the self-subclass code in the last VB6 version only works in VB6, and while twinBASIC supports AddressOf on class members, VBA7 does not. Note that there's a bug in the self-sub version that changes the way multiple pages are handled, sending all events through the first page class. So if you use multiple paged Task Dialogs, you'll now need to relocate events for the other pages to their own event Subs (the Demo does this with it's multi-page Demos).

    LongPtr in VB6/VBA?
    You'll need to add LongPtr support to use this codebase in VB6/VBA6. This thread provides two methods: via a typelib with an alias, or via an enum. For simplicity this project currently uses the Enum method (defined in modHelper.bas).

    In the ZIP
    The zip contains the .twinproj for twinBASIC, and an export directory with the project sources. You don't need the images in other projects, but you might need the manifest. The images in the root folder are just for the demo too.

    IMPORTANT: For full compatibility with all platforms, the class relies on external module to help with subclassing, so you must additionally add mTDHelper.bas to any project you add cTaskDialog.cls to (you do not need mTDSample for other projects, it's just for the Demo app).

    For twinBASIC, this projects requires Beta 108 or newer, although the latest Beta 154 is recommended to avoid an issue with an erroneous error saying GetSystemImageList is ambiguous (if you do wish to use an earlier version, restarting the compiler will get rid of that).

    Note for users of the previous VB6 version
    For multi-page Task Dialogs, it was actually a bug that all pages had their events raised in the first page's class. This version doesn't have the bug, and events will fire in the actual class of each page. So if you use multi-page dialogs, keep that in mind when switching to this version.


    UPDATED: Version 1.2.3 fixes a repositioning issue on system with certain visual effects disabled. When min/max animation was disabled, the main window was resized immediately, so when it checked for a difference from the old value, there was none.

    Version 1.2.2 fixes the font scaling issues on some systems, the logo position/transparency issue, an issue with the dialog resizing too small after unexpanding an expando, the Long instead of LongPtr in one unused Sub, and a bug with different behavior in a page of a multi-page task dialog if you navigate back to it after loading another. Also adds a default date/time (Now) for disabled check datetimes, and the twinBASIC Logo Demo shows querying the class for current DPI to load a larger image if needed.

    Known Issues
    -Custom control repositioning after expansion is incorrect on some systems. This is related to DPI scaling, but as I'm on a 150% scale myself and it doesn't happen on my system, it's proving difficult to isolate and fix the cause of this without breaking positioning on my system and/or 100% scale.



    This project is also on GitHub, if you want to use that to report bugs or make feature requests (you can still do it here too).



    Good day to you Mr. fafalone,
    I love the work with the task dialog. The folks I work for recently switched to Office 64 bit and I have been using your Task Dialog for their MS Access application. When the switch was made, I grabbed your 64 bit version. When the Showdialog is run the software gets hung up on Line 2485 "ptrBtn = VarPtr(m_uButtons_VBA7): ptrRbn = VarPtr(m_uRadioButtons_VBA7)" with the compile error Type mismatch, In the immediate window I get "DebugAppend Event Line 1527:[2022-11-18 08:44:41] TaskDialogIndirect ret=0x80070057:". The folks I am working with are USCG. Would you be able to assist me in finding a way to get this to work? If so, what would you need from me?

  9. #9

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,243

    Re: [twinBASIC/VB6/VBA7] TaskDialogIndirect: cTaskDialog universal implementation x86

    Apologies, it should be

    ptrBtn = VarPtr(m_uButtons_VBA7(0)): ptrRbn = VarPtr(m_uRadioButtons_VBA7(0))

    There's also the same issue in NavigatePage;

    ptrBtn = VarPtr(uBTN_VBA7): ptrRbn = VarPtr(uRBN_VBA7)

    should be:

    ptrBtn = VarPtr(uBTN_VBA7(0)): ptrRbn = VarPtr(uRBN_VBA7(0))

    I've updated the project in the first post and on GitHub.

    (Have been having trouble getting 64bit Office up and running, so haven't been able to thoroughly test... the error, 0x80070057, is 'Invalid parameter' and likely caused by having a null pointer for the buttons if you skipped over those lines when they errored; so fixing the above should fix that as well)

    Edit: There does seem to be a deeper issue preventing it from working; I managed to get Office installed on a VM and I fixed some other bugs and am trying to resolve it soon. Update: I'm honestly at loss right now; the VBA code to call it by byte array works perfectly under twinBASIC x64 now, but VBA just keeps crashing. I've traced it to the callback method... if I disable the callback, it works... but that also eliminates numerous basic features.
    Last edited by fafalone; Nov 27th, 2022 at 09:23 PM.

Tags for this Thread

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