# ヘルプ要求への応答

この章では、ヘルプ・ダイアログ・ウィジェットのリソースの設定によって、さまざまなヘルプ情報を表示する方法を説明します。

HRDC.HReq.mkr.2
HRDC.HReq.mkr.3
HRDC.HReq.mkr.5
HRDC.HReq.mkr.6
HRDC.HReq.mkr.7
HRDC.HReq.mkr.8
HRDC.HReq.mkr.9
HRDC.HReq.mkr.11
HRDC.HReq.mkr.12

## ヘルプの要求

アプリケーションの使用中にユーザがヘルプを要求したときは、どのヘルプ・トピックを表示すべきか、アプリケーション側で決定します。

### コンテキストの検知

「バージョン」のヘルプ（通常は著作権のトピックが表示されます）など、特定の情報を明示的に要求するヘルプ要求もあります。しかし、それ以外のヘルプ要求では、コンテキストの検知を必要とします。つまり、アプリケーションにおけるユーザの現在のコンテキストに基づいて、適切なヘルプ・トピックを選択する処理が必要となります。

たとえば、アプリケーションは、適切なヘルプ・トピックを判断するため、モードや設定のステータスをテストすることがあります。あるいは、入力フィールドの値をテストし、その値が有効でなければ詳細ヘルプを、有効であれば一般ヘルプを表示することもあります。

### エントリ・ポイント

エントリ・ポイント とは、ヘルプ・ボリューム内の特定の場所のことで、通常はトピックの先頭です。アプリケーション内でヘルプを要求すると、エントリ・ポイントに直接アクセスできます。

設計者の観点から言えば、エントリ・ポイントはヘルプ・ボリュームの適切な場所にIDを指定することによって設定されます。プログラマの観点から言えば、ユーザがヘルプを要求できるようにし、特定のヘルプが要求されたときに適切なIDを使用することでエントリ・ポイントが作成されます。

ユーザがヘルプを要求する方法には、次の４種類があります。

- [ヘルプ]キー（ほとんどのキーボードでは[F1]キー）を押す

- ダイアログ・ボックスの[ヘルプ]ボタンをクリックする

- アプリケーションの[ヘルプ]メニューからコマンドを選択する

- [アイテムヘルプ]を選択する

## ヘルプ・トピックの表示

ヘルプが要求されると、アプリケーションが表示するヘルプ・トピックを決定します。次に、ヘルプ・ダイアログを（必要ならば）作成し、管理して、ヘルプ・トピックを表示するための適切なリソースを設定します。

ほとんどの要求については、アプリケーションのヘルプ・ボリュームの一部であるヘルプ・トピックが表示されます。しかし、ヘルプ・システムのヘルプ・ダイアログは、マニュアル・ページ、テキスト・ファイル、単純なテキスト文字列を表示することもできます。

ヘルプ・システムのダイアログは、Xt イントリンシクスと Motif プログラミングに排他的に基づいているので、他のウィジェットと同じように、リソースを設定することによって、ヘルプ・ダイアログ内の値を変更できます。

`DtNhelpType` リソースは、表示すべき情報の種類を決定します。次のいずれかの値が設定されます。

- `DtHELP_TYPE_TOPIC` ヘルプ・ボリュームの一部である通常のヘルプ・トピックを表示します。ボリュームは `DtNhelpVolume` リソースを設定して指定します。トピックは `DtNLocationId` リソースを設定して指定します。

- `DtHELP_TYPE_STRING` アプリケーションが提供する文字列を表示します。自動的な行の折り返しは使用できないため、改行は文字列で指定してください。文字列は `DtNstringData` リソースを設定して指定します。

- `DtHELP_TYPE_DYNAMIC_STRING` アプリケーションが提供する文字列を、行の折り返しでテキストをフォーマットした状態で表示します。改行は段落の区切りを示します。文字列は `DtNstringData` リソースを設定して指定します。

