F1 and the screen context
The difference between a chatbot and a help assistant is that the second one knows where the user is when they ask. HelpChatAI builds that context natively, on the main thread, and hands it to the provider — the chat page never sends it, so it cannot be stale or forged.
What the context contains
| Field | Where it comes from |
|---|---|
ScreenName | Name of the active form |
ScreenLabel | caption of the active tab sheet, or of the form |
ScreenType | class name of the form |
HelpKeyword | the deepest HelpKeyword found |
HelpContext | the deepest HelpContext found (when no keyword) |
FocusedControl | Name of the focused control |
The search starts at the focused control and walks up through its parents, with the form last: a grid with its own keyword wins over the tab sheet, which wins over the form. That is how one screen can have different help for different parts of it.
What the provider actually searches with is a search hint: the readable HelpKeyword when there is one, otherwise the screen label. Class names and internal component names are never used as search terms — they would only add noise.
Declaring the help of a screen
Use the standard Delphi properties. The value that works best is the title of the page of your manual, because that is what the retriever matches against:
// VCL
LeadsTab.HelpType := htKeyword;
LeadsTab.HelpKeyword := 'Leads'; // the title of a page of the manual
// numbers work too, if your manual is indexed by context id
OrdersForm.HelpType := htContext;
OrdersForm.HelpContext := 4040;In FireMonkey the same properties live on TStyledControl (forms do not have them): put them on tabs and panels.
What F1 does
Two mechanisms, in this order:
- The Delphi help system. With
RegisterHelpViewer := True(the default) the component registers a viewer implementingICustomHelpViewerandIExtendedHelpViewer. When a control in the chain declares help, the VCL routes F1 to the help system exactly as it would to a CHM viewer, and the help system calls HelpChatAI.Application.HelpKeyword(...),Application.HelpContext(...)andHelpShowTableOfContentsreach it too. - The fallback. Where nothing declares help — the VCL would do nothing at all — the component's own F1 handler opens the chat with the current screen, if
HandleF1is True.
This is why you should not hook Application.OnHelp yourself: what you declared already works, and mixing the two produces the classic double question.
Both mechanisms, one question
A key repeat, or a request that arrives twice, cannot send the same question twice: identical questions within 1.5 seconds are shown but sent once.
In FireMonkey there is no routing at all: see The FMX component.
Refining the context
OnGetContext is called every time the context is built, just before it is used:
procedure TMainForm.HelpChatGetContext(Sender: TObject; var AContext: THelpChatContext);
begin
// a screen whose meaning depends on what it is showing
if (AContext.ScreenName = 'DocumentForm') and (FDocument <> nil) then
AContext.ScreenLabel := 'Documento ' + FDocument.Kind;
// or a keyword you compute instead of declaring
if AContext.HelpKeyword = '' then
AContext.HelpKeyword := CurrentModuleHelpTopic;
end;Use it also to remove things: if a screen label contains a customer name, blank it — only the screen name, label, type and keyword ever reach a provider, but that is still your data.
Asking about a screen from your own code
HelpChatAI.OpenForHelp('Leads', 0); // that screen
HelpChatAI.OpenForCurrentScreen; // what F1 does
HelpChatAI.OpenWithQuestion('How do I prepare a proposal?'); // a question of yoursAnd the standard way, which goes through the help system and therefore through HelpChatAI:
Application.HelpKeyword(PageControl.ActivePage.HelpKeyword);