メニューの「ヘルプ」「キーワード検索」を選択すると左のような
ダイアログボックスが表示されるようにします。キーワードを複数指定する場合は
セミコロンで区切って入力します。
キーワード検索をするにはHH_KEYWORD_LOOKUPコマンドを使います。
HH_AKLINK構造体は次のように定義されています。HH_KEYWORD_LOOKUPコマンド pszFileには、キーワードを含むchmファイルを指定します。 dwDataにはHH_AKLINK構造体へのポインタを指定します。
cbStructは、この構造体のサイズを指定します。typedef struct tagHH_AKLINK { int cbStruct; BOOL fReserved; LPCTSTR pszKeywords; LPCTSTR pszUrl; LPCTSTR pszMsgText; LPCTSTR pszMsgTitle; LPCTSTR pszWindow; BOOL fIndexOnFail; } HH_AKLINK;
fReservedは、予約済みでFALSEを設定します。
pszKeywordsには、検索対象のキーワードを指定します。複数指定するにはセミコロンで区切ります。
pszUrlは、検索が失敗したときのトピックファイルを指定します。
pszMsgTextには、fIndexOnFailがFALSEでpszUrlがNULLの場合、失敗時のメッセージボックスに 表示するテキストを指定します。
pszMsgTitleは、前項のタイトルを指定します。
pszWindowは、ウィンドウタイプを指定します。
fIndexOnFailは、失敗時にキーワードタブを表示するかどうかを指定します。
では、プログラムを見てみましょう。
メニューは、「ヘルプの最大化」、「キーワード検索」が増えました。// help02.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END POPUP "ヘルプ(&H)" BEGIN MENUITEM "目次(&C)", IDM_MOKUJI MENUITEM "キーワード(&I)", IDM_INDEX MENUITEM "検索(&S)", IDM_SEARCH MENUITEM "ヘルプの最大化(&X)", IDM_MAX MENUITEM "キーワード検索(&K)", IDM_KEY END END ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 187, 73 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "キーワード入力" FONT 9, "MS Pゴシック" BEGIN EDITTEXT IDC_EDIT1,7,7,173,15,ES_AUTOHSCROLL DEFPUSHBUTTON "OK",IDOK,7,52,50,14 PUSHBUTTON "キャンセル",IDCANCEL,129,52,50,14 LTEXT "キーワードはセミコロンで区切って複数入力できます", IDC_STATIC,7,30,173,13 PUSHBUTTON "クリア",IDC_BUTTON1,68,52,50,14 END
ダイアログボックスは、上の図も参照してください。
HTMLヘルプの場所をいちいち書くのは面倒なのでHTMLHELPで 代用する事にしました。// help02.cpp #ifndef STRICT #define STRICT #endif #define HTMLHELP "e:\\MyDocument\\htmlhelp\\novo\\insulin.chm" #include <windows.h> #include <windowsx.h> #include <htmlhelp.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); HINSTANCE hInst; char szClassName[] = "help02"; //ウィンドウクラス DWORD dwCookie; //クッキー char szKeyWords[1024]; //キーワード入力用
コントロール関連のマクロを使うのでwindowsx.hをインクルードしています。
ダイアログボックスのプロシージャのプロトコル宣言が増えました。また、 検索するキーワード格納用のグローバル変数も増えました。 インスタンスハンドルを格納するグローバル変数も増えました。
いつもと同じですが、インスタンスハンドルをグローバル変数にコピーしています。int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; hInst = hCurInst; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; HtmlHelp(NULL, NULL, HH_INITIALIZE, (DWORD)&dwCookie); while (GetMessage(&msg, NULL, 0, 0)) { if (!HtmlHelp(NULL, NULL, HH_PRETRANSLATEMESSAGE, (DWORD)&msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; }
HH_INITIALIZEコマンドとHH_PRETRANSLATEMESSAGEコマンドを忘れないでください。
InitApp, InitInstanceの各関数に変更はありません。
親ウィンドウのプロシージャです。//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; HH_FTS_QUERY q; char szHelp[256]; HWND hHelp; static int wx, wy; HH_AKLINK ak; switch (msg) { case WM_CREATE: wx = GetSystemMetrics(SM_CXSCREEN); wy = GetSystemMetrics(SM_CYSCREEN); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_KEY: id = DialogBox(hInst, "MYDLG", hWnd, (DLGPROC)MyDlgProc); if (id == IDCANCEL) break; memset(&ak, 0, sizeof(HH_AKLINK)); ak.cbStruct = sizeof(HH_AKLINK); ak.pszKeywords = szKeyWords; ak.pszMsgText = "そのようなキーワードはありません"; ak.pszMsgTitle = "エラー"; HtmlHelp(hWnd, HTMLHELP, HH_KEYWORD_LOOKUP, (DWORD)&ak); break; case IDM_MAX: hHelp = HtmlHelp(hWnd, HTMLHELP, HH_GET_WIN_HANDLE, (DWORD)"MyWin01"); if (hHelp) MoveWindow(hHelp, 0, 0, wx, wy, TRUE); else MessageBox(hWnd, "ヘルプは表示されていません", "Error", MB_OK); break; case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_MOKUJI: strcpy(szHelp, HTMLHELP); strcat(szHelp, "::/oldex/q01.htm"); hHelp = HtmlHelp(hWnd, szHelp, HH_DISPLAY_TOC, NULL); break; case IDM_INDEX: HtmlHelp(hWnd, HTMLHELP, HH_DISPLAY_INDEX, (DWORD)"ガラス球"); break; case IDM_SEARCH: //なぜか正しく動作しません memset(&q, 0, sizeof(HH_FTS_QUERY)); q.cbStruct = sizeof(HH_FTS_QUERY); q.fUniCodeStrings = FALSE; q.pszSearchQuery = "インスリン"; q.iProximity = HH_FTS_DEFAULT_PROXIMITY; q.fStemmedSearch = FALSE; q.fTitleOnly = FALSE; q.fExecute = TRUE; q.pszWindow = NULL; HtmlHelp(hWnd, HTMLHELP, HH_DISPLAY_SEARCH, (DWORD)&q); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { if (HtmlHelp(hWnd, HTMLHELP, HH_GET_WIN_HANDLE, (DWORD)"MyWin01")) HtmlHelp(NULL, NULL, HH_CLOSE_ALL, 0) ; else MessageBox(hWnd, "閉じるべきヘルプはありません", "ヘルプ", MB_OK); DestroyWindow(hWnd); } break; case WM_DESTROY: HtmlHelp(NULL, NULL, HH_UNINITIALIZE, dwCookie); PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }
HtmlHelp関数の第2引数はHTMLHELPで代用してあります。
WM_CREATEメッセージが来たらスクリーンの大きさを調べてwx, wyに格納しています。 GetSystemMetrics関数については第67章で少しだけ解説があります。
メニューからIDM_KEYが選択されたら、ダイアログボックスを呼び出します。 キャンセルボタンが押されたら何もしません。
OKボタンが押されたらHH_AKLINK構造体のメンバをセットしてHH_KEYWORD_LOOKUPコマンドを 実行します。
メニューからIDM_MAXが選択されたら、ヘルプのウィンドウハンドルを調べて、 スクリーンと同じ大きさにします。
ダイアログボックスのプロシージャです。LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { static HWND hEdit; switch (msg) { case WM_INITDIALOG: hEdit = GetDlgItem(hDlg, IDC_EDIT1); Edit_SetText(hEdit, szKeyWords); SetFocus(hEdit); return TRUE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: Edit_GetText(hEdit, szKeyWords, sizeof(szKeyWords)); EndDialog(hDlg, IDOK); return TRUE; case IDCANCEL: EndDialog(hDlg, IDCANCEL); return TRUE; case IDC_BUTTON1: Edit_SetText(hEdit, ""); SetFocus(hEdit); return TRUE; } return FALSE; } return FALSE; }
WM_INITDIALOGメッセージが来たら、エディットコントロールの ハンドルを調べておきます。そして、szKeyWordsをここに表示します。
OKボタンが押されたら、エディットコントロールの内容をszKeyWordsに保存して、 ダイアログを閉じます。
キャンセルボタンが押されたら、何もせずにダイアログを閉じます。
「クリア」(IDC_BUTTON1)ボタンが押されたら、エディットコントロールの内容を クリアします。
さて、今回は簡単でした。
Update 28/Aug/2000 By Y.Kumei