- `DtHELP_TYPE_FILE` テキスト・ファイルを表示します。表示するファイルの名前は `DtNhelpFile` リソースを設定して指定します。

- `DtHELP_TYPE_MAN_PAGE` ヘルプ・ダイアログのマニュアル参照ページ（マニュアル・ページ）を表示します。表示するマニュアル・ページは `DtNmanPage` リソースを設定して指定します。

上記の値は、`Help.h` ファイルで定義されています。

### 関連項目

- HRDC.CrDia.mkr.1

### ヘルプ・トピックを表示するには

1. ヘルプ・ダイアログを作成します。

2. 次のようなヘルプ・ダイアログのリソースを設定します。

   `DtNhelpType` | `DtHELP_TYPE_TOPIC` を設定します。
   `DtNhelpVolume` | アプリケーションのボリューム名を設定します。
   `DtNlocationId` | 表示するトピックのIDを設定します。

   サイズやタイトルなど、その他の値も設定できます。

3. `XtManageChild()` を使用してダイアログを管理します。

#### 例

次のプログラム・セグメントは、IDである getting-started が付いたトピックを、ボリューム `MyVolume` に表示します。

    ac = 0;
    XtSetArg (al[ac], DtNhelpType,   DtHELP_TYPE_TOPIC);  ac++;
    XtSetArg (al[ac], DtNhelpVolume,  “MyVolume”);         ac++;
    XtSetArg (al[ac], DtNlocationId,  “getting-started”);  ac++;
    XtSetArg (al[ac], DtNcolumns,    40);                  ac++;
    XtSetArg (al[ac], DtNrows,       12);                  ac++;
    XtSetValues (helpDialog, al, ac);
    XtManageChild (helpDialog);

ヘルプ・ボリューム `MyVolume` が未登録の場合、`DtNhelpVolume` の値を指定するために、`MyVolume.sdl` ファイルへの絶対パスが必要です。

### テキスト文字列を表示するには

1. 簡易ヘルプ・ダイアログを作成します。

   一般ヘルプ・ダイアログでも使用できますが、このダイアログの機能は文字列データには、ほとんど適用されないので、使用しないようにしてください。

2. 次のようなヘルプ・ダイアログのリソースを設定します。

   `DtNhelpType` | `DtHELP_TYPE_DYNAMIC_STRING`（行の折り返しを使用する場合）または `DtHELP_TYPE_STRING`（改行を有効にしたい場合）を設定します。
   `DtNstringData` | 表示する文字列を設定します。文字列のコピーは、内部的に保持されるので、保存する必要はありません。

   サイズやタイトルなど、その他の値も設定できます。

3. `XtManageChild()` を使用してダイアログを管理します。

#### 例

次のプログラム・セグメントは、変数 descriptionString に格納された文字列を表示します。

    ac = 0;
    XtSetArg (al[ac], DtNhelpType,   DtHELP_TYPE_DYNAMIC_STRING); ac++;
    XtSetArg (al[ac], DtNstringData, (char *)descriptionString);   ac++;
    XtSetValues (quickHelpDialog, al, ac);
    XtManageChild (quickHelpDialog);

ヘルプ・ダイアログは、データのコピーを作成するため、文字列が不要になった場合はメモリを解放できます。

    XtFree (descriptionString);

### テキスト・ファイルを表示するには

1. 簡易ヘルプ・ダイアログを作成するか、ダイアログ・キャッシュのひとつを取り出します。

   一般ヘルプ・ダイアログも使用できますが、このダイアログ機能のほとんどが標準ヘルプ・トピックについてのみ有効なので、使用しないようにしてください。

2. 次のようなヘルプ・ダイアログのリソースを設定します。

   `DtNhelpType` | `DtHELP_TYPE_FILE` を設定します。
   `DtNhelpFile` | 表示するファイル名を設定します。アプリケーションの現在のディレクトリにファイルがない場合は、ファイルへのパスを指定してください。

   サイズやタイトルなど、その他の値も設定できます。特に、幅についてはテキスト・ファイルの標準である80に設定したいときがあるでしょう。

