この章では、ヘルプ・ダイアログ・ウィジェットのリソースの設定によってさまざまなヘルプ情報を表示する方法を説明します。
アプリケーションの使用中にユーザがヘルプを要求したときは、どのヘルプ・トピックを表示するべきか、アプリケーション側で決定します。
「バージョン」のヘルプ (通常は著作権のトピックが表示されます) など、特定の情報を明示的に要求するヘルプ要求もあります。ただしそれ以外のヘルプ要求では、コンテキストを要求します。つまり、アプリケーションにおけるユーザの現在のコンテキストに基づいて適切なヘルプ・トピックを選ぶ処理が必要です。
たとえばアプリケーションは、適切なヘルプ・トピックを判断するため、モードや設定のステータスをテストすることがあります。あるいは、入力フィールドの値をテストし、その値が有効でなければ詳細ヘルプを、有効であれば一般ヘルプを表示することもあります。
エントリ・ポイントとはヘルプ・ボリューム内の特定の場所のことで、通常はトピックの先頭です。アプリケーション内でヘルプを要求すると、エントリ・ポイントに直接アクセスできます。
設計者の見地から言えば、エントリ・ポイントはヘルプ・ボリュームの適切な場所に ID を指定することにより設定されます。プログラマの見地から言えば、ユーザがヘルプを要求できるようにし、特定のヘルプが要求されたときに適切な ID を使用することでエントリ・ポイントが作成されます。
ユーザがヘルプを要求する方法には次の 4 つがあります。
ヘルプ・キー (ほとんどのキーボードでは [F1] キー) を押す
ダイアログ・ボックスの [ヘルプ] ボタンをクリックする
アプリケーションの [ヘルプ] メニューからコマンドを選択する
[アイテムヘルプ] を選択する
ヘルプが要求されると、アプリケーションが表示するヘルプ・トピックを決定します。次にヘルプ・ダイアログを (必要であれば) 作成し、管理して、ヘルプ・トピックを表示するのに適切なリソースを設定します。
ほとんどの要求については、アプリケーションのヘルプ・ボリュームの一部であるヘルプ・トピックが表示されます。しかしヘルプ・システムのヘルプ・ダイアログは、マニュアル・ページ、テキスト・ファイル、単一テキスト文字列を表示することもできます。
ヘルプ・システムのヘルプ・ダイアログは Xt イントリンシクスと OSF/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 ファイルで定義されています。
ヘルプ・ダイアログを作成します。
次のようなヘルプ・ダイアログのリソースを設定します。
DtHELP_TYPE_TOPIC を設定します。
アプリケーションのボリューム名を設定します。
表示するトピックの ID を設定します。
サイズやタイトルなど、その他の値も設定できます。
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 ファイルへの絶対パスが必要です。
簡易ヘルプ・ダイアログを作成します。
一般ヘルプ・ダイアログも使用できますが、このダイアログの機能は文字列データにほとんど適用されないので、使用しないようにしてください。
次のようなヘルプ・ダイアログのリソースを設定します。
DtHELP_TYPE_DYNAMIC_STRING (行の折り返しを使用する場合) または DtHELP_TYPE_STRING (改行を有効にしたい場合) を設定します。
表示する文字列を設定します。文字列のコピーは内部的に保持されるので、保存する必要はありません。
サイズやタイトルなど、その他の値も設定できます。
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 つを取り出します。
一般ヘルプ・ダイアログも使用できますが、このダイアログの機能のほとんどが標準ヘルプ・トピックについてのみ有効なので、使用しないようにしてください。
次のようなヘルプ・ダイアログのリソースを設定します。
表示するファイル名を設定します。アプリケーションの現在のディレクトリにファイルがない場合は、ファイルへのパスを指定してください。
サイズやタイトルなど、その他の値も設定できます。特に幅はテキスト・ファイルの標準である 80 に設定します。
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);
簡易ヘルプ・ダイアログを作成します。
一般ヘルプ・ダイアログも使用できますが、このダイアログの機能のほとんどが標準ヘルプ・トピックについてのみ有効なので、使用しないようにしてください。
次のようなヘルプ・ダイアログのリソースを設定します。
DtHELP_TYPE_MAN_PAGE を設定します。
マニュアル・ページ名を設定します。このリソースの値は、システムの man コマンドへ直接渡されます。したがって特定のセクションを指定するときは、通常 man コマンドを入力するときのように、セクション番号の前にマニュアル・ページ名を付けてください。
サイズやタイトルなど、その他の値も設定できます。
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);
ヘルプ・キー機能は、すべての OSF/Motif マネージャ・ウィジェットとプリミティブ・ウィジェットに組み込まれています。ヘルプ・キーをアクティブにしたいウィジェットにヘルプ・コールバックを追加すると、ヘルプ・キーが使用可能になります。
アプリケーション内では、ヘルプに固有のエントリ・ポイントが必要なウィジェットすべてに、それぞれヘルプ・コールバックを追加してください。そのコールバックを呼び出すまで、ヘルプ・コールバック機能は自動的にウィジェット階層を (シェル・ウィジェットまで) 上ります。
ヘルプ・コールバックをマネージャ・ウィジェットに追加する場合、ヘルプ・キーを任意の子のために押すと、(子ウィジェットに独自のヘルプ・コールバックがなければ) マネージャのヘルプ・コールバックが呼び出されます。
XtAddCallback() 関数を次のように使用します。
XtAddCallback ( Widget widget, String DtNhelpCallback, XtCallbackProc HelpRequestCB, XtPointer clientData );
ヘルプ・キーをアクティブにする場所のウィジェット
ユーザがヘルプ・キーを押したときにヘルプ要求を処理するアプリケーションの関数
HelpRequestCB() 関数に渡すデータ。通常は表示するトピックを示します。
ユーザがヘルプ・キーを押すと、ウィジェットのヘルプ・コールバックが現在のキーボード・フォーカスと共に呼び出されます。ウィジェットにヘルプ・コールバックがない場合、ヘルプ・コールバックを持つ最も近い先祖のコールバックが呼び出されます。
ヘルプ・コールバックが見つからない場合は何も処理されません。この場合、ヘルプ・コールバックをアプリケーションの各シェルに追加するようにしてください。こうすると、ユーザのヘルプ要求が失われることがありません。
ヘルプ・コールバックをダイアログ・シェルに追加すると、自動的にダイアログの [ヘルプ] ボタンでヘルプ・コールバックを呼び出せるようになります。
追加したそれぞれのヘルプ・コールバックで clientData に固有の値を指定すると、各ヘルプ・コールバックを処理するために別々の関数を書かずに済みます。アプリケーションにはすべてのヘルプ要求を処理する 1 つのコールバック・プロシージャを持たせることができます (「ヘルプ・コールバックを追加するには」を参照してください)。コールバック・プロシージャでは、ユーザが要求したヘルプを識別するのに clientData を使用します。つまり、ヘルプ・コールバックを追加するたびに、clientData に固有の値を設定してください。
次の例は、ID をエントリ・ポイントに指定する方法の 1 つを示しています。HelpEntryIds.h ファイルは、各ヘルプ・コールバックの clientData に固有の整数を定義するのに使用します。各ウィジェットに対する 2 つの ID 文字列も定義されます。1 つは通常の [F1] ヘルプ用、もう 1 つはアイテムヘルプ・モード (ユーザがウィジェットから記述を取得する場所) 用です。
たとえば、アプリケーションのユーザ・インタフェースが、Name、Address、Telephone Number という 3 つの入力フィールドを持つメイン・ウィンドウだとします。次の例は 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; }
上記の関数は、アプリケーションがすべてのヘルプ要求に対して 2 つのヘルプ・ダイアログ (mainHelpDialog と mainQuickHelpDialog) を使用し、これらのダイアログがすでに作成されていると想定しています。また、(Xt 引き数リストで使用される) al と ac が別の場所で宣言されたものと見なしています。
『共通デスクトップ環境 スタイル・ガイド』では、各メニュー・バーに [ヘルプ] メニューを含むことを推奨しています。[ヘルプ] メニューには、ユーザがアプリケーションでさまざまなオンライン・ヘルプにアクセスできるように多数のコマンドが入っています。
最も重要なコマンドは次のとおりです。
Introduction (概要)
アプリケーションのヘルプのホーム・トピックを表示し、ユーザがハイパーリンクを使用して必要な任意の情報へナビゲートできるようにします。
Using Help (ヘルプの使い方)
ヘルプの使い方を表示します。ユーザにヘルプ・システムの使い方を示す情報です。
Version (バージョン)
アプリケーションのバージョン情報と著作権情報を表示します。(<copyright> 要素で作成される) 著作権のトピックには、識別子 _copyright が付いています。
その他、特殊キーボードの使い方、アプリケーションの使い方、リファレンス、チュートリアルに関するヘルプを表示するコマンドがあります。『共通デスクトップ環境 スタイル・ガイド』のガイドラインや推奨事項の範囲で、使用する [ヘルプ] メニューが自分のアプリケーションに適応するように設計してください。
「ホーム・トピックを作成するには」では、設計者がヘルプ・ボリュームのホーム・トピックを作成する方法を説明しています。
「メタ情報セクションを作成するには」では、設計者が著作権トピックを作成する方法を説明しています。
第 12 章「「ヘルプの使い方」の作成」では、ヘルプの使い方の検索方法と、アプリケーションへの追加方法を説明しています。
一部のアプリケーションは、[ヘルプ] メニューに [アイテムヘルプ] コマンドまたは [ヘルプ・モード] コマンドを備えています。このコマンドはマウス・ポインタを一時的に ? (クエスチョン・マーク) として再定義し、ユーザに画面の項目を選択するようプロンプト要求します。項目を選択すると、その項目の説明をアプリケーションが表示します。
便利な関数に DtHelpReturnSelectedWidgetId() がありますが、これはポインタをクエスチョン・マークに変更してユーザがウィジェットを選択するのを待ちます。選択したウィジェットの ID が返されます。この関数は XmTrackingLocate() に似ていますが、ユーザがエスケープ・キーを押してオペレーションを取り消すと NULL を返す点が異なります。
選択した項目のヘルプを表示するには、単に返されたウィジェットのヘルプ・コールバックを呼び出すだけです。これはウィジェットの使用中にユーザが [F1] キーを押すのと同じことです。
アイテムヘルプと F1 ヘルプとを区別させる場合は、ウィジェットのヘルプ・コールバックを呼び出す前にフラグを設定します。こうすると、アイテムヘルプの結果として呼び出すコールバックを判別するのにそのフラグを使用し、それに従って応答するようになります。
DtHelpReturnSelectedWidgetId() 関数を使用して関数を記述します。この関数では、選択したウィジェットのヘルプ・コールバックを呼び出します。次のステップではこの関数を ProcessOnItemHelp() と呼びますが、他の名前を付けることもできます。
[ヘルプ] メニューに [アイテムヘルプ] というラベルの付いたコマンドを追加します。ProcessOnItemHelp() 関数を呼び出すアクティブ・コールバックを追加します。
アイテム・ヘルプを使用するアプリケーションの各ウィジェットに、ヘルプ・コールバックを追加します。
選択したウィジェットにヘルプ・コールバックがない場合、アプリケーションはその親ウィジェットの検索を試みます。同様に、親ウィジェットにない場合はその上の階層を検索し、ヘルプ・コールバックが見つかるまで試行を繰り返します。
次のプロシージャは 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; } }