Sage
Welcome to Sage
Volume (96%) Hide Volume
Topics
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.

Note

Parts of this article assume familiarity with the UIHelp namespace from DSGUIUtil.


Overview

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.

Prerequisites

To get started, follow these steps…

  1. Ensure that the VCL project contains the unit Utility\DSSageUIHelp. This unit, and the others that it uses, implements the Sage help system.

  2. 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.

  3. 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.

  4. 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.

HelpKeyword for Controls

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.

Parent Controls

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).

Valid URL Syntax

The following are the valid forms for the HelpKeyword

  • /Volume
  • /Volume/#Section
  • /Volume/Article
  • /Volume/Article#Section
  • Article
  • Article#Section
  • #Section

As UIHelp moves from a control to its parent, it does not allow a parent to override a URL component specified by a child. For example, if a control's HelpKeyword is #Section1, and it's parent's HelpKeyword is /Volume3/Article2, then UIHelp combines these to yield /Volume3/Article2#Section1. However, if the parent's HelpKeyword is #Section4, UIHelp will ignore this (and move to the next parent up), as parents cannot override URL components specified by a child.

Similarly, UIHelp does not allow a parent to specify a lower-level URL component than what the child already specified. For example, if a control's HelpKeyword is Article2, the parent cannot specify #Section3 (the reverse is allowed, of course).

Thus, once a Volume has been specified, the process of moving up the containment hierarchy stops.

Application-Wide HelpKeyword

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.

HelpKeyword in the Object Inspector

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…

Effective Path

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.

Source

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).

Validate

This button, in the lower-left corner, validates the current control's HelpKeyword, including information obtained from the parent control(s). See also: Source.

Jump

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.

Right-Click on a Control

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.

Validating the Project

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.

Note

The progress dialog for this command is large (the size of the IDE's main window), to work around some significant flickering issues caused by having a modal dialog (the progress dialog) active while opening forms in the background (that is, opening them in order to validate their contents, but not making actual editor tabs for them). This work-around is not ideal, but trust me: it is better than the seizure-inducing flicker that it suppresses.


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.

Overriding the Parent at Design Time

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.

Note

The TParentOverride component has no effect on runtime behavior. It is strictly for design-time features such as Code Insight, validation, etc.


Changing the Parent at Run-Time

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: 10/24 10:59:46 am
In this article (top)  View article's Sage markup
10/24 10:59:46 am