3. `XtManageChild()` を使用してダイアログを管理します。

#### 例

次のプログラム・セグメントは、ファイル `/tmp/printer.list` を表示します。ダイアログのサイズもテキスト・ファイルにより適応するようにします。

    ac = 0;
    XtSetArg (al[ac], DtNhelpType, DtHELP_TYPE_FILE);      ac++;
    XtSetArg (al[ac], DtNhelpFile,  “/tmp/printer.list”);  ac++;
    XtSetArg (al[ac], DtNcolumns,  80);                    ac++;
    XtSetArg (al[ac], DtNrows,     20);                    ac++;
    XtSetValues (quickHelpDialog, al, ac);
    XtManageChild (quickHelpDialog);

### マニュアル・ページを表示するには

1. 簡易ヘルプ・ダイアログを作成します。

   一般ヘルプ・ダイアログも使用できますが、このダイアログ機能のほとんどが 、標準ヘルプ・トピックについてのみ有効なので、使用しないようにしてください。

2. 次のようなヘルプ・ダイアログのリソースを設定します。

   `DtNhelpType` | `DtHELP_TYPE_MAN_PAGE` を設定します。
   `DtNmanPage` | マニュアル・ページの名前を設定します。このリソースの値は、システムの `man` コマンドへ直接渡されます。したがって、特定のセクションを指定するときは、通常の `man` コマンドを入力するときのように、セクション番号の前に、マニュアル・ページ名を付けてください。

   サイズやタイトルなど、その他の値も設定できます。

3. `XtManageChild()` を使用してダイアログを管理します。

#### 例

次のプログラム・セグメントは、`grep` コマンドのマニュアル・ページを表示します。ダイアログのサイズもマニュアル・ページに適応するように設定します。

    ac = 0;
    XtSetArg (al[ac], DtNhelpType, DtHELP_TYPE_MAN_PAGE);  ac++;
    XtSetArg (al[ac], DtNmanPage,   “grep”);   ac++;
    XtSetArg (al[ac], DtNcolumns,  80);                          ac++;
    XtSetArg (al[ac], DtNrows,     20);                          ac++;
    XtSetValues (quickHelpDialog, al, ac);
    XtManageChild (quickHelpDialog);

## ヘルプ・キー（[F1]キー）を使用可能にする

ヘルプ・キー 機能は、すべての Motif マネージャ・ウィジェットとプリミティブ・ウィジェットに組み込まれています。ヘルプ・キーをアクティブにしたいウィジェットにヘルプ・コールバックを追加すると、ヘルプ・キーが使用可能になります。

アプリケーション内では、ヘルプに固有のエントリ・ポイントが必要なウィジェットすべてに、それぞれヘルプ・コールバックを追加してください。そのコールバックを呼び出すまで、ヘルプ・コールバック機能は自動的にウィジェット階層を（シェル・ウィジェットまで）上がります。

ヘルプ・コールバックをマネージャ・ウィジェットに追加する場合、ヘルプ・キーを任意の子ウィジェットのために押すと（子ウィジェットに独自のヘルプ・コールバックがなければ）マネージャのヘルプ・コールバックが呼び出されます。

### ヘルプ・コールバックを追加するには

`XtAddCallback()` 関数を次のように使用します。

    XtAddCallback (
          Widget            widget,
          String            DtNhelpCallback,
          XtCallbackProc    HelpRequestCB,
          XtPointer         clientData );

引き数の説明を以下に示します。

widget | ヘルプ・キーをアクティブにする場所のウィジェットです。
`HelpRequestCB()` | ユーザがヘルプ・キーを押したときにヘルプ要求を処理するアプリケーションの関数です。
clientData | `HelpRequestCB()` 関数に渡すデータです。通常は、表示するトピックを示します。

