Previous: 15 Plotting graphs
Next: 17 Startup and closedown
In this section:
Help for users of your application program comes in a diverse variety of ways. Outside of the application there are training courses, telephone helplines and printed manuals, and within the program the help system can also take a range of forms.
At one end of the spectrum there is the complete compiled hypertext help file run by the HH.EXE standard program in Windows (see right back in Chapter 1). This has several disadvantages, most notably the delay while the hypertext help program and .CHM file load, and then the time taken for the user to find the precise entry that relates to their problem. The need to hunt through the CHM file may be reduced by jumping to the right keyword in the helpfile, which is a facility within ClearWin+. Then, it is possible to program pop-up dialogs using some basic facilities of ClearWin+, which is likely to launch more quickly than using an external facility, although dialogs almost always contain less information than the complete contents of a helpfile.
The real downside of using a .CHM file is not the time taken to load it, but is that you need a helpfile compiler to produce it. That also requires a learning curve, and although there are freeware options, there is usually a cost to obtaining that software.
If a delay is acceptable, an alternative approach is to produce an HTML file instead. ClearWin+ has facilities for loading and displaying HTML files. A local file will load quicker than one downloaded via the internet, but if the latter is kept up to date, with errors corrected and descriptions enhanced, then the approach may have its merits.
Naturally, a well-designed interface, with dialogs that users find intuitive to use, reduces the need for help in the first place. That means not reinventing the wheel but instead, using shortcuts and actions that the user will already be familiar with. It also means designing icons for toolbars that for common actions are recognisable from other commercial applications and where they are highly specific to your program that they are in fact meaningful.
Finally, there are ‘tool tips’, or help messages attached to particular controls that are presented after a short delay when the control experiences a mouseover event. Not every control benefits from having a tooltip, and indeed, the badly timed presentation of tooltips may be a greater annoyance to the user than a help! It is therefore worth considering whether to make the display of tooltips optional. Tooltips are particularly useful for the options in a toolbar, because the controls do not have an accompanying text description, nor the legend that one provides for a button.
It is possible to provide help for particular controls in toolbars, menus and dialogs in the form of pop-up messages. The relevant controls are %bh (bubble help) and %th (tooltip help) with a third format code %he that assists in controlling where the messages appear. It is possible to arrange for the help messages to be associated closely with the control in question, at the cursor, or in a status bar, and to be invoked by various means, including to a mouseover event, with or without a delay.
In my experience, it is a mistake to provide too many controls with help in this manner, because if the action captions are helpful and relevant a short help string may not be long enough to provide a significant extra aid to the user. Where this form of help is most useful is in connection with toolbars, especially those that have only icons and no captions. I prefer the
%th[ms_style] with a 300 ms delay before it appears.
A factor that needs to be considered is that these help messages popping up when they are not wanted can be distracting or even annoying to an experienced user, and therefore a useful menu setting is to turn them off, or to restore them for a different, perhaps less experienced, user.
The guidance about programming these format codes in the online help files is thorough and so does not need to be repeated here. My contribution is to suggest that these help utilities are kept to the minimum, particularly at first, and only extended when the need is shown. Sometimes the solution is more likely to be a change in any action words on control buttons, labels on radio buttons and tick boxes, or even redrawn icons. The answer is not having pop-up help on every control, and especially not to provide the help whether a user needs it or not.
My recommendation with regard to tooltips is that you use them quite sparingly, and initially, only on your toolbars until you have had several reviews from other users about what they find easy and what they find difficult or confusing about your application and react to that feedback rather than conform rigidly to an idea you had at an early stage.
ClearWin+ can read and write some types of hypertext files, and a great way to keep users informed of changes to or issues with your application is to refer them to hypertext files kept on your own fileserver – until an internet connection is lost! Keeping files locally solves that problem but in turn generates the issue that files may need some mechanism to keep them up to date.
The %ht format that uses hypertext in a dialog is described in the online help file along with all the associated functions. There is also the alternative %wb which you may prefer. The difference between the two is that %ht is native to ClearWin+, whereas %wb uses the Internet Explorer engine.
Accelerator keys are sometimes called shortcut keys, and include not only single keys such as the function keys on a PC keyboard but also ‘chords’ where several keys are pressed simultaneously, usually in combination with Shift, Ctrl or Alt. ClearWin+ can associate these accelerator keys to menu or toolbar commands. One method is to define the accelerator keys when for example a menu system is being generated. The other method is to switch on or switch off the accelerator keys with subroutine calls.
The subroutine call method allows you to temporarily switch off accelerator keys while a particular dialog is operative and then to reactivate them on exit from the dialog.
Subroutines: The subroutines are named ADD_ACCELERATOR@ and REMOVE_ACCELERATOR@. The routine ADD_ACCELERATOR@ has three parameters and REMOVE_ACCELERATOR@ has two.
In the case of ADD, the parameters are:
The key or key combination name is given in a prescribed way within quotes as a standard character string, with examples such as: ‘Alt+Esc’, ‘Ctrl+Shift+Del’, ‘Esc’, ‘Alt+Enter’, ‘F1’ and ‘Ctrl+F3’. In the case of REMOVE, the two parameters are the first two from ADD.
WINIO@: You can associate the accelerator keys with particular callback functions using the %ac format code when building a window with WINIO@, as in:
IW = WINIO@ ('%ac[F1]&', KB_HELP_FILE)
Accelerator keys can also be associated with specific %mn items by placing the accelerator key or key combination after the name of the menu item, with the item and key combination separated by a TAB code (represented by ⬛ below, as in:
IW = WINIO@ ('%mn[Help[File⬛F1]]&', KB_HELP_FILE)
Clearly, the accelerator keys relate to the same callback function as the menu item.
If you examine a number of commercial applications, you will discover that there is an de facto standard for some of them, particularly Ctrl-P to launch the Print option in the File menu, or F1 to invoke Help. If you define your own standards from scratch, you will make it more difficult for users to become confident or adept in using your program. Indeed, as a user yourself you will soon discover the pitfalls of an unconventional set of accelerator keys!
At some stage you will discover that a Windows program in Fortran and ClearWin+ runs to many subprograms, and managing them all will be a problem. The answer in part is not to try and lump everything into the same source code file, as we had to when programs were on 80 column cards, and also not to have one source code file for every subprogram as that simply exchanges one sort of problem with another.
I became used to having one source code file for each subprogram when I first started using a personal computer with floppy drives and editing my programs with WordStar in ‘non-document’ mode, but that was when my programs might have only had a half-dozen or more files and routines to contend with.
Plato does a superb job of managing a project with multiple source code files, but the issue is in finding particular routines across all of those files. What I do and have found works for me is to limit a source code file typically to about 2000 to 2500 lines and the appropriate number of subprograms that fit in that length. At the beginning of each source code file, I have a list of comments that name each subprogram and give the line number where it starts. During program development, these line numbers change regularly and there is no way of hyperlinking them, so it is a question largely of updating the numbers periodically. Provided that the line numbers are right to within 10 or so, and you know that you are working on that file, it probably does not matter terribly much, and only when the code is comparatively stable do you need to produce the definitive list.
My next problem is in finding which file contains a routine that I’m interested in. The method that I’ve found useful to cope with this is to copy each gazetteer section from every source code file and put them in to another file which I have called WHEREIS.FOR. Again, during program development, the contents of WHEREIS.FOR have to be updated but that is a matter of cut-and-paste of a block of lines.
To reduce the number of times that I have to update the line numbers, I usually find it preferable to put routines in development at the bottom of any particular source code file.
Another trick that I have found very useful is to use an in-line comment after every subroutine is called that tells me which source code file contains that subroutine.
I also maintain a file called WHATIS.FOR that lists the variable names from my program and explains what they represent. This is a hangover from the days when I would provide that information in every subprogram, but doing the old practice makes the source code files very long indeed.
I have found that once a particular application has many subprograms and source code files that it is a mistake to develop something within the framework of the complete program. Instead, I do the development of something (for example like a new dialog box) in a stand-alone program and only incorporate it in the main application when I am content that it works reasonably well. Attempting to debug errors that you have introduced into several areas in a really big application can be a nightmare.
Of course, you must follow your own experience, programming habits and methodology as suits you best, but I certainly have found that I needed a lot more discipline given the length and complexity of a Windows GUI relative to an old-style Fortran program.
An important feature of most Windows applications is that we can Undo a previous command. If you wish to implement Undo, then you have to implement the reversal of selections in some way. No doubt there are some really fancy programming solutions to the problem, but essentially it boils down to keeping a record of what was done and programming the means to reverse those changes. It isn’t always necessary to implement Undo, so for example, if there is a dialog in which a graphical object can be set to one of a small set of colours, then rather than Undo to revert to a previously selected colour, the user can simply revisit the dialog. Where it is necessary is when the user performs an action that has far-reaching consequences that cannot be reversed simply by selecting a simple option. One example might be when the user deletes a main branch of a family tree, say by wiping out Queen Victoria from a royal family tree. To revert to the previous status quo by re-inserting all of her descendants would be a mighty job.
I don’t often meet this in things I program, but where I have had to, I have got over it by frequently saving my entire dataset in files that are systematically named with the names held in a list, and Undo simply means reloading those files, perhaps after re-initialising all the arrays. Alternatively, the Undo information can be held in memory.
Most dialogs have a Cancel button. Note that if the user has made any changes to variables or selections, then unless steps are taken to revert to the original values, then your Cancel will simply act as a sort of perplexing Accept !
There are two approaches, and the one I prefer is to use a set of surrogate variables that are given initial values on entry to a dialog, and then those variables are used in data input boxes etc. Then, the original variables retain their initial values if the dialog box is closed or Cancelled. It does mean that if Accept is selected, the WINIO@ return code must be checked, and if set, the original variables are updated.
The alternative is to save the initial values into the surrogates on entry to the routine, use the original variables in the dialog, but be prepared to revert to the values held temporarily in the surrogates if Cancel is selected or the dialog closed other than with explicitly accepting the changes.
Footnotes:
12. John Lennon was 25 when he wrote Help! – with some ‘Help’ from Paul McCartney, apparently.
13. Tom Jones? 1968 was a great year for pop ...
FORTRAN and the ART of Windows Programming, Copyright © Eddie Bromhead, 2023.