2020-06-12

FoxyDialogs v1.0 - going much forward with vista TaskDialog API in VFP

Here comes the evolution of a function I've been working for the last days, FOXYDIALOGS. A Visual FoxPro function that makes it simple for us to deal with several types of dialogs.

The new FoxyDialog function brings an easy way for us to have some more up to date dialogs to inform the users, and also a new way to get some simple information in a much more powerful and beautiful INPUTBOX() function.

- up to 6 buttons allowed
- use the default Windows icons, those stored in "IMAGERES.DLL", used by Windows all over, and also any ICO or bitmap file
- a wider dialog window, that stretches to fit all your text
- apart from the WindowTitle and the Contents, you have the "Main Instruction" parameter
- introduced the timeout property
- allows using Unicodes, for some cool characters and Multilanguages
- Icons in buttons, using some default windows images
- New input data types, such as texts, numbers, dates, date and time, date ranges



The primitive version of this function was derived from the excellent sample published in VFPX , by Anatolyi Mogylevets and Tore Bleken - How to display a Task Dialog (Vista). The original sample displays the dialog, but using only the default Windows dialog buttons, such as "Ok, Cancel, Abort, Retry, Yes, No".

This function is leveraging from some amazing VFPX projects: the VFPX Win32 API from Anatolyi Mogylevets and Tore Bleken and VFP2C32, from Christian Ehlcheid.
I also received a great inspiration from "Fafalone" from http://www.vbforums.com/showthread.php?777021-VB6-TaskDialogIndirect-Complete-class-implementation-of-Vista-Task-Dialogs, who used the biggest brother of the TaskDialog API for other very cool usages. Something that I already did, but hope to bring in another post.


These dialogs are Unicode friendly. That means that we can add almost whatever characters we desire. Just search the Web for "UNICODE + Heart", and you'll get the codes for you to try.
For unicodes, it's important to notice that this works with UTF-16 (16 bit Unicode). For Double-byte characters, like the "Thumbs up", pass the 8 digits inside the tag. All unicodes are accepted, you can pass several unicodes separated by a single SPACE.


Function:
  • NEWDIALOG(tcTitle, tcMainInstruction, tcContent, tcnIcon, tcButtons, tnDefault, tnTimeout)

Parameters:
  • tcTitle - string to be used for the task dialog title.

  • tcMainInstruction - string to be used for the main instruction.

  • tcContent - string used for additional text that appears below the main instruction, in a smaller font. 

  • tcnIcon - Character or Integer that identifies the icon to display in the task dialog. 
This parameter can be an integer or some predefined text values, allowing several options.
- If this parameter is EMPTY() or omitted, no icon will be displayed.
- For numeric, the variety of icons is HUGE, all icons stored in the %systemroot%\system32\imageres.dll file. The imageres.dll file contains many icons, used almost everywhere in Windows 10. It has icons for different types of folders, hardware devices, peripherals, actions, and so on. Below in Appendixes 1 and 2 there is a list of the available strings and enumerated icons. In this parameter you can also determine the background color of the dialog main instruction.
- Send a string comma separated, having the desired main icon first, and after the comma a letter representing the background color: R=Red; G=Green; Y=Yellow; S=Silver; B=Blue; Empty() no background, and finally "-" means no left margin. You can also pass a BMP or ICO file - just make sure to have it available on disk, not embedded in your EXE.
  • tcButtons - This parameter determines some important behaviors of the dialog.