ユーザがヘルプ・キーを押すと、ウィジェットのヘルプ・コールバックが現在のキーボード・フォーカスとともに呼び出されます。ウィジェットにヘルプ・コールバックがない場合、ヘルプ・コールバックをもつもっとも近い祖先のコールバックが呼び出されます。

ヘルプ・コールバックがみつからない場合は、何も処理されません。この場合、ヘルプ・コールバックをアプリケーションの各シェルに追加するようにしてください。このようにすれば、ユーザのヘルプ要求が失われることがありません。

ヘルプ・コールバックをダイアログ・シェルに追加すると、自動的にダイアログの[ヘルプ]ボタンでヘルプ・コールバックを呼び出せるようになります。

### クライアント・データの重要性

追加したそれぞれのヘルプ・コールバックで clientData に固有の値を指定すると、各ヘルプ・コールバックを処理するために、別々の関数を書かずに済みます。アプリケーションには、すべてのヘルプ要求を処理するひとつのコールバック手続きをもたせることができます。（HRDC.HReq.mkr.10 を参照してください。）コールバック手続きでは、ユーザが要求したヘルプを識別するのに clientData を使用します。つまり、ヘルプ・コールバックを追加するごとに、clientData に固有の値を設定してください。

#### 例

次の例は、ID をエントリ・ポイントに指定する方法のひとつを示しています。`HelpEntryIds.h` ファイルは、各ヘルプ・コールバックの clientData に固有の整数を定義するために使用します。各ウィジェットに対する２つの ID 文字列も定義されます。ひとつは通常の[F1]キーのヘルプ用、もうひとつはアイテムヘルプ・モード（ユーザがウィジェットから記述を取得する場所）用です。

この例では、アプリケーションのユーザ・インタフェースが、Name、Address、および Telephone Number という３つの入力フィールドをもつメイン・ウィンドウであると仮定しています。 次の例は、`HelpEntryIds.h` ファイルの内容です。

    #define HELP_volumeName            "MyVolume"
    #define HELP_MainWindow            100
    #define HELP_MainWindow_ID         "basic-tasks"
    #define HELP_MainWindow_ITEM_ID    "main-window-desc"

    #define HELP_NameField             101
    #define HELP_NameField_ID          "specifying-a-name"
    #define HELP_NameField_ITEM_ID     "name-field-desc"

    #define HELP_AddressField          102
    #define HELP_AddressField_ID       "specifying-an-address"
    #define HELP_AddressField_ITEM_ID  "address-field-desc"

    #define HELP_PhoneField            103
    #define HELP_PhoneField_ID         "specifying-a-phone-no"
    #define HELP_PhoneField_ITEM_ID    "phone-field-desc"

最初にウィジェットを作成したアプリケーションの一部で、次のようにヘルプ・コールバックが各ウィジェットに追加されます。

    XtAddCallback (mainWindow, DtNhelpCallback,
                   HelpRequestCB, HELP_MainWindow);
    XtAddCallback (nameField, DtNhelpCallback,
                   HelpRequestCB, HELP_NameField);
    XtAddCallback (addressField, DtNhelpCallback,
                   HelpRequestCB, HELP_AddressField);
    XtAddCallback (phoneField, DtNhelpCallback,
                   HelpRequestCB, HELP_PhoneField);

