テクニカル ノート 28: 状況依存のヘルプのサポート

更新 : 2007 年 11 月

ここでは、ヘルプ コンテキスト ID の決め方など、MFC (Microsoft Foundation Class) のヘルプに関して説明します。状況依存のヘルプを使うには、Visual C++ のヘルプ コンパイラが必要です。

bt2hyd40.alert_note(ja-jp,VS.90).gifメモ :

MFC では、Windows ヘルプを使用して状況依存のヘルプを実装できるだけでなく、HTML ヘルプの使用もサポートしています。このサポートと HTML ヘルプによるプログラミングの詳細については、「HTML ヘルプ : プログラムの状況依存のヘルプ」を参照してください。

サポートされるヘルプの種類

Windows アプリケーションには 2 種類の状況依存のヘルプがあります。1 つは "F1 ヘルプ" と呼ばれるもので、現在アクティブなオブジェクトに対応するコンテキストで Windows ヘルプを起動します。もう 1 つは "Shift+ F1 ヘルプ" と呼ばれるものです。この場合は、マウスのカーソルがヘルプ カーソルに変わり、その状態でユーザーがオブジェクトをクリックしていきます。そうすると、Windows ヘルプが起動され、クリックしたオブジェクトに関するヘルプが表示されます。

MFC では、両方の形式のヘルプが実装されています。さらに、フレームワークでは [索引] と [ヘルプの使い方] の 2 つのヘルプ コマンドもサポートされています。

ヘルプ ファイル

MFC では、単一のヘルプ ファイルが使われるものと想定しています。ヘルプ ファイルの名前とパスは、アプリケーションと同じであることが必要です。たとえば、実行可能ファイルが C:\MyApplication\MyHelp.exe であれば、ヘルプ ファイルは C:\MyApplication\MyHelp.hlp でなければなりません。パスは、CWinApp クラスm_pszHelpFilePath メンバ変数で設定します。

ヘルプ コンテキストの範囲

MFC の既定の実装では、ヘルプ コンテキスト ID の決め方に関するルールを守ってプログラムを作成する必要があります。そのルールとは、特定のコントロールに割り当てる ID の範囲に関するルールです。このルールを変更するには、ヘルプ関係のメンバ関数をオーバーライドします。

0x00000000 - 0x0000FFFF : user defined
0x00010000 - 0x0001FFFF : commands (menus/command buttons)
   0x00010000 + ID_
   (note: 0x18000-> 0x1FFFF is the practical range since command IDs are >=0x8000)
0x00020000 - 0x0002FFFF : windows and dialogs
   0x00020000 + IDR_
   (note: 0x20000-> 0x27FFF is the practical range since IDRs are <= 0x7FFF)
0x00030000 - 0x0003FFFF : error messages (based on error string ID)
   0x00030000 + IDP_
0x00040000 - 0x0004FFFF : special purpose (non-client areas)
   0x00040000 + HitTest area
0x00050000 - 0x0005FFFF : controls (those that are not commands)
   0x00040000 + IDW_

簡単なヘルプ コマンド

MFC では次の 2 つの簡単なヘルプ コマンドが実装されます。

最初のコマンドでは、アプリケーションのヘルプ索引が表示されます。2 番目のコマンドでは、Windows ヘルプの使い方に関するユーザー ヘルプが表示されます。

状況依存のヘルプ (F1 ヘルプ)

通常 F1 キーを押すと、メイン ウィンドウのアクセラレータ テーブルにあるアクセラレータによって、キーストロークが ID_HELP の ID を割り当てられたコマンドに変換されます。ID_HELP コマンドは、メイン ウィンドウまたはダイアログ ボックス上で、ID_HELP の ID が割り当てられているボタンを押した場合も生成されます。

ID_HELP コマンドは、生成方法にかかわりなく、コマンド ハンドラに達するまで通常のコマンドとしてルーティングされます。MFC のコマンド ルーティング アーキテクチャの詳細については、「テクニカル ノート 21」を参照してください。アプリケーションでヘルプを有効にすると、ID_HELP コマンドは CWinApp::OnHelp によって処理されます。つまり、アプリケーション オブジェクトがヘルプ メッセージを受け取ってから、そのコマンドを適切にルーティングします。この動作が必要なのは、既定のコマンド ルーティングでは具体的なコンテキストを十分に判別できないからです。

CWinApp::OnHelp 関数は次の順序で Windows ヘルプを起動しようとします。

  1. ヘルプ ID が割り当てられていてアクティブな AfxMessageBox 呼び出しがないか調べます。メッセージ ボックスが現在アクティブな場合、そのメッセージ ボックスに対応するコンテキストで Windows ヘルプを起動します。

  2. WM_COMMANDHELP メッセージをアクティブなウィンドウに送信します。Windows ヘルプを起動してもウィンドウが応答しない場合は、そのメッセージが処理されるか、最上位ウィンドウが現在のウィンドウになるまで、同じメッセージをそのウィンドウの祖先に送ります。

  3. ID_DEFAULT_HELP コマンドをメイン ウィンドウに送信します。これにより、既定のヘルプが起動します。このコマンドは通常 CWinApp::OnHelpIndex 関数に割り当てられています。