For ordinary dialogs, used for you to pass some information to the users, it specifies the push buttons displayed in the dialog box. A single string containing comma separated captions. If you wish to show a disabled button, add a "\" before the caption. All buttons are Unicode friendly, and you can use some special button captions with special extensions, for the very commonly used buttons - Ok, Cancel, Print, Save, Search. Adding a "#" will add some basic unicode icons. Adding an asterisk - "*" will add some colored icons. 
For INPUTBOXES mode, in the first word of the parameter you can add some special characters as well:

  1. "@I" - turns the dialog into a modern INPUTBOX().
    "@IU" or "@I!" - the textbox will accept only UPPERCASE characters
    "@IL" - the textbox will accept only LOWERCASE characters
    "@IN" or "@ID" - numeric (negative and comma accepted) or DIGITS (only integers)
    "@IP" - Password inputbox, shows asterisks for every character
  2. "@D" - DateBox dialog - showing a cool combobox for date picking
  3. "@T" - DateTimeBox dialog - showing the same combobox above and a time inputbox
  4. "@M" - MonthBox dialog - showing a single calendar for date picking
  5. "@R" - DateRangeBox dialog - showing a double month calendar, allowing users to pick some date ranges

  • tcnDefault -

    - For DialogBox mode - numeric, specifies the button Id that will be focused. Default = 1

    - For special InputBox mode - specifies the default values shown when the input dialog is shown: Character for "@I" or Date for "@D", "@M", "@R" or DateTime for "@T" tcButtons type
  • tnTimeout - Specifies the number of milliseconds the dialog will be displayed without input from the keyboard or the mouse before clearing itself. You can specify any valid timeout value. A value of less than 1 never times out until user enters input and behaves the same as omitting the nTimeout parameter. The Timeout parameter can be a numeric value or a Character, with the time in milisseconds, and the string that will come together with the time shown. The tag " < SECS > " will be replaced by the time in seconds, with the small unicode clock. Don't miss the samples below.
Returns:
  • For Regular DialogBox - nId - the Id of the selected button, or 0 (zero) if Cancelled or -1 for timed out
  • For InputBoxes, according to each type, as follows:

    - "@I", "@I!", "@IP" - returns the character entered, or an empty string if "Cancel"
    - "@IN", "@ID" - returns a numeric value, or an empty string if cancelled. - Notice that cancel returns a Character empty string!
    - "@D", "@M" - returns a Date format value
    - "@T" - returns a DateTime format value
    - "@R" - returns an object with two properties: "StartDate" and "EndDate"

There are numerous ways to use it, but after you play with the samples I hope you'll feel comfortable with it. The samples below will show you almost all the most important features available:



Sample 1:

? FoxyDialog("Vista Task Dialog", "The main instruction text for the TaskDialog goes here", ;
 "The content text for the task dialog is shown here and the text will automatically wrap as needed." + CHR(13) + CHR(13) + ;
 "Any expanded content text for the task dialog is shown here and the text will automatically wrap as needed." + CHR(13) + CHR(13) + ;
    "Do you like it?", "OK2", ;
 "Yes!,Not really,I dunno")

Sample 2:

? NewDialog("Bad Username or Password", ;
      "Access Denied", ;
      "You have entered the wrong credentials for 3 times." + CHR(13) + CHR(13) + ;
             "Please wait for 30 minutes and try again, otherwise your account may be suspended.", ;
      "Lock", ;
      "Return")

Sample 3:

? FoxyDialog("Critical error", ;
     "Corrupted Data", ;
     "An unexpected error has occurred and the system needs to be restarted." + ;
         CHR(13) + CHR(13) + "What do you want to do ?", ;
     "X2", ;
     "Restart Now,Restart later,Keep working", ; && Button captions
     2) && Default button


Sample 4: Dialogs using simple timeout, with unicodes - everywhere, titles, contents and even buttons!

? FoxyDialog("Nice job!  <UC>2661 2665 2764</UC>", ;
    "Success! <UC>d83ddc4d</UC>", ;
    "Your account details have been updated successfully." + ;
    CHR(13) + CHR(13) + "You can proceed with the next step to get your cashback!", ;
    "OK2", ;
    "Ok*,Ok <UC>2714</UC>,Ok <UC>D83DDDF9</UC>", ; && Button captions
    1, ;  && Default button
    9000) && Timeout



Sample 5: Unicodes - Multilanguages

Unicode friendly means endless usages, really very easilly. The dialog below uses several languages from different character sets.
To get the Unicodes, first I used Google translator to translate the word "Welcome". The results were pasted to one among many Unicode translators, like Branah - https://www.branah.com/unicode-converter. Just paste your text and it will provides the unicodes. Make sure to check the "Remove \u", and when pasting, make sure to separate every character with a space. In general, for most languages you'll use 4 characters. For double byte languages, like Chinese, Japanese and Korean, or for some special characters, like the "thumbs up", you'll pass every 8 characters at a time.



