はじめに
「Windows phoneでテキストエディタを作ろう!」の4回目では、「検索」「置換」を実装します。
(テキストエディタと呼ばないかもしれませんが)Windows付属のメモ帳を参考に、デスクトップで動作しているテキストエディタの検索・置換と同等の機能を、どのようにしてWindows phoneアプリケーションに組み込むかを検討しながら実装を進めて行きましょう。
実装後のサンプルプログラムを用意しています。UIに手を入れていますので実際にVisual Studioのフォームデザイナを確認しながら追っていただければ、より理解が早いかと思います。
検索機能のUIを検討する
メモ帳のメニューから検索を選択すると、検索専用のダイアログが表示されます。
テキストエディタに触ったことはありますか? 検索を行う時には、大抵文章が表示されているフォームとは別に小さなダイアログを表示し、文章を確認しながら検索ワードや置換ワードを入力していたのではないでしょうか。
今作っているアプリケーションでもメモ帳と同様に、小さなダイアログを表示して検索機能を設けたいところですが、Windows phoneアプリケーションのダイアログと言えば「Windows phoneでテキストエディタを作ろう!」の3回目で使用したOpenFileDialogのように全画面表示されてしまいます。
前述の通り、検索と置換は文章を確認しながら行いたいのでダイアログは使用せずに、テキストボックスの上部にパネルを用意し、そのパネル上から検索と置換の操作を行うようにしましょう。
検索・置換用のパネルの作成
フォームデザイナのツールボックスからPanelコントロールを選択し、TextBox上にPanelを配置します。Panelの以下のプロパティを変更します。
Name | panelSearch |
Dock | Top |
Visible | False |
Visibleプロパティは、コントロールの表示・非表示を設定するプロパティです。アプリケーションの起動時点にこのパネルを表示させる必要はありませんので、Falseに設定します。
また、TextBoxよりもPanelを後に追加しているため、Panelが最前面に表示されTextBoxが隠れてしまっています。TextBoxを右クリックしポップアップから「最前面へ移動」を選択すると、TextBoxが適切に表示されます。
Panel上に検索ワード・置換ワードの入力欄や、実際に検索処理を行う為のボタン等のコントロールを配置しましょう。
それぞれのコントロールの名前は以下のように設定しました。
textSearchWord | 検索ワードの入力欄 |
textReplaceWord | 置換ワードの入力欄 |
btnSearch | 検索・置換処理ボタン |
btnPanelClose | パネル閉ボタン |
パネルの表示・非表示処理の実装
検索パネルへの各コントロールの配置が完了しましたので実装を進めて行きます。ここではパネルの表示・非表示処理の実装を行います。
検索と置換で同じパネルを共有して使いたいので、現在のモードを持って処理する内容を切り分けたいと思います。検索か置換かのパネルの状態を定義したPanelModeを定義し、現在の状態を持つPanelMode型の変数nowPanelModeを宣言します。
このnowPanelModeの状態に応じて処理を切り分けます。
「検索」選択時のパネルの表示
メニューから「検索」が選択された場合の処理を記します。検索を行いますので、パネルのモードには、PanelMode.Searchを設定します。
使用しないtextReplaceWordのEnabledプロパティにfalseを設定し無効にしています。パネルに対する設定が完了後、検索パネルのVisibleプロパティにtrueを設定し、検索パネルを表示します。
「置換」選択時のパネルの表示
メニューから「置換」が選択された場合の処理を記します。検索パネルの表示時と同様の処理を行います。置換ですのでパネルのモードはPanelMode.Replaceを設定します。
置換するテキストを入力したいので、textReplaceWordを有効にしています。最後にパネルのVisibleプロパティをtrueに設定し置換パネルを表示します。
検索パネルの非表示処理
「閉じる」ボタンを押下すると、検索パネルを非表示にしたいです。パネルの表示処理とは逆にpanelSearchのVisibleプロパティをfalseに設定することで、パネルを閉じることができます。
「検索」「置換」の実装
検索ボタンが押下された時の処理を記します。検索と置換の共通処理部分のみ記載しています。非共通部分は後で書きます。
長いコードなので特に注意すべき点のみを抜き出して説明します。
入力されたテキストから対象となるワードを検索するのに、String.IndexOf(string, int)メソッドを使用しています。このIndexOfメソッドは最初に発見した検索ワードの開始位置を返します。見つからなかった場合は-1を返しますので、wordIdxの位置をチェックし処理を行わずに終了します。
パネルモードごとの処理を行った後、現在の表示領域外にカーソルが行ってしまうとユーザーから確認する手段がなくなってしまいます。TextBoxコントロールのScrollToCaretメソッドでカレットが表示領域に入るまでスクロールを行います。
「検索」の実装
検索の実装は選択状態にするだけです。
「置換」の実装
次に置換の実装を行います。TextBoxコントロールには置換用のメソッドは無いため、Windowsメッセージを送り置換処理に対応します。
置換処理を行うWindows メッセージは、EM_REPLACESEL(http://msdn.microsoft.com/en-us/library/aa929135.aspx)です。現在選択選択されているテキストに対して「置換」を行います。もし範囲選択されていなければカーソル位置に対しての「挿入」となります。ここでは、置換として扱いたいので実際に置き換える前に、検索ワードを選択状態にしてからEM_REPLACESELを送ることにします。
コピーやペーストの時に実装した処理と違い、EM_REPLACESELには引数を渡す必要があります。引数wParamは、アンドゥを許可するかどうかを指定します。1の場合はアンドゥを許可し、0の場合は許可しません。引数lParamには、置換ワードを指定します。
まとめ
今回は、検索・置換機能の実装を行いました。文字列を発見すればテキストを選択するだけの「検索」と違い、.NET Compact Frameworkでの「置換」処理ではWindowsメッセージを使う必要がありました。結果、コードを量が多くなってしまい少し複雑になってしましました。.NET Frameworkでの開発経験のある方からすると、思いのほかWindowsメッセージを使うと感じられたかもしれません。
さて、この「Windows phoneでテキストエディタを作ろう!」も予定していた機能の実装が完了しました。これで.NET Compact Frameworkで作るWindows phoneアプリケーション開発の一通りのエッセンスを経験したことになります。次回は、インストーラファイルを作成したいと思います。
以上で今回は終わりです。ありがとうございました。