既定の ID の基本値 (コマンド用の 0x10000、ダイアログ ボックスなどのリソース用の 0x20000 など) をグローバルにオーバーライドするには、アプリケーションで CWinApp::WinHelp をオーバーライドします。

この機能をオーバーライドして、ヘルプ コンテキストの判定方法を変更するには、WM_COMMANDHELP メッセージを処理します。フレームワークで用意されるルーティングでは、現在のマルチ ドキュメント インターフェイス (MDI: Multiple Document Interface) 子ウィンドウまでしか対象にならないため、より詳細なヘルプ ルーティングも用意できます。また、特定のダイアログ ボックスやウィンドウ専用のヘルプも用意できます。この場合、オブジェクトの内部状態またはダイアログ ボックス内のアクティブなコントロールなどに応じてヘルプを用意します。

WM_COMMANDHELP

afx_msgLRESULTCWnd::OnCommandHelp(WPARAM wParam, LPARAM lParam)

WM_COMMANDHELP は、ヘルプが要求されたときにアクティブ ウィンドウに送られるプライベート Windows MFC メッセージです。ウィンドウはこのメッセージを受け取ると、その内部状態に合ったコンテキストで CWinApp::WinHelp を呼び出します。

  • lParam
    現在利用できるヘルプ コンテキストを指定します。ヘルプ コンテキストが決まっていない場合、lParam は 0 になります。OnCommandHelp の実装では、lParam のコンテキスト ID を使って別のコンテキストを判定することもあれば、そのままそのコンテキスト ID を CWinApp::WinHelp に渡すこともあります。

  • wParam
    このパラメータは使用しません。常に 0 になります。

OnCommandHelp 関数が CWinApp::WinHelp を呼び出すと、TRUE が返されます。TRUE が返されると、このコマンドは他のクラスや他のウィンドウに送られません。

ヘルプ モード (Shift + F1 ヘルプ)

これは状況依存のヘルプの 2 番目の形式です。通常、Shift + F1 キーを押すか、メニューまたはツール バーを使ってこのモードに入ります。これはコマンド (ID_CONTEXT_HELP) として実装されています。モーダル ダイアログ ボックスまたはメニューがアクティブなときは、コマンドを変換するためのメッセージ フィルタ フックは使われません。そのため、ユーザーがこのコマンドを使える期間は、アプリケーションがメイン メッセージ ポンプ処理 (CWinApp::Run) を実行している間に限られます。

このモードに入ると、ウィンドウ周囲のサイズ変更境界など、アプリケーション独自のカーソルが表示される領域も含めて、アプリケーションのあらゆる領域でヘルプ マウス カーソルが表示されます。ユーザーがマウスまたはキーボードでコマンドを選択すると、コマンドが実行される代わりに、そのコマンドのヘルプが表示されます。ユーザーがツール バーのボタンなど、画面上の表示オブジェクトをクリックすると、そのオブジェクトのヘルプが表示されます。このモードのヘルプは CWinApp::OnContextHelp 関数によって提供されます。

このループの実行中は、メニュー アクセス用のキーを除いて、キーボードからの入力はすべて無効になります。また、ユーザーがアクセラレータ キーを押して対応するコマンドのヘルプを参照できるように、PreTranslateMessage を使用したコマンド変換は引き続き実行されます。

PreTranslateMessage 関数による変換や操作の一部を Shift + F1 ヘルプ モードで禁止する場合は、禁止対象の変換や操作の前に CWinAppm_bHelpMode メンバ変数をチェックしてください。たとえば、PreTranslateMessage 関数の CDialog は、IsDialogMessage 関数を呼び出す前にこの変数をチェックすることによって、Shift + F1 ヘルプ モードでは、モードレス ダイアログ ボックスの "ダイアログ ナビゲーション" キーを無効にします。CWinApp::OnIdle 関数はこのループ中でも呼び出されます。

ユーザーがメニューからコマンドを選択すると、次のように WM_COMMANDHELP メッセージを介して、そのコマンドのヘルプが表示されます。ユーザーがアプリケーション ウィンドウの表示領域をクリックすると、その領域がクライアント領域であるか、非クライアント領域であるかがチェックされます。OnContextHelp 関数が、非クライアント領域でのクリックをクライアント領域でのクリックに自動的に対応付けます。クライアント領域をクリックすると、クリックされたウィンドウに WM_HELPHITTEST が送られます。ウィンドウがゼロ以外の値を返したときは、その値がヘルプのコンテキストとして使われます。0 が返されたときは、OnContextHelp はその親ウィンドウに対してメッセージを送ります。そこでも失敗したときはさらにその親ウィンドウへと送られます。ヘルプ コンテキストを判定できなかったときは、既定の ID_DEFAULT_HELP コマンドがメイン ウィンドウに送られます。メイン ウィンドウは通常 CWinApp::OnHelpIndex に割り当てられます。