? FoxyDialog("Playing with Unicodes  <UC>d83ddc4d</UC>", ;
    "Welcome! <UC>2661 2665 2764</UC>", ;
 "   <UC>27a4</UC>  Turkish <UC>0048 006f 015f 0067 0065 006c 0064 0069 006e 0069 007a</UC>" + CHR(13) + ;
 "   <UC>21f0</UC>  Arabic <UC>0623 0647 0644 0627 2000 0628 0643</UC>" + CHR(13) + ;
 "   <UC>2192</UC>  Greek <UC>03ba 03b1 03bb 03c9 03c2 2000 0397 03a1 0398 0391 03a4 0395</UC>" + CHR(13) + ;
 "   <UC>21e8</UC>  Simplified Chinese <UC>6b228fce</UC>" + CHR(13) + ;
 "   <UC>21fe</UC>  Hebrew <UC>05d1 05e8 05d5 05da 2000 05d4 05d1 05d0</UC>" + CHR(13) + ;
 "   <UC>2794</UC>  Japanese <UC>30883046 3053305d</UC>" + CHR(13) + ;
 "   <UC>27a7</UC>  Russian <UC>0434 043e 0431 0440 043e 2000 043f 043e 0436 0430 043b 043e 0432 0430 0442 044c</UC>", ;
    "OK2", ;
    "No! <UC>d83ddec7</UC>,Cancel*,Ok*,Ok <UC>2714</UC>,Ok <UC>D83DDDF9</UC>") && Button captions





Sample 6: Timeout with special caption

? NewDialog("Covid-19 crazy warning - See the timer -->", ;
    "Please stay home!", ;
    " - Clean your hands often." + CHR(13) + ;
    " - Keep a safe distance from anyone who is coughing or sneezing." + CHR(13) + ;
    " - Don’t touch your eyes, nose or mouth." + CHR(13) + ;
    " - Cover your nose and mouth with your bent elbow or a tissue when you cough or sneeze." + CHR(13) + ;
    " - Avoid close contact with people who are sick." + CHR(13) + ;
    " - Stay at home as much as possible." + CHR(13) + ;
    " - Put distance between yourself and other people." + CHR(13) + ;
    " - If you have a fever, cough and difficulty breathing, seek medical attention." + CHR(13), ;
    "!2", ;
    "More Info,I agree,Leave me!", ; && Button captions
    2, ;  && Default button
    "8000,<SECS> secs.") && Timeout








Sample 7: Predefined unicode buttons:
For the basic captions: "Ok, Cancel, Print, Save and Search", add an "*", and the corresponding unicode icon will be added to the button, as below:


? FoxyDialog("Playing with Unicodes in buttons", ;
    "Predefined buttons", ;
 "There are currently 5 predefined buttons that will add a unicode icon automatically." + CHR(13) + CHR(13) + ;
 "Add an asterisk - '*' after the words below, and the corresponding icons will be added to the buttons:" + CHR(13) + CHR(13) + ;
 "     Ok*        <UC>27f6</UC>     Ok <UC>2713</UC>" + CHR(13) + ;
 "     Cancel*    <UC>27f6</UC>     Cancel <UC>d83dddd9</UC>" + CHR(13) + ;
 "     Print*     <UC>27f6</UC>     Print <UC>2399</UC>" + CHR(13) + ;
 "     Save*      <UC>27f6</UC>     Save <UC>d83dddab</UC>" + CHR(13) + ;
 "     Search*    <UC>27f6</UC>     Search <UC>d83ddd0e</UC>", ;
    "I", ;
    "Ok*,Cancel*,Print*,Save*,Search*")  && Button captions




Sample 8: Custom title with no icon, and with background:
Notice the icon parameter - the comma separated string - ",S" means that there will be no main icon, but with a silver background:

* Sample 8
? FoxyDialog("Covid-19 warning", ;
    "Custom title with no icon and background" + CHR(13) + "PLEASE STAY HOME!" + CHR(13) + "I hope you'll keep your word!", ;
    " - Clean your hands often." + CHR(13) + ;
    " - Avoid close contact with people who are sick." + CHR(13) + ;
    " - Stay at home as much as possible." + CHR(13) + ;
    " - Put distance between yourself and other people." + CHR(13) + ;
    " - If you have a fever, cough and difficulty breathing, seek medical attention." + CHR(13), ;
    ",S", ; && No icon, silver background
    "\More Info,I agree,Leave me!") && Button captions, 1st button disabled




