Sage Help for VCL Apps
This article discusses how to link to Sage
articles from a VCL application,
to serve as a Help facility for Windows programs.
Using the techniques discussed here,
you can easily add context-sensitive Help
features to a VCL application.
When the user hits F1
(or a menu item, tool button, etc),
they will be taken to a browser tab,
showing the relevant Sage content.
Alternatively, the user can hit ⇧ Shift+F1
to use the "What Is This?" help feature.
This turns the mouse pointer into a symbol
like this...
...until the user clicks on a UI element.
At this point, the mouse pointer is restored,
and the user is taken to the relevant Sage
content for the element they clicked on.
Requesting help for an individual
control can take the user directly to an article
(or article section) discussing that control.
To get started, follow these steps…
- Ensure that the VCL project contains the unit Utility\DSSageUIHelp. This unit, and the others that it uses, implements the Sage help system.
- During startup (for example, in the main form's OnCreate event handler), call the method UIHelp.Enable (defined in DSGUIUtil). This method begins listening for F1 and ⇑ Shift + F1.
- If you would like to offer menu items and/or tool buttons to initiate help commands, use the UIHelp.ForActiveControl and UIHelp.ByPointer methods. These methods are functional even if UIHelp.Enable has not been called.
- On various controls, including forms, frames, panels, edit boxes, buttons, check boxes, etc, set the HelpKeyword property to associate Sage content with UI elements. More on this shortly.
TControl has a string property, HelpKeyword.
This property is related to the VCL's help system,
which is based on WinHelp or HTMLHelp technologies.
However, we can easily leverage this property for use
with Sage help, using the UIHelp namespace defined
in DSGenUtil.
When the user requests help for a control,
UIHelp looks at the control's HelpKeyword property.
This property contains a partial Sage URL,
of the form:
/Volume/Article#Section
Only the Volume is required,
though it is preferable to take the user
directly to a section discussing the control in question.
If a control's HelpKeyword does not specify a Volume,
UIHelp moves to the control's parent,
and examines its HelpKeyword.
This process continues until a Volume is encountered
(or until a top-level form, with no parent, is reached).
For example, suppose your application has a modal dialog
with a dozen or so UI elements.
Also suppose you have a Sage article discussing the dialog,
with a separate section for each control on the dialog.
At design time, you should set the form's HelpKeyword
to /Volume/Article.
This way, when the user asks for help anywhere on the dialog,
they will be taken to the article.
Additionally, for each control that has its own section,
set the control's HelpKeyword to #Section.
Not every control needs its own section
(for example, maybe the Cancel button doesn't).
With this arrangement, if you change the name (or alias)
of the article, there is only one HelpKeyword to modify
(that of the form itself).
The following are the valid forms for the HelpKeyword…
- /Volume
- /Volume/#Section
- /Volume/Article
- /Volume/Article#Section
- Article
- Article#Section
- #Section
If your application has more than one form,
you may find yourself repeating the volume name
in the HelpKeyword for several forms.
For example, imagine an application with several forms,
each with its own article (in a common volume).
Each form would need a HelpKeyword such as: /Volume/Article.
Ideally, many of the controls on each form would
have a HelpKeyword specifying a section.
Fortunately, UIHelp offers a way to specify
an application-wide HelpKeyword,
so that the volume can appear once per app
(as opposed to once per form).
This property is called UIHelp.AppKeyword,
but you should not set property this in code.
Instead, use the Tools | Dimeric Options command,
and select the UI Help tab…
This dialog will store the AppKeyword in the project's
*.dproj file, and will initialize UIHelp.AppKeyword
as the application starts up.
The benefit of this approach is that it makes the AppKeyword
available at design time, which will come into play in the
following sections.
The Object Inspector offers a Property Editor
for the TControl.HelpKeyword.
To invoke this, double-click the HelpKeyword value,
or hit ^ Ctrl + ⏎ Enter,
or click on the ... button along the right edge.
The Property Editor displays the following dialog…
The large memo labeled HelpKeyword shows the value of
the HelpKeyword property.
You can make changes directly in this memo,
and you can hit ^ Ctrl + Space
for Code Insight suggestions…
This read-only edit box, along the top of the dialog,
displays the effective (partial) Sage URL,
based on the selected control's HelpKeyword,
and that of the parent control(s), if relevant.
This combo box, in the upper-right corner,
indicates how the dialog implements certain features,
such as Code Insight and validation.
There are three choices:
Production, Local Web, and Local Files.
The last of these is not yet implemented.
Production communicates with the production Sage web server.
Local Web uses a non-production Sage web server,
the URL for which is specified using the
Tools | Dimeric Options command,
on the UI Help tab (details).
This button, in the lower-left corner,
validates the current control's HelpKeyword,
including information obtained from the parent control(s).
See also: Source.
This button, in the lower-right corner,
opens the relevant Sage content,
based on the current control's HelpKeyword,
including information obtained from the parent control(s).
See also: Source.
If you right-click on a control in the Form Designer,
the menu that appears will include an item displaying
the control's HelpKeyword property…
This makes it easy to double-check the HelpKeyword,
without having to locate it in the Object Inspector.
If you click this menu item, it will invoke the
property editor.
Note: this command has a hotkey of
⇑ Shift + ⌥ Alt + K,
and is also available on the Tools | Infrequent menu.
The Tools | Validate VCL Project command,
^ Ctrl + ⌥ Alt + V,
validates all forms and frames in the active project.
Specifically, the HelpKeyword property of all TControl
components will be validated.
If any validation issues are encountered,
a form will appear, listing these issues…
Double-click on an item to go directly to the relevant control.
If a form or frame will typically
reside within a parent control
(which is always the case for frames,
and sometimes the case for forms as well),
this may cause confusion at design time.
For example, suppose a project includes a dialog and a frame
that will be instantiated on the dialog.
If the dialog's HelpKeyword establishes the volume and article,
and various controls on the frame specify sections,
the IDE will be confused when validating the HelpKeyword
for the controls on the frame.
To work around this issue, drop a TParentOverride component
onto the frame (or form) at design time.
This component offers two string properties:
OwnerName and ParentName.
Set OwnerName to the name of the form or frame that will host
the current form/frame at runtime.
For example, if we have a dialog named MyDialog,
and a frame that will reside there, named MyFrame,
then drop a TParentOverride onto MyFrame,
and set its OwnerName to MyDialog.
If the form or frame will reside on a specific control
(often a TPanel or TScrollBox),
set the ParentName to the name of the control.
To continue our earlier example,
if MyFrame will reside on MyPanel (a control on MyDialog),
then set ParentName to MyPanel.
Leave ParentName blank if the form/frame will reside directly
on the form/frame referenced by OwnerName.
Both of these properties have property editors,
allowing you to see a drop-down list of valid choices.
The OwnerName property suggests all VCL forms and frames
in the current project,
while the ParentName suggests all TWinControl components
(that can accept children) on the form/frame specified
by OwnerName.
Some applications set a control's parent at runtime.
For example Taos applications have a mechanism for
merging the toolbar of a view into the main form's toolbar.
Thus, at design time, the tool buttons on a view can specify
a section in their HelpKeyword, and "inherit" the
volume and article from the view itself.
However, at runtime, the view's toolbar will be moved onto
the main form, so that the view's tool buttons no longer
"inherit" HelpKeyword information from the view.
Fortunately, there is a simple solution to this issue.
Before changing a control's parent,
call UIHelp.ExpandKeyword…
class procedure ExpandKeyword(
Control: TControl; IncludeChildren: Boolean); static;
This method examines Control
(and, if IncludeChildren is True, all of its children),
looking for HelpKeyword properties that don't specify
a Volume name.
As these are found, they will be expanded to their
(current) effective HelpKeyword, based on the parent
control(s).
For example, the base main from in Taos has
code like this…
procedure TBaseClientForm.MoveControlToToolBar(
View: TWinControl; Control: TControl);
begin
if UIHelp.Enabled then
UIHelp.ExpandKeyword(Control, True);
//...
end;
Before moving a control to the main form's toolbar,
UIHelp.ExpandKeyword is called
(but only if UIHelp.Enabled is True).
⏱ Last Modified: 11/17 12:39:43 pm