WM_HELPHITTEST

afx_msg LRESULT CWnd::OnHelpHitTest(WPARAM, LPARAM lParam)

WM_HELPHITTEST は、MFC のプライベート Windows メッセージで、Shift + F1 ヘルプ モードのときにクリックされたアクティブ ウィンドウに送られます。ウィンドウはこのメッセージを受け取ると、Windows ヘルプで使われる DWORD のヘルプ ID を返します。

  • LOWORD(lParam)
    マウスがクリックされた位置を表すデバイス座標系の X 座標を指定します。これは、ウィンドウのクライアント領域を基準にした相対位置です。

  • HIWORD(lParam)
    Y 座標を指定します。

  • wParam
    このパラメータは使用しません。常に 0 になります。戻り値が 0 以外の場合は、その値のコンテキストで Windows ヘルプを呼び出します。0 の場合は、親ウィンドウに対してヘルプを要求します。

多くの場合、既存のヒット テスト コードを改良できます。WM_HELPHITTEST メッセージの処理の例として、CToolBar::OnHelpHitTest 関数を参照してください。これは、CControlBar のボタンやツール ヒントに使われているヒット テスト コードを改良したものです。

MFC アプリケーション ウィザードによるサポートと MAKEHM

MFC アプリケーション ウィザードは、ヘルプ ファイルの構築に必要なファイル (.cnt、.hpj ファイル) を作成します。その中には、Microsoft ヘルプ コンパイラ用のビルド済みの .rtf ファイルも多く含まれています。多くのトピックは完全な形になっていますが、アプリケーションによっては変更が必要な場合もあります。

"ヘルプ マップ" ファイルは、MAKEHM ユーティリティによって自動的に生成されます。MAKEHM ユーティリティは、アプリケーションの RESOURCE.H ファイルをヘルプ マップ ファイルに変換します。次に例を示します。

#define IDD_MY_DIALOG   2000
#define ID_MY_COMMAND   150

上記のコードは次のように変換されます。

HIDD_MY_DIALOG    0x207d0
HID_MY_COMMAND    0x10096

この形式は、ヘルプ コンパイラがコンテキスト ID (右側の数値) をトピック名 (左側のシンボル) に対応付ける場合と同様の形式です。

MAKEHM のソース コードは、『MFC サンプル』の MAKEHM にあります。

MFC アプリケーション ウィザード実行後のヘルプ サポートの追加

アプリケーションにヘルプを追加する一番良い方法は、アプリケーションを作成する前に、MFC アプリケーション ウィザードの [高度な機能] ページで [コンテキスト ヘルプ] をオンにしておくことです。この方法では、MFC アプリケーション ウィザードが、ヘルプをサポートするために必要なメッセージ マップ エントリを CWinApp 派生クラスに自動的に追加します。

メッセージ ボックスにおけるヘルプ

メッセージ ボックスにおけるヘルプ (警告とも呼ばれます) は、AfxMessageBox 関数によってサポートされます。この関数は MessageBox Windows API のラッパー関数です。

AfxMessageBox には 2 つのバージョンがあり、1 つは文字列 ID を使い、もう 1 つは文字列へのポインタ (LPCSTR) を使います。

int AFXAPI AfxMessageBox(LPCSTR lpszText, UINT nType, UINT nIDHelp);
int AFXAPI AfxMessageBox(UINT nIDPrompt, UINT nType, UINT nIDHelp);

いずれも、ヘルプ ID を指定できます。

前者では、既定の nIDHelp は 0 です。これは、メッセージ ボックスにヘルプがないことを示します。このようなメッセージ ボックスがアクティブなときにユーザーが F1 キーを押しても、アプリケーションがヘルプをサポートしている場合でも、ヘルプは表示されません。これを避けるには、nIDHelp にヘルプ ID を設定する必要があります。

後者では、既定の nIDHelp は -1 です。これは、ヘルプ ID が nIDPrompt と同じであることを示します。ヘルプは、ヘルプ機能を持たないアプリケーションでは動作しません。メッセージ ボックスにヘルプを表示しない場合は、nIDHelp に 0 を渡します。ヘルプを使用可能にしてメッセージを表示する場合に、nIDPrompt とは異なる ID のヘルプを表示するには、nIDPrompt とは異なる正の値を nIDHelp に設定します。

参照

その他の技術情報

番号順テクニカル ノート

カテゴリ別テクニカル ノート