`HelpRequestCB()` 関数では、ヘルプ要求を（`switch()` 文によって）ディスパッチするために、clientData パラメータを使用します。ヘルプ・コールバックが[F1]キーによって呼び出された（フラグは “false”）のか、アイテム・ヘルプ・モードでユーザがウィジェットを選択した（フラグは “true”）のかを調べるため、グローバル・フラグ `itemHelp` の値が調べられます。

    XtCallbackProc HelpRequestCB (
          Widget     w,
          XtPointer  clientData,
          XtPointer  callData)
    {
       char    *topicToDisplay;
       Boolean  useQuickHelpDialog;
       /* Determine the topic ID for the given `clientData.' */
       switch ((int)clientData)
         {
           case HELP_MainWindow:
             useQuickHelpDialog = False;
             if (itemHelpFlag)
               topicToDisplay = HELP_MainWindow_ITEM_ID;
             else
               topicToDisplay = HELP_MainWindow_ID;
             break;       case HELP_NameField:
             useQuickHelpDialog = True;
             if (itemHelpFlag)
               topicToDisplay = HELP_NameField_ITEM_ID;
             else
               topicToDisplay = HELP_NameField_ID;
             break;       case HELP_AddressField:
             useQuickHelpDialog = True;
             if (itemHelpFlag)
               topicToDisplay = HELP_AddressField_ITEM_ID;
             else
               topicToDisplay = HELP_AddressField_ID;
             break;       case HELP_PhoneField:
             useQuickHelpDialog = True;
             if (itemHelpFlag)
               topicToDisplay = HELP_PhoneField_ITEM_ID;
             else
               topicToDisplay = HELP_PhoneField_ID;
             break;       default:
             /* An unknown clientData was received. */
             /* Put your error handling code here. */
             return;
             break;
         }
       /* Display the topic. */
       ac = 0;
       XtSetArg (al[ac], DtNhelpType,   DtHELP_TYPE_TOPIC); ac++;
       XtSetArg (al[ac], DtNhelpVolume, HELP_volumeName);    ac++;
       XtSetArg (al[ac], DtNhelpType,   topicToDisplay);     ac++;
       if (useQuickHelpDialog)
         {
            XtSetValues (mainQuickHelpDialog, al, ac);
            XtManageChild (mainQuickHelpDialog);
         }
       else
         {
            XtSetValues (mainHelpDialog, al, ac);
            XtManageChild (mainHelpDialog);
         }
       /* Clear the `item help' flag. */
       itemHelpFlag = False;
     }

上記の関数は、アプリケーションがすべてのヘルプ要求に対して２つのヘルプ・ダイアログ（`mainHelpDialog` と `mainQuickHelpDialog`）を使用し、これらのダイアログがすでに作成されていると想定します。また（Xt 引き数リストで使用される）`al` と `ac` が別の場所で宣言されていることを仮定しています。

## ヘルプ・メニューの提供

CDE/Motif スタイルガイドおよび認証チェックリスト では、各メニュー・バーに[ヘルプ]メニューを含むようにすすめています。[ヘルプ]メニューには、ユーザがアプリケーションでさまざまなオンライン・ヘルプにアクセスできるように、多くのコマンドが用意されています。

もっとも重要なコマンドは次のとおりです。

- `Introduction (概要)` アプリケーションのヘルプのホーム・トピックを表示し、ユーザがハイパーリンクを使用して、必要な任意の情報へナビゲートできるようにします。

- `Using Help (ヘルプの使い方)` 「ヘルプの使い方」を表示します。ユーザにヘルプ・システムの使い方を示す情報です。

- `Version (バージョン)` アプリケーションのバージョン情報と著作権情報を表示します。

その他、特殊キーボードの使い方、アプリケーションの使い方、リファレンス、チュートリアルのそれぞれに関するヘルプを表示するコマンドがあります。CDE/Motif スタイルガイドおよび認証チェックリスト のガイドラインや推奨事項の範囲で、使用する[ヘルプ]メニューが、アプリケーションに適応するように設計してください。

### 関連項目

- HRDC.OrgH.mkr.13 では、設計者がヘルプ・ボリュームのホーム・トピックを作成する方法を説明しています。

- HRDC.OrgH.mkr.16 では、設計者が著作権トピックを作成する方法を説明しています。

- HRDC.H4Hlp.mkr.1 では、ヘルプの使い方をみつける方法と、それをアプリケーションに追加する方法を説明しています。