Sample 9: Buttons with custom icons, from Imageres.dll and Shell32.dll
Notice the index numbers in the button captions parameters. These come immediately after every caption.

* Sample 9
? FoxyDialog("Covid-19 crazy warning - See the timer -->", ;
    "Please stay home!", ;
    " - Clean your hands often." + CHR(13) + ;
    " - Avoid close contact with people who are sick." + CHR(13) + ;
    " - Stay at home as much as possible." + CHR(13) + ;
    " - Put distance between yourself and other people." + CHR(13) + ;
    " - If you have a fever, cough and difficulty breathing, seek medical attention." + CHR(13), ;
    "!2", ; && Exlamation default with yellow backgound (default)
    "\More Info_99,I agree_5341,Leave me!_89,Ok_116802", ; && Button captions, 1st button disabled
    2, ;  && Default button
    "8000,<SECS> secs.") && Timeout




Sample 10: Predefined buttons icons:
The icon parameter has the special characters: "I,B", meaning the Information icon, and the blue background
For the basic captions: "Ok, Cancel, Print, Save and Search", add an "#", and the corresponding unicode icon will be added to the button, as below:

* Sample 10
? FoxyDialog("Playing with real icons in buttons", ;
    "Custom title icon and background!" + CHR(13) + "Predefined buttons with colored icons", ;
 "There are currently 5 predefined buttons that will add some colored icons automatically." + CHR(13) + CHR(13) + ;
 "Add an HASHTAG - '#' after the words below, and the corresponding icons will be added to the buttons:" + CHR(13) + CHR(13) + ;
 "  -  Ok#     " + CHR(13) + ;
 "  -  Cancel# " + CHR(13) + ;
 "  -  Print#  " + CHR(13) + ;
 "  -  Save#   " + CHR(13) + ;
 "  -  Search# ", ;
    "I,B", ; && Information icon, blue background
    "Ok#,Cancel#,Print#,Save#,Search#")  && Button captions




Sample 11: Green background with custom icon, and unicodes

* Sample 11
? FoxyDialog("Playing with Unicodes in buttons", ;
    "You did it!!!" + CHR(13) + "Custom title icon and background!" + CHR(13) + "Predefined unicode buttons", ;
 "There are currently 5 predefined buttons that will add a unicode icon automatically." + CHR(13) + CHR(13) + ;
 "Add an asterisk - '*' after the words below, and the corresponding icons will be added to the buttons:" + CHR(13) + CHR(13) + ;
 "     Ok*        <UC>27f6</UC>     Ok <UC>2713</UC>" + CHR(13) + ;
 "     Cancel*    <UC>27f6</UC>     Cancel <UC>d83dddd9</UC>" + CHR(13) + ;
 "     Print*     <UC>27f6</UC>     Print <UC>2399</UC>" + CHR(13) + ;
 "     Save*      <UC>27f6</UC>     Save <UC>d83dddab</UC>" + CHR(13) + ;
 "     Search*    <UC>27f6</UC>     Search <UC>d83ddd0e</UC>", ;
    "Ok3,G", ; && Ok icon, green background
    "Ok*,Cancel*,Print*,Save*,Search*")  && Button captions





Sample 12: Basic INPUTBOX() dialog with custom icon, image buttons, and timeout

* Sample 12 - INPUTBOX
* - The 5th parameter determines the INPUTBOX() type
* - Custom ICO file
* - Active timeout
* - E-mail icon from https://www.creativefreedom.co.uk/icon-designers-blog/email-icon-android-ios-win-app-icon/
? FoxyDialog("New inputbox dialog", ;
    "E-mail registration", ;
    "Please enter your e-mail from a secure server", ;
    "email.ico,S",       ;  && MAIL icon, BLUE background
    "@I,Ok#,Cancel#",    ;  && Buttons, the '@I' at the beginning means INPUTBOX mode
    "johndoe@doeenterprises.com",  ;    && Default text
    "58000,<SECS> secs.")   && Timeout







Sample 13: Password INPUTBOX() dialog with custom icon, image buttons, and timeout

