Private nComboIdx As Long
Private nComboNewIndex As Long
property
Code:
Public Property Get ComboHeight() As Long: ComboHeight = cyCombo: End Property
Public Property Get ComboNewIndex() As Long: ComboNewIndex = nComboNewIndex: End Property
Public Property Let SliderAlign(nAlign As TDInputBoxAlign): nSliderAlign = nAlign: End Property
and finally I made these changes to ComboAddItem and at the same time cut down on the use of UBound() to make the code a tad more efficient
Code:
Public Sub ComboAddItem(sText As String, Optional iImage As Long = -1, Optional iOverlay As Long = -1, Optional lParam As Long = 0)
If aComboItems(0).sText = "" Then
aComboItems(0).sText = sText
aComboItems(0).iImage = iImage
aComboItems(0).iOverlay = iOverlay
aComboItems(0).lpData = lParam
Exit Sub
End If
nComboNewIndex = UBound(aComboItems) + 1
ReDim Preserve aComboItems(nComboNewIndex)
aComboItems(nComboNewIndex).sText = sText
aComboItems(nComboNewIndex).iImage = iImage
aComboItems(nComboNewIndex).iOverlay = iOverlay
aComboItems(nComboNewIndex).lpData = lParam
If hCombo Then
CBX_InsertItem hCombo, sText, iImage, iOverlay, lParam
End If
End Sub
Maybe you prefer the repeated calls to UBound as your coding style, I just try to avoid unnecessary calls :-)
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
Hi again, I think I have found something at least I concider to be a bug.
In the ProcessCallback function, if the combostyle is editable and the combo text field is left empty when submitting the dialog (in this case clicking a custom button)
Code:
Case TDN_DESTROYED
If hEditBox Then
Dim lLen As Long, sText As String
lLen = SendMessageW(hEditBox, WM_GETTEXTLENGTH, 0, ByVal 0&) * 2
If lLen Then
sText = Space$(lLen)
Call SendMessageW(hEditBox, WM_GETTEXT, lLen, ByVal sText)
sEditText = StrConv(sText, vbFromUnicode)
End If
End If
If hCombo Then
sComboText = GetComboTextW(hEditCombo)
the sComboText variable will get assigned a Chr$(0) so you can never make the test
Code:
If len(Trim$(.ResultComboText)) > 0 Then
or
Code:
If Trim$(.ResultComboText) = "" Then
so I think the returned string somehow needs to be tested for Chr$(0) and removed if exists.
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
ah good call, I'd tend to fix it at the source, GetComboText was adding a 1 to the length even if it was 0. Can't recall if the extra 1 is needed for anything or not, but in case:
Code:
Private Function GetComboTextW(hEdit As Long) As String
Dim bytS() As Byte
Dim ch As Long
ch = SendMessageW(hEdit, WM_GETTEXTLENGTH, 0, ByVal 0&) * 2
If ch = 0& Then Exit Function
ch = ch + 1
ReDim Preserve bytS(ch)
ch = SendMessageW(hEdit, WM_GETTEXT, ch, ByVal VarPtr(bytS(0))) * 2 - 1
If ch >= 0 Then
ReDim Preserve bytS(ch)
End If
GetComboTextW = CStr(bytS)
End Function
The return on that len=0 for empty boxes.
Will also add the other parts of the extra data you found, thanks.
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
ooou, another one maybe, at least the code doesn't make sense to me.
Code:
Public Sub EnableButton(ButtonID As Long, lEnable As Long)
'lEnable=0 disable; <>0 enable
...
Else
Dim lnew() As Long
ReDim lnew(0)
Dim i As Long, k As Long
For i = 0 To UBound(lBtnDis)
If lBtnDis(i) <> ButtonID Then
ReDim Preserve lnew(k)
lnew(k) = lBtnDis(i)
End If
Next
lBtnDis = lnew
End If
...
End Sub
doesn't variable k need to be incremented here? and is the first ReDim of lnew() really necessary?
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
Good catches, I'll update the project when I have a chance.
1st redim is probably not neccessary but I've gotten burned by trying to refer to ubound(array) only to be told it's out of bounds so many times I've gotten in the habit of immediately putting redim(0) after declaring an array since it will usually help and doesn't hurt.
Last edited by fafalone; May 23rd, 2021 at 08:51 PM.
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
Here is another one, SimpleDialog shouldn't it be 'As TDRESULT' rather than 'As TDBUTTONS' ? As it is now the intellisense gives wrong suggestions, which doesn't match with what's returned.
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
i have a string conversion problem when using the class on a chinese windows system.
The function StrConv converts the characters from a string wrong:
BEFORE:
AFTER:
Everyone should avoid to use the function StrConv if your app will run on a windows system with unicode language like chinese, russian etc.
Do you have a replacement for the StrConv-function?
Maybe a self-written function to convert the wide-unicode-string to a VB-String?
The StrConv is used here in your code:
Code:
Public Property Get InputText() As String
If hEditBox Then
Dim lLen As Long, sText As String
lLen = SendMessageW(hEditBox, WM_GETTEXTLENGTH, 0, ByVal 0&) * 2
If lLen Then
sText = Space$(lLen)
Call SendMessageW(hEditBox, WM_GETTEXT, lLen, ByVal sText)
sEditText = StrConv(sText, vbFromUnicode)
Else
sEditText = vbNullString
End If
End If
InputText = sEditText
End Property
Code:
Case TDN_DESTROYED
If hEditBox Then
Dim lLen As Long, sText As String
lLen = SendMessageW(hEditBox, WM_GETTEXTLENGTH, 0, ByVal 0&) * 2
If lLen Then
sText = Space$(lLen)
Call SendMessageW(hEditBox, WM_GETTEXT, lLen, ByVal sText)
sEditText = StrConv(sText, vbFromUnicode)
End If
End If
I fixed the problem with the wrong text conversion!
Now the TaskDialog returns the correct unicode string!
Can you add the fix to your next release?
I added this API declaration:
Code:
Private Declare Function SendMessageW2 Lib "user32" Alias "SendMessageW" (ByVal hWnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
And changed the code from:
Code:
Case TDN_DESTROYED
If hEditBox Then
Dim lLen As Long, sText As String
lLen = SendMessageW(hEditBox, WM_GETTEXTLENGTH, 0, ByVal 0&) * 2
If lLen Then
sText = Space$(lLen)
Call SendMessageW(hEditBox, WM_GETTEXT, lLen, ByVal sText)
sEditText = StrConv(sText, vbFromUnicode)
End If
End If
to
Code:
Case TDN_DESTROYED
If hEditBox Then
Dim lLen As Long, sText As String
lLen = SendMessageW(hEditBox, WM_GETTEXTLENGTH, 0, ByVal 0&) * 2
If lLen Then
sText = Space$(lLen)
Call SendMessageW(hEditBox, WM_GETTEXT, lLen, StrPtr(sText))
sEditText = Left$(sText, InStr(sText, Chr$(0)) - 1)
End If
End If
and i changed this code:
Code:
Public Property Get InputText() As String
If hEditBox Then
Dim lLen As Long, sText As String
lLen = SendMessageW(hEditBox, WM_GETTEXTLENGTH, 0, ByVal 0&) * 2
If lLen Then
sText = Space$(lLen)
Call SendMessageW(hEditBox, WM_GETTEXT, lLen, ByVal sText)
sEditText = StrConv(sText, vbFromUnicode)
Else
sEditText = vbNullString
End If
End If
InputText = sEditText
End Property
to
Code:
Public Property Get InputText() As String
If hEditBox Then
Dim lLen As Long, sText As String
lLen = SendMessageW(hEditBox, WM_GETTEXTLENGTH, 0, ByVal 0&) * 2
If lLen Then
sText = Space$(lLen)
Call SendMessageW2(hEditBox, WM_GETTEXT, lLen, StrPtr(sText))
sEditText = Left$(sText, InStr(sText, Chr$(0)) - 1)
Else
sEditText = vbNullString
End If
End If
InputText = sEditText
End Property
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
@Mith, thanks, will add to next release.
@Visualman: This is expected behavior. .ResultComboText is only meant to return the text of a regular combobox, not the item text for the DropdownList style. If you need to refer back to the item text for a dropdownlist item, you can store the entries in a module-level variable before adding them to the class, then access that variable based on the returned index.
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
Hi
Kindly some one help with setting up Progressbar for Taskdialog.
I cannot figureout how to interact with progress to update it after it shows in my Sub.
You cannot open it as non-blocking so you can update progress manulayy whenever I need as required during my code is running.
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
There's an example of that in the set of examples in the first couple posts:
The TaskDialog supports having a progress bar, both regular and marquee. To enable it, include the TDF_SHOW_PROGRESS_BAR or the TDF_SHOW_MARQUEE_PROGRESS_BAR flag (you can switch back and forth between them while the dialog is open if you want). Getting it to show up is the easy part, linking it to actual events in your program is where it gets a little tricky. There's some events that are provided that will help out...
TaskDialog_DialogCreated is triggered when the dialog is displayed, then all the buttons, the radio buttons, the expando button, the checkbox, and hyperlinks all have events when the user clicks them. In addition to that, TaskDialog_Timer is sent approximately every 200ms and includes a variable telling you how many ms has elapsed since the dialog appeared, or since it was reset with the .ResetTimer() call. The example shows a basic counter, but you can go further and enable/disable buttons and use hyperlinks to control things too.
Code:
Private bRunProgress As Boolean
Private lSecs As Long
With TaskDialog1
.Init
.MainInstruction = "You're about to do something stupid."
.Content = "Are you absolutely sure you want to continue with this really bad idea? I'll give you a minute to think about it."
.IconMain = TD_INFORMATION_ICON
.Title = "cTaskDialog Project"
.Footer = "Really, think about it."
.Flags = TDF_USE_COMMAND_LINKS Or TDF_SHOW_PROGRESS_BAR Or TDF_CALLBACK_TIMER
.AddCustomButton 101, "YeeHaw!" & vbLf & "Put some additional information about the command here."
.AddCustomButton 102, "NEVER!!!"
.AddCustomButton 103, "I dunno?"
.VerifyText = "Hold up!"
bRunProgress = True
.ShowDialog
End With
Private Sub TaskDialog1_DialogCreated(ByVal hWnd As Long)
If bRunProgress Then
Timer1.Interval = 1000
Timer1.Enabled = True
TaskDialog1.ProgressSetRange 0, 60
End If
End Sub
Private Sub TaskDialog1_Timer(ByVal TimerValue As Long)
If lSecs > 60 Then
Timer1.Enabled = False
bRunProgress = False
Else
TaskDialog1.ProgressSetValue lSecs
TaskDialog1.Footer = "You've been thinking for " & lSecs & " seconds now..."
End If
End Sub
Private Sub TaskDialog1_VerificationClicked(ByVal Value As Long)
If Value = 1 Then
Timer1.Enabled = False
bRunProgress = False
Else
bRunProgress = True
Timer1.Enabled = True
End If
End Sub
Private Sub Timer1_Timer()
lSecs = lSecs + 1
End Sub
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
Hi
Thanks for your quick response. This is what I have already explored and workin gok for examples for progressbars we have.
But my issue is I have subs in a Module (one example is attached for Microsoft Access). If I run the Taskdialog before the actual tasks in my subs, I cannot go back to update the progress as Taskdialog does not let even if I don't bind hwnd to nothing.
Secondly If I take all my sub into Taskdialog timer event, it's all gets crazy.
Is there no way to just open the dialog and then within my sub I just update the progress wheneve something is completed.
I'm using Statusbar progress monitor in my sub but I wan t to replace it with Taskdialog as I repaced all other messagebox with it.
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
Just like the MsgBox, the TaskDialog isn't asynchronous so the only option that doesn't involve doing it through the timer callback would be running it in a different thread. Which is very difficult in VB6 and I don't know if it can even be done in VBA; perhaps this kind of progress dialog is more appropriate for the task?
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
This project now has a Universal version that works in twinBASIC x86/x64 and VBA7 x84/x64, in addition to VB6 and VBA6.
For now I'm leaving the version in this thread up, but the next feature update will use the universal codebase (you could drop in cTaskDialog.cls and modTDHelper from the universal codebase into the VB6 version in this thread too).
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
Hello, I'm here to report something.
This line (2361)
Code:
Public Function SimpleDialog(sMessage As String, Optional dwBtn As TDBUTTONS = TDCBF_OK_BUTTON, Optional sTitle As String, Optional sMainText As String, Optional dwIco As TDICONS, Optional hWndOwner As Long, Optional hinst As Long) As TDBUTTONS
Shouldn't it be
Code:
Public Function SimpleDialog(sMessage As String, Optional dwBtn As TDBUTTONS = TDCBF_OK_BUTTON, Optional sTitle As String, Optional sMainText As String, Optional dwIco As TDICONS, Optional hWndOwner As Long, Optional hinst As Long) As TDRESULT
If you go with the former, you'll get the wrong result. Like when you expect the result to be Cancel, you'll get Yes instead.
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
I am trying to do a dialog with .Flags = TDF_COMBO_BOX Or TDF_INPUT_BOX Or TDF_DATETIME
all of them with the align set to TDIBA_Content
Looks like it will not work
is there any way around it?
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
It's not currently supported... it was very difficult to account for all positioning issues with just a single custom control; having multiple ones in the same area would greatly increase the complexity, and I haven't accounted for that in the current version. You can have any single custom control with any combination of built in controls, but just the one for now.
It *might* work ok if you put them in different alignment slots (ComboAlignInContent, InputAlignInContent, DateTimeAlignInContent), but I can't promise that.
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
They're not traditional elements with hwnds; they're locked behind Microsoft's undocumented DirectUI rendering system, so there's no easy way to change their color I'm aware of. Your best option might be changing them globally through the Theme API (hopefully a Microsoft-provided theme or the color options for them will do it (right click desktop, personalize->themes), otherwise the options become complicated as MS locked themes down to prevent people from restoring the superior Windows 7 look). There might also be a way in through the accessibility APIs, though even if you did find the underlying control hwnd I don't know the renderer would respond to API-called based changes.
Can you tell me any more about the errors in more recent versions? The only issues I'm aware of involve using the universal versions in 64bit Office; quite a lot of testing was done while developing that version (based on the most recent v1.2 32bit-only) and it's been solid in VB6/tB.
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
Sorry I'm getting 'invalid attachment'... sometimes the attachment system here is a little wonky...
If you're using the x64 version one issue I can think of... mTDSample.bas, the module for Demo, isn't written to work in VB6, and you'd get syntax errors; you'd have to use the mTDSample.bas from the VB6 version, which goes with the forms since .twin files can't be opened in VB6. Or if you copy-pasted from tB into VB6 instead of loading the file from the export folder, it would have copied the hidden syntax that is in VB6 files but can't appear in the editor. Is one of these the issue? Just guessing here since I just compiled in VB6, tb 32bit, and tb 64bit again to test without issue and I couldn't see the attachment.
Edit: For the former issue you'll now find a VB6-Demo folder on the project GitHub, you can extract those files to the folder with cTaskDialog.cls and the images, and the mTDSample.bas there will work in VB6 (and twinBASIC 32/64bit, but not Office).
Last edited by fafalone; May 2nd, 2023 at 01:43 PM.
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
Why would you remove the space? It's necessary for the AddressOf operator; AddressOf ProcedureName returns the memory address of the procedure, which is how the API sends data back while the dialog is open.
tdFARPROC is defined (line 2493), and TaskDialogCallbackProc is defined in mTDHelper.bas (line 8)-- did you add that? It has to be in a .bas; you can't just cut/paste mTDHelper's contents into the class.
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
As I mentioned up above, I've been having a lot of problems getting it to work in Office.
For Access, currently I believe you'd be better off using Kevin Bell's 64bit port of cTaskDialog. It's all the same features, it's just an alternative 64bit port of the VB6 version, which for whatever bizarre reason I can't identify, doesn't have the crashes you're heading for even if you do fix the title (which is a known issue)...
(The title line should be changed to
Code:
#If ((VB6 <> 0) Or (VBA7 <> 0)) And (TWINBASIC = 0) Then
m_sTitle = "cTaskDialog"
#Else
m_sTitle = App.Title
#End If
since Office doesn't have an equivalent to App.Title; substitute your own title for cTaskDialog.
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
With VBA64 now fully working, I'm updating this post to v1.3.8 Universal. This attachment on this post contains the VB6 project and form sample updated to work with the universal version (LongPtr), as well as the twinBASIC demo project.
IMPORTANT: For compatibility, this version no longer uses self-subclassing, and like earlier versions, once again requires mTDHelper.bas in all projects. (mTDSample.bas is still only for the demo form).
You can also view this project on GitHub, but currently only this thread has the VB6 sample project/form (even though the code is the same in the cls and twinBASIC form).
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
I don't believe making a whole new class for interfaces is more efficient, no. I'll add notes to the other 2 about not calling them, only one has that now.
Re: [VB6] TaskDialogIndirect - Complete class implementation of Vista+ Task Dialogs
Hi Fafalone
sorry for this stupid and newbie question.
I'm trying to launch your "TaskDialogIndirect" from the VB6 IDE in Win10, but I always get "Error 453, Unable to point entry to comctl32.dll"
The compiled version runs without problems.
How can I solve it? I tried with a manifest in the VB6 folder, but it doesn't work. I'm definitely doing something wrong