## アイテムヘルプ・モードのサポート

一部のアプリケーションは、[ヘルプ]メニューに[アイテムヘルプ]コマンドまたは[ヘルプ・モード]コマンドを備えています。このコマンドは、マウス・ポインタを一時的に `?`（疑問符）の形状に再定義し、ユーザに画面の項目を選択するようにプロンプト要求します。項目を選択すると、その項目の説明をアプリケーションが表示します。

便利な関数に `DtHelpReturnSelectedWidgetId()` がありますが、これはポインタを疑問符に変更して、ユーザがウィジェットを選択するのを待ちます。選択したウィジェットのIDが返されます。この関数は `XmTrackingLocate()` に類似していますが、ユーザがエスケープ・キーを押して操作を取り消すと `DtHelpReturnSelectedWidgetId()` は NULL を返す点が異なります。

選択した項目のヘルプを表示するには、単に返されたウィジェットのヘルプ・コールバックを呼び出すだけです。これは、ウィジェットの使用中に、ユーザが[F1]キーを押すのと同じことです。

アイテムヘルプと[F1]ヘルプとを区別させる場合は、ウィジェットのヘルプ・コールバックを呼び出す前にフラグを設定します。こうすると、アイテムヘルプの結果として呼び出すコールバックを判別するときにそのフラグを使用し、それにしたがって応答するようになります。

### アイテムヘルプのサポートを追加するには

1. `DtHelpReturnSelectedWidgetId()` 関数を使用して関数を記述します。この関数では、選択したウィジェットのヘルプ・コールバックを呼び出します。次のステップでは、この関数を `ProcessOnItemHelp()` と呼びますが、他の名前を付けることもできます。

2. [ヘルプ]メニューに`アイテムヘルプ`というラベルの付いたコマンドを追加します。`ProcessOnItemHelp()` 関数を呼び出す起動コールバックを追加します。

3. アイテムヘルプを使用するアプリケーションの各ウィジェットに、ヘルプ・コールバックを追加します。

選択したウィジェットにヘルプ・コールバックがない場合、アプリケーションはその親ウィジェットの検索を試みます。同様に、親ウィジェットにない場合は、その上の階層を検索し、ヘルプ・コールバックがみつかるまで試行を繰り返します。

#### 例

次の手続きは、`ProcessOnItemHelp()` 関数の例ですが、これは[ヘルプ]メニューから `[アイテムヘルプ]` を選択すると呼び出されます。

    void ProcessOnItemHelp(
       Widget widget)
    {
     /* Declare a variable for the selected widget. */
      Widget selWidget=NULL;
      int status=DtHELP_SELECT_ERROR;
      /* Get an application shell widget from our widget hierarchy to
    * pass into DtHelpReturnSelectedWidgetId().   */

      while (!XtIsSubclass(widget, applicationShellWidgetClass))
                       widget = XtParent(widget);
      status = DtHelpReturnSelectedWidgetId(widget, NULL, &selWidget);
      switch ((int)status)
        {
          case DtHELP_SELECT_ERROR:
            printf(“Selection Error, cannot continue\n”);
          break;
          case DtHELP_SELECT_VALID:
             /* We have a valid widget selection, now let's look
            for a registered help callback to invoke.     */

             while (selWidget != NULL)
              {
                if ((XtHasCallbacks(selWidget, XmNhelpCallback)
                                         == XtCallbackHasSome))
                  {
                    /* Found a help callback, so just call it */
                    XtCallCallbacks((Widget)selWidget,
                                    XmNhelpCallback,NULL);
                    break;
                  }
                else
                  /* No help callback on current widget, so try
                  the widget's parent   */
                     selWidget = XtParent(selWidget);
              }
          break;
          case DtHELP_SELECT_ABORT:
            printf("Selection Aborted by user.\n");
          break;
          case DtHELP_SELECT_INVALID:
            printf("You must select a component within your app.\n");
          break;
        }
    }