* Sample 13 - PASSWORD INPUTBOX
* The '@IP' parameter does the trick 
? FoxyDialog("New PASSWORD dialog", ;
    "Server Access", ;
    "Please enter the server access password" + CHR(13) + ;
     "Press the CAPS-LOCK key to see the balloontip!", ;
    "LOCK",        ;    && LOCK icon, BLUE background
    "@IP,Ok#,Cancel#", ;    && Buttons, the '@IP' at the beginning means PASSWORD INPUTBOX mode
    "Password1234",  ;    && Default text
    "58000,<SECS> secs.") && Timeout





Sample 14: Uppercase INPUTBOX() dialog


* Sample 14 - UPPERCASE INPUTBOX
? FoxyDialog("New inputbox dialog", ;
    "FORMATTED INPUTBOX", ;
    "All text entered will be converted to UPPERCASE", ;
    "OK3",        ;    && 'Ok' icon, EMPTY background
    "@I!,Ok#,Cancel#", ;    && Buttons, the '@I!' at the beginning means Uppercase INPUTBOX mode
    "This is your default text",  ;    && Default text
    "58000,<SECS> secs.") && Timeout






Sample 14b: Numeric INPUTBOX() dialog


* Sample 14b - NUMERIC INPUTBOX
lnValue = FoxyDialog("New inputbox dialog", ;
    "Enter the amount you need to withdraw from your account", ;
    "This control accepts only numeric keys and one point", ;
    "Money3.ico,B",    ;    && Custom Money icon, BLUE background
    "@IN,Ok#,Cancel#", ;    && Buttons, the '@IN' at the beginning means Numeric INPUTBOX mode
    123456.78)    && Default value
? lnValue, VARTYPE(lnValue)







Sample 15: Month Calendar INPUTBOX() dialog

* Sample 15 - MONTH INPUTBOX
? FoxyDialog("New Month Inputbox dialog", ;
    "Date select", ;
    "Please enter your date of birth", ;
    "Calendar2.ico,B",  ;  && Calendar2 icon, BLUE background
    "@M,Ok#,Cancel#",   ;  && Buttons, the '@M' at the beginning means MONTHBOX mode
    CTOD("01/12/2019"), ;  && Default date
    "58000,<SECS> secs.") && Timeout






Sample 16: Date INPUTBOX() dialog

* Sample 16 - DATE INPUTBOX
? FoxyDialog("New Date Input dialog", ;
    "Date select", ;
    "Please enter your date of birth", ;
    "Calendar4.ico",    ;  && Custom Calendar.ICO icon, no background
    "@D,Ok#,Cancel#",   ;  && Buttons, the '@D' at the beginning means DATEBOX mode
    CTOD("01/12/2019"), ;  && Default date
    "58000,<SECS> secs.") && Timeout





Sample 17: DateTime INPUTBOX() dialog

* Sample 17 - DATETIME INPUTBOX
? FoxyDialog("New DateTime box dialog", ;
    "Date and Time select", ;
    "Please enter the date and time of estimated delivery", ;
    "DateTime1.ico,B",  ;  && DateTime.ico, BLUE background
    "@T,Ok#,Cancel#",   ;  && Buttons, the '@T' at the beginning means DATETIMEBOX mode
 DATETIME(), ; 
    "58000,<SECS> secs.") && Timeout




Sample 18: Month Calendar date range INPUTBOX() dialog

* Sample 18 - MONTH CALENDAR RANGE INPUTBOX
* The date selection is returned in the 'loDatesRange' object as below
loDatesRange = FoxyDialog("New Datebox range dialog", ;
    "Date range select", ;
    "Please enter the date range for your report", ;
    "Calendar1.ico,S",       ;  && LOCK icon, BLUE background
    "@R,Ok#,Cancel#",   ;  && Buttons, the '@M' at the beginning means MONTHBOX mode
    CTOD("01/12/2019"), ;  && Default text
    "120000,<SECS> secs.") && Timeout

? "Initial date:", loDatesRange.StartDate
? "Final date:"  , loDatesRange.EndDate







APPENDIX 1:
The image below shows all the icons stored in ImageRes.Dll. Each icon comes with an ID. Vhoose your button, and pass its ID number to the "tcnIcon" parameter to have it displayed in your dialog.






