POPUP "編集(\036E\037ヘ)" BEGIN MENUITEM "元に戻す(\036U\037モ)", IDM_UNDO MENUITEM SEPARATOR MENUITEM "切り取り(\036T\037キ)", IDM_CUT MENUITEM "コピー(\036C\037コ)", IDM_COPY MENUITEM "貼り付け(\036P\037ハ)", IDM_PASTE MENUITEM "削除(\036L\037サ)", IDM_DEL MENUITEM "すべての範囲を選択(\036L\037ス)", IDM_ALL MENUITEM SEPARATOR MENUITEM "右端で折り返す(\036W\037ミ)", IDM_FOLD ENDを追加し、Cソースに
case IDM_DEL : SendDlgItemMessage(hDlg, IDEDIT, EM_REPLACESEL, 0, (LPARAM)(LPSTR)""); break; case IDM_CUT : SendDlgItemMessage(hDlg, IDEDIT, WM_CUT , 0, 0); break; case IDM_UNDO : SendDlgItemMessage(hDlg, IDEDIT, EM_UNDO , 0, 0); break; case IDM_COPY : SendDlgItemMessage(hDlg, IDEDIT, WM_COPY , 0, 0); break; case IDM_PASTE: SendDlgItemMessage(hDlg, IDEDIT, WM_PASTE, 0, 0); break; case IDM_ALL: #ifdef WIN32 SendDlgItemMessage(hDlg, IDEDIT, EM_SETSEL, 0, -1); break; #else SendDlgItemMessage(hDlg, IDEDIT, EM_SETSEL, 0, MAKELONG(0,-1)); break; #endifを追加します。
POPUP "検索(\036S\037ケ)" BEGIN MENUITEM "文字列の検索(\036F\037ケ)...", IDM_FIND MENUITEM "次を検索(\036N\037ツ)", IDM_NEXT MENUITEM "文字列の置換(\036R\037チ)...", IDM_REP END検索や置換のダイアログは、コモンダイアログを使う手もありますが、今回は自分で作ってみようと 思います。
メインウインドウ以外のモードレスダイアログは、同じダイアログを複数開くと、まずいです。 そこで必ず、すでにダイアログが開かれているかどうかチェックします。 開かれていた場合は、それをアクティブにします。
case IDM_FIND: if (hDlgSearch) SetActiveWindow(hDlgSearch); else hDlgSearch=CreateDialog(hInstApp, "searchdlg", hDlg, lpSearch); break;検索や置換のダイアログでは、TABキーをコントロール間の移動に使いたいため、 WinMainのメッセージループで、IsDialogMessage()を呼び出します。
while (GetMessage(&msg, NULL, 0, 0)) { if ((hDlgSearch ==NULL || !IsDialogMessage(hDlgSearch, &msg)) && (hDlgReplace==NULL || !IsDialogMessage(hDlgReplace, &msg))){ TranslateMessage(&msg); DispatchMessage(&msg); } }検索や置換のダイアログプロシージャでは、実行ボタンが押されたら、文字列などを取得して、 メインダイアログにWM_COMMANDを送ることにします。実際の検索や置換の作業は、 メインダイアログのダイアログプロシージャが行います。
case IDOK: GetDlgItemText(hDlg, IDS_EDIT, searchstr, sizeof(searchstr)); SendMessage(hDlgMain, WM_COMMAND, IDM_NEXT, 0L); return TRUE;実際の検索処理は、以下のようになります。
最初に、コントロールにEM_GETLINECOUNTを送って、全体の行数を取得しておきます。 それから、現在の選択位置(選択されていない時はカーソル位置)を取得(EM_GETSEL)。 EM_GETSELで取得した位置は、先頭からの文字数なので、それを先頭からの行数と その行の何文字目かに変換します(EM_LINEFROMCHARとEM_LINEINDEX)。 EM_GETLINEで行の内容を取得し、C言語ライブラリのstrstr()で検索します。 見つけたら、EM_SETSELでその範囲を選択します。 見つからなかったら、その旨のメッセージを出して終了します。
置換処理も似たようなものですが、置換はテキストの最初から実行します。 strstr()で検索して、EM_SETSELでその範囲を選択したら、EM_REPLACESELで置換します。
なお、EM_GETLINEで行を取得するとき、そのバッファの先頭2バイトにはバッファサイズを入れておきます。 その情報は上書きされますので、毎回セットする必要があります。
この検索ルーチンは、実は未完成です。なぜなら、strstr()で検索するのは、本当はまずいのです。 テキストに「白血病」検索文字列に「剣」で検索してみてください。誤動作するはずです。 jstrstr()もしくは_mbsstr()のような日本語(マルチバイト)文字列対応の検索関数を使う必要があります。 英語版コンパイラで、このような関数が無い場合、もしくはあってもうまく動作しない場合は、自作しないといけません。 (この問題があるので、大文字小文字の同一視も今回はサポートしていません。単純にtoupper() などを呼び出しても誤動作するのは明白です。)
一つ上のページに戻る