Delphi RSS Resources, Delphi Components, Delphi Sites, Articles, Dynamic XML Feeds, Tutorials, Sources
 
 
 
Google
 
Web delphirss.com
| Server-Scripts.com | Informations for JAVA | Informations for PHP | SEO Web Links | Borland Delphi
 

Windows Help

WinHelp macros
Using Help
HelpFiles
Searching your application's help file


WinHelp macros

Question

Is it possible to call the WinHelp macro 'Search()' from  Delphi?

Answer

A:
Yes, you can do this by a direct call to the Windows API WinHelp function, or
(more easily) by calling the Application.HelpCommand method.
Or (more easily still) you could avoid having to fiddle with pointers to null
terminated strings every time, by going a stage further and encapsulating the
call into a simple procedure like this:

unit Help;

{$X+      {Allow Application.HelpCommand's result to be discarded}

interface

 procedure HelpSearch (const Key: string);


implementation
 uses
   Forms,         {for Application}
   SysUtils,      {for StrPCopy}
   WinTypes;      {for HELP_PARTIALKEY}

 procedure HelpSearch (const Key: string);
{----------------------------------------------------------------}
{ Calls Windows Help engine for a Search on the supplied Key.    }
{ If more than one match or no match, brings up Search dialog.   }
{----------------------------------------------------------------}
 var
   AStr255: array[0..255] of char;
   PStr255: pointer;
 begin
   PStr255 := StrPCopy(@AStr255, Key);
   Application.HelpCommand(HELP_PARTIALKEY, longint(PStr255));
 end;


end.

Using Help

Question

I'm using Application.helpJump to implement context-sensitive help.
Sometimes, however, the topic string I construct isn't in the help file, in
which case winHelp displays "Topic not found" and keeps the user in Help
with a blank screen.  Does anyone know of a way to interrogate a WinHelp
file to see if a context string exists, or alternatively a way to extract
all context strings from a help file (then I can write a little loop to see
if the string is there).

Answer

A:
You can support LDLLHandler() in your help system. With that I think you can
check DW_ENDJUMP, lparam1 of it will hold the position of the help topic.
When it fails you can call the callback function RcCloseHfs to close Help.
I suppose there would be a blink that the user may notice, but it may be
tolerable.

The work to do is to create a DLL to support LDLLHandler() and a DLL macro in
the help system to send information to the DLL.

A:
The following code demonstrates how to bring up the WinHelp "Search"
dialog for your application's help file.  You can use TApplication's
HelpCommand method to send the Help_PartialKey command to the WinHelp
system. The parameter for this command should be a PChar (cast to a
longint to circumvent typechecking) that contains the string on
which you'd like to search.  The example below uses an empty string,

which invokes "Search" dialog and leaves the edit control in the
dialog empty.

procedure TForm1.SearchHelp;
var
  P: PChar;
begin
  Application.HelpFile := 'c:\delphi\bin\delphi.hlp';
  P := StrNew('');
  Application.HelpCommand(Help_PartialKey, longint(P));
  StrDispose(P);
end;

DISCLAIMER: You have the right to use this technical information
subject to the terms of the No-Nonsense License Statement that
you received with the Borland product to which this information
pertains.

A:
  Here's my Help unit.  You may find some of the routines down
  at the bottom useful -  e.g. look for WinHelpTopic.  Let me
  know if you need any of the routines which it calls:


{----------------------------------------------------------------}
{                                                                }
{    The Pascal Factory - Delphi Tools Library - Help unit       }
{                                                                }
{    Routines for easy implementation of Windows Help & Hints.   }
{----------------------------------------------------------------}
                  {c 1990-1996 Mike O'Hanlon, The Pascal Factory.}
unit Help;

{$R HELPCURS.RES}

interface
 uses
   Controls,      {for TControl}
   Graphics;      {for TColor}

 procedure PaleYellowHints;
 function  QuestionMarkCursor: Boolean;
 procedure RemoveHint (var Hint: THintWindow);
 function  RevealHint (Control: TControl; Color: TColor)
                      : THintWindow;
 procedure ResetQuestionMarkCursor;
 procedure SetQuestionMarkCursor;
 procedure WinHelpContents;
 procedure WinHelpForForm (Sender: TObject);
 procedure WinHelpForFormTab (Sender: TObject);
 procedure WinHelpQuit;
 procedure WinHelpSearch;
 procedure WinHelpTopic (const Topic: string);


implementation
 uses
   Basics,        {for RemoveFirst}
   Classes,       {for Bounds}
   Errors,        {for Err handling}
   ExtCtrls,      {for TNotebook}
   Extras,        {for InstallCursor}
   Forms,         {for TForm}
   SysUtils,      {for StrPCopy}
   TabNotBk,      {for TTabbedNotebook}
   WinProcs,      {for DrawText}
   WinTypes;      {for HELP_PARTIALKEY}

 const
   crQuestionMark = 1;
 var
   PreviousCursor: TCursor;


 procedure PaleYellowHints;
{----------------------------------------------------------------}
{ Makes all Hints for the application a bit paler than standard. }
{----------------------------------------------------------------}
 begin
   Application.HintColor := $00C1FFFF; {Very pale yellow}
 end;


 function QuestionMarkCursor: Boolean;
{----------------------------------------------------------------}
{ Returns state of cursor: true for question mark, else false.   }
{----------------------------------------------------------------}
 begin
   if Screen.Cursor = crQuestionMark
     then QuestionMarkCursor := true
     else QuestionMarkCursor := false;
 end;


 procedure RemoveHint (var Hint: THintWindow);
{----------------------------------------------------------------}
{ Releases the window handle of a Hint previously popped up with }
{ RevealHint.                                                    }
{----------------------------------------------------------------}
 begin
   Hint.ReleaseHandle;
   Hint.Free;
   Hint := nil;
 end;


 function RevealHint (Control: TControl; Color: TColor)
                     : THintWindow;
{----------------------------------------------------------------}
{ Pops up Hint window for the specified Control, and returns a   }
{ reference to the hint object so it may subsequently be removed }
{ with RemoveHint.                                               }
{----------------------------------------------------------------}
 var
   Outcome: THintWindow;
   ShortHint: string;
   AShortHint: array[0..255] of Char;
   HintPos: TPoint;
   HintBox: TRect;
   HeightOfText: Integer;
 begin
   { Create the window: }
   Outcome := THintWindow.Create(Control);
   if Color <> 0 then
     Outcome.Color := Color;
   { Get first half of hint up to '|': }
   ShortHint := GetShortHint(Control.Hint);
   { Calculate Hint Window position & size: }
   HintPos := Control.ClientOrigin;
   Inc(HintPos.Y, Control.Height + 6);
   HintBox := Bounds(0, 0, Screen.Width, 0);
   HeightOfText := DrawText(Outcome.Canvas.Handle,
       StrPCopy(PChar(@AShortHint), ShortHint), -1, HintBox,
       DT_CALCRECT or DT_LEFT or DT_WORDBREAK or DT_NOPREFIX);
   OffsetRect(HintBox, HintPos.X, HintPos.Y);
   Inc(HintBox.Right, 6);
   Inc(HintBox.Bottom, 2);
   { Now show the window: }
   Outcome.ActivateHint(HintBox, ShortHint);
   RevealHint := Outcome;
 end; {RevealHint}


 procedure ResetQuestionMarkCursor;
{----------------------------------------------------------------}
{ Resets cursor from Question Mark cursor.                       }
{----------------------------------------------------------------}
 begin
   PreviousCursor := 0;
   Screen.Cursor := PreviousCursor;
 end;


 procedure SetQuestionMarkCursor;
{----------------------------------------------------------------}
{ Store cursor (for later reset) and set Question Mark cursor.   }
{----------------------------------------------------------------}
 begin
   PreviousCursor := Screen.Cursor;
   Screen.Cursor := crQuestionMark;
 end;


 procedure WinHelpCommand (Command: Word; Data: Longint);
{----------------------------------------------------------------}
{ Calls Application.HelpCommand with the supplied parameters.    }
{ Displays an error message if HelpCommand returns false and     }
{ Debug information is on.                                       }
{----------------------------------------------------------------}
 var
   CommandStr: string;
 begin
   if not Application.HelpCommand(Command, Data) then
{$IFOPT D+}
   begin
     case Command of
       HELP_CONTENTS:   CommandStr := 'HELP_CONTENTS';
       HELP_PARTIALKEY: CommandStr := 'HELP_PARTIALKEY';
       HELP_QUIT:       CommandStr := 'HELP_QUIT';
       else             CommandStr := 'unknown';
     end; {case}
     Err(['Proc: WinHelpCommand',
          'Meth: Application.HelpCommand',
          'Win:  WinHelp',
          'HelpCommand call returned false result',
          'Command was ' + CommandStr]);
   end;
{$ENDIF}
 end;


 procedure WinHelpContents;
{----------------------------------------------------------------}
{ Calls the Windows Help engine and displays the Contents page.  }
{----------------------------------------------------------------}
 begin
   WinHelpCommand(HELP_CONTENTS, 0);
 end; {WinHelpContents}


 procedure WinHelpForForm (Sender: TObject);
{----------------------------------------------------------------}
{ Calls the Windows Help engine with a Topic built from the      }
{ ClassName (less leading 'T') of the parent Form of the Sender. }
{----------------------------------------------------------------}
 begin
 { Go up parent tree until Form is found: }
   while not (Sender is TForm) do
     Sender := TWinControl(Sender).Parent;
   WinHelpTopic(RemoveLeading('T', Sender.ClassName));
 end; {WinHelpForForm}


 procedure WinHelpForFormTab (Sender: TObject);
{----------------------------------------------------------------}
{ Calls the Windows Help engine with a Topic built from the      }
{ ClassName (less leading 'T') of the parent Form of the Sender. }
{ If the form has a (visible) Notebook or TabbedNotebook on it,  }
{ the name of the displayed Tab (less '&' accelerator character) }
{ is appended to the Topic.                                      }
{----------------------------------------------------------------}
 var
   Tab: string;
   I: Integer;
 begin
 { Go up parent tree until Form is found: }
   while not (Sender is TForm) do
     Sender := TWinControl(Sender).Parent;
 { Check components on Form for visible Notebook/TabbedNotebook: }
   Tab := '';
   with TForm(Sender) do
     for I := 0 to ComponentCount - 1 do
       if TControl(Components[I]).Visible then
         if (Components[I] is TNotebook) then
         begin
           with TNotebook(Components[I]) do
             Tab := '_'+ RemoveFirst('&', Pages[PageIndex]);
           Tab := RemoveAll(' ', Tab);
           Break; {out of for loop}
         end
         else if (Components[I] is TTabbedNotebook) then
         begin
           with TTabbedNotebook(Components[I]) do
             Tab := '_'+ RemoveFirst('&', Pages[PageIndex]);
           Tab := RemoveAll(' ', Tab);
           Break; {out of for loop}
         end;
   WinHelpTopic(RemoveLeading('T', Sender.ClassName) + Tab);
 end; {WinHelpForFormTab}


 procedure WinHelpQuit;
{----------------------------------------------------------------}
{ Should be called before app exits.  WinHelpQuit calls Windows  }
{ Help engine and informs it that Help is no longer needed.  If  }
{ no other applications have asked for Help, WinHelp is closed.  }
{----------------------------------------------------------------}
 begin
   WinHelpCommand(HELP_QUIT, 0);
 end; {WinHelpQuit}


 procedure WinHelpSearch;
{----------------------------------------------------------------}
{ Calls the Windows Help engine and brings up the Search dialog. }
{----------------------------------------------------------------}
 const
   ForceSearch = '???';
 var
   AStr255: array[0..255] of Char;
   Data: Longint;
 begin
   WinHelpContents;
   Data := Longint(StrPCopy(PChar(@AStr255), ForceSearch));
   WinHelpCommand(HELP_PARTIALKEY, Data);
 end; {WinHelpSearch}


 procedure WinHelpTopic (const Topic: string);
{----------------------------------------------------------------}
{ Calls Windows Help engine and looks for the supplied Topic.    }
{ If more than one match or no match, brings up Search dialog.   }
{----------------------------------------------------------------}
 var
   AStr255: array[0..255] of Char;
   Data: Longint;
 begin
   Data := Longint(StrPCopy(PChar(@AStr255), Topic));
   WinHelpCommand(HELP_PARTIALKEY, Data);
 end; {WinHelpTopic}


initialization
  PreviousCursor := 0;
  InstallCursor('QUESTIONMARKCURSOR', crQuestionMark);
end.


  Hope something in there (Win)Helps...

A:
I have written a THelper component, which provides additional Help
features. Here are the source files HELPER.PAS, HELPCONS.PAS and 
HELPER.RC

-------------- chew off here for HELPER.PAS
unit Helper;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs;

type
  EHelperError = class(Exception)
  end;

  THelper = class(TComponent)
  protected
    procedure Check(Condition: Boolean; Operation: Word);
  public
    procedure ShowContents;
    procedure SearchTopic(const Topic: string; Partial: Boolean);
    procedure ShowContext(ContextNumber: LongInt); procedure
    ShowContextString(const ContextString: string); procedure
    SearchDialog; procedure HelpMacro(const MacroName: string);
    procedure HelpOnHelp; 
  end;

procedure Register;

implementation

{$R HELPER.RES}

uses
  HelpCons;

procedure Register;
begin
  RegisterComponents('Lance', [THelper]);
end;

{ THelper Component }

procedure THelper.Check(Condition: Boolean; Operation: Word);
const
  MaxMsg = 64;
var
  Msg:    PChar;
  PasMsg: string;
begin
  if not Condition then
  begin
    Msg := StrAlloc(MaxMsg + 1);
    try
      LoadString(HInstance, Operation, Msg, MaxMsg);
      PasMsg := StrPas(Msg);
      raise EHelperError.Create(PasMsg);
    finally
      StrDispose(Msg);
    end;
  end;
end;

procedure THelper.SearchTopic(const Topic: string; Partial: Boolean);
var
  Key:      PChar;
  HelpFile: PChar;
  Command:  Word;
begin
  Key := StrAlloc(Length(Topic) + 1);
  try
    StrPCopy(Key, Topic);
    HelpFile := StrAlloc(Length(Application.HelpFile) + 1);
    try
      StrPCopy(HelpFile, Application.HelpFile);
      Check(Application.HelpCommand(HELP_FORCEFILE, 0),
      SHelpCantHelp); if Partial then
        Command := HELP_PARTIALKEY
      else
        Command := HELP_KEY;
      Check(Application.HelpCommand(Command,
                    LongInt(Key)), SHelpCantShowHelpFile);
    finally
      StrDispose(HelpFile);
    end;
  finally
    StrDispose(Key);
  end;
end;

procedure THelper.ShowContents;
var
  HelpFile: PChar;
begin
  HelpFile := StrAlloc(Length(Application.HelpFile) + 1);
  try
    StrPCopy(HelpFile, Application.HelpFile);
    Check(Application.HelpCommand(HELP_FORCEFILE, 0), SHelpCantHelp);
    Check(Application.HelpCommand(HELP_CONTENTS,
                  0), SHelpCantShowTOC);
  finally
    StrDispose(HelpFile);
  end;
end;

procedure THelper.ShowContext(ContextNumber: LongInt);
var
  HelpFile: PChar;
begin
  HelpFile := StrAlloc(Length(Application.HelpFile) + 1);
  try
    StrPCopy(HelpFile, Application.HelpFile);
    Check(Application.HelpCommand(HELP_FORCEFILE, 0), SHelpCantHelp);
    Check(Application.HelpCommand(HELP_CONTEXT,
                  ContextNumber), SHelpCantShowCTX);
  finally
    StrDispose(HelpFile);
  end;
end;

procedure THelper.SearchDialog;
begin
  SearchTopic('', True);
end;

procedure THelper.HelpMacro(const MacroName: string);
var
  Key:      PChar;
  HelpFile: PChar;
  Command:  Word;
begin
  Key := StrAlloc(Length(MacroName) + 1);
  try
    StrPCopy(Key, MacroName);
    HelpFile := StrAlloc(Length(Application.HelpFile) + 1);
    try
      StrPCopy(HelpFile, Application.HelpFile);
      Check(Application.HelpCommand(HELP_FORCEFILE, 0),
      SHelpCantHelp); Check(Application.HelpCommand(HELP_COMMAND,
                    LongInt(Key)), SHelpCantMacro);
    finally
      StrDispose(HelpFile);
    end;
  finally
    StrDispose(Key);
  end;
end;

procedure THelper.HelpOnHelp;
begin
  HelpMacro('HelpOn()');
end;

procedure THelper.ShowContextString(const ContextString: string);
begin
  Check(Application.HelpCommand(HELP_FORCEFILE, 0), SHelpCantHelp);
  Check(Application.HelpJump(ContextString), SHelpCantShowTopic);
end;

end.

---------------- chew here for HELPCONS.PAS

unit Helpcons;

interface

const
 SHelpCantHelp          = 30000;
 SHelpCantShowTopic     = SHelpCantHelp + 1;
 SHelpCantShowContext   = SHelpCantShowTopic + 1;
 SHelpCantShowHelpFile  = SHelpCantShowContext + 1;
 SHelpCantShowTOC       = SHelpCantShowHelpFile + 1;
 SHelpCantShowCTX       = SHelpCantShowTOC + 1;
 SHelpCantMacro         = SHelpCantShowCTX + 1;

implementation

end.

---------------- chew here for HELPERRC

#include "helpcons.pas"

STRINGTABLE 
{
 SHelpCantHelp, "Can't open helpfile"
 SHelpCantShowTopic, "Can't show help topic"
 SHelpCantShowContext, "Can't show Helpcontext"
 SHelpCantShowHelpFile, "Can't search helpfile"
 SHelpCantShowTOC, "Can't show help contents"
 SHelpCantShowCTX, "Can't show help by contextnumber"
 SHelpCantMacro, "Can't execute help macro"
}

HelpFiles

Question

Can you please tell me how to execute a .hlp file from my app.?

Answer

A:
Executing help file in delphi is very easy. All you have to do is just
assigning Application.HelpFile property and the HelpContext property of each
component you have.

Following example demonstrate how to call a help content in 'MYHELP.HLP'
assigned with a context number on [MAP] section in your help project file.

You can get the help content by pressing F1 or the help button (HelpBtn).

.........

[MAP]
demo    2000;

.........

procedure Form1.FormCreate(sender: TObject);
begin
   Application.HelpFile := 'MYHELP.HLP';
   HelpContext := 2000;
end;

procedure Form1.HelpBtnClick(Sender:TObject);
begin
   Application.HelpContext(HelpContext);
end;

A:
Begin
Application.HelpCommand(HELP_CONTENTS, 0);
end;

Pop that into an event handler.  Make sure you specify the application
help file in the project options first.

Searching your application's help file

Question

How can I search in application's help file?

Answer

{
  The following code demonstrates how to bring up the WinHelp "Search"
  dialog for your application's help file.  You can use TApplication's
  HelpCommand method to send the Help_PartialKey command to the WinHelp
  system. The parameter for this command should be a PChar (cast to a
  longint to circumvent typechecking) that contains the string on
  which you'd like to search.  The example below uses an empty string,
  which invokes "Search" dialog and leaves the edit control in the
  dialog empty.
}
procedure TForm1.SearchHelp;
var
  P: PChar;
begin
  Application.HelpFile := 'c:\delphi\bin\delphi.hlp';
  P := StrNew('');
  Application.HelpCommand(Help_PartialKey, longint(P));
  StrDispose(P);
end;










© DelphiRSS.com. All Rights Reserved.