APPENDIX 2:
Some of the available strings and values for the tnIcon parameter:
ComputerNumericIconBackgroundImage
"!"-1 or 107Warning shield - !
"BEEP"
"!2"-6Warning shield - !Yellow
"!3"84Warning - !
"!4"1403Warning - !
"X"-2 or 105Error shield - X
"BEEP"
"X2"-7Error shield - XRed
"X3"89Error - X
"X4"98Error - X
"X5"1402Error - X
"I"-3Information - i
"BEEP"
"I2"81Information - i
"?"0x7F02 or 99Question - ?
"?2"104Question shield - ?
"OK"106Success shield - Ok
"OK2"-8Success shield - OkGreen
"OK3"1400Success
"OK4"1405Success
"SHIELD"-4Shield
.....
"KEY"82Key
"KEY2"5360Key
"LOCK"59Lock
"LOCK2"1304Lock
"LOCK3"5381Lock
"ZIP"174Zip
"SEARCH"177Search
"SEARCH2"5332Search
"USER"1029User
"USER2"5356User
"CLOUD"1043Cloud
"CLOUD2"1404Cloud
"STAR"1024Star
"FOLDER"1023Folder
"MAIL"20Mail
"CONNECT"25Connect
"CONNECT2"179Connect
"PRINTER"51Printer
"PRINTER2"45Printer
"CAMERA"57Camera
"FILM"46Film
"FAX"76Fax
"DOCUMENT"90Document
"SCAN"95Scan
"COMPUTER"109Computer
"COMPUTER2"149Computer
"DIAGNOSE"150Diagnose
"MUSIC"1026Music
"CANCEL"1027Cancel
"WRITE"5306Write
"PLAY"5341Play
"CLOCK"5368Clock
"MOBILE"6400Mobile






* UPDATE * 2020-05-10
First of all, thanks very much for the positive feedback, bug reports and suggestions from my friends from Foxite
I applied several fixes and tweaks - the most important were:

New property:
- tnDefault, determines the default button that will receive the focus

Fixes:
- When "ESC" or the dialog closed by clicking at the "X" button made the function wrongly return the value "2"
- Sometimes the returned values were negative


They seem to be very simple, but were really very tricky to fix.
The TaskDialog API does not allow almost any external interference, and this obliged me to test several aproaches to try to bypass it. Hopefully things will run fine now.

The most annoying difficulty was with the fact that I could not resize the buttons. This obliged me to use the original "Cancel" button, that had its caption renamed. But whenever the user clicked on the "X" or pressed <ESC> , the Dialog interpreted that the button that originally was named as "Cancel" was pressed. I had to control the WM_KEYUP Windows event, detect if <ESC> was pressed, and change the returned value.
I could not hide the "X" button. I tried several aproaches that usually work in normal forms, but all I could do is to disable it.
If the dialog has 3 or more buttons, pressing <ESC> will close the dialog, returning the value 0 - ZERO.



* UPDATE * 2020-05-17
Some new enhancements and small tweaks, introducing the timeout property, and the possibility to use Unicodes, to get some cool characters to enhance our dialogs.


* UPDATE * 2020-05-23
New features:
- Add a custom icon with 6 predefined background colors: Red, Green, Yellow, Blue, Silver, and white
- Add true icons to your buttons

That means that we don't need to use the shield icons to get the colored backgrounds!
Some custom icons were also predefined.

For the buttons, you may use the icons from both "Imageres.dll" and "Shell32.dll"
Pass the captions with an "underline" - "_" symbol and the index number of the icon. By default, the icons will use ImageRes.dll. To use Shlell32.ddl's, add 100000 to the index number, see the samples below:


Comming next:

There is a much empowered version of the TaskDialog API, the TaskDialogIndirect function, that allows us to have several other components in our dialogs, such as Option buttons, Checkboxes, expandable footer, and even a ProgressBar!
I have this already working, with the help of another great VFPX project, VFP2C, that brings us the possibility to make Callback functions in VFP. I hope to publish it very soon.



See Also:


4 comments:

  1. FoxxyDialog is amazing! Congratulations to the developers.

    ReplyDelete
  2. Congratulations, it was excellent and very easy to use. thank you!

    ReplyDelete
  3. Amazing!!! Congratulations for your work, is very impressive.

    ReplyDelete
  4. Hi, Cesar, just to let you know that there is a thread going on UT/LE concerning FoxyDialog.

    ReplyDelete