はじめに
「Windows phoneでテキストエディタを作ろう!」
(テキストエディタと呼ばないかもしれませんが)
実装後のサンプルプログラムを用意しています。UIに手を入れていますので実際にVisual Studioのフォームデザイナを確認しながら追っていただければ、
- サンプルプログラム
(101KB)
検索機能のUIを検討する
メモ帳のメニューから検索を選択すると、

テキストエディタに触ったことはありますか? 検索を行う時には、
今作っているアプリケーションでもメモ帳と同様に、
前述の通り、
検索・置換用のパネルの作成
フォームデザイナのツールボックスからPanelコントロールを選択し、
Name | panelSearch |
---|---|
Dock | Top |
Visible | False |
Visibleプロパティは、
また、

Panel上に検索ワード・

それぞれのコントロールの名前は以下のように設定しました。
textSearchWord | 検索ワードの入力欄 |
---|---|
textReplaceWord | 置換ワードの入力欄 |
btnSearch | 検索・ |
btnPanelClose | パネル閉ボタン |
パネルの表示・非表示処理の実装
検索パネルへの各コントロールの配置が完了しましたので実装を進めて行きます。ここではパネルの表示・
検索と置換で同じパネルを共有して使いたいので、
private enum PanelMode
{
Search, // 検索モード
Replace // 置換モード
}
private PanelMode nowPanelMode;
このnowPanelModeの状態に応じて処理を切り分けます。
「検索」選択時のパネルの表示
メニューから
private void menuItemSearch_Click(object sender, EventArgs e)
{
// 検索パネルのモードを「検索」に設定
nowPanelMode = PanelMode.Search;
// ボタンのテキストを「検索」に設定
btnSearch.Text = "検索";
// 置換ワード欄への入力を無効にする
lblReplaceWord.Enabled = false;
textReplaceWord.Enabled = false;
// 検索パネルを開く
panelSearch.Visible = true;
}
使用しないtextReplaceWordのEnabledプロパティにfalseを設定し無効にしています。パネルに対する設定が完了後、

「置換」選択時のパネルの表示
メニューから
private void menuItemReplace_Click(object sender, EventArgs e)
{
// 検索パネルのモードを「置換」に設定
nowPanelMode = PanelMode.Replace;
// ボタンのテキストを「置換」に設定
btnSearch.Text = "置換";
// 置換ワード欄への入力を有効にする
lblReplaceWord.Enabled = true;
textReplaceWord.Enabled = true;
// 検索パネルを開く
panelSearch.Visible = true;
}
置換するテキストを入力したいので、

検索パネルの非表示処理
「閉じる」
private void btnPanelClose_Click(object sender, EventArgs e)
{
// 検索パネルを閉じる
panelSearch.Visible = false;
}
「検索」「置換」の実装
検索ボタンが押下された時の処理を記します。検索と置換の共通処理部分のみ記載しています。非共通部分は後で書きます。
private void btnSearch_Click(object sender, EventArgs e)
{
// 検索ワードの取得
string searchWord = textSearchWord.Text;
// 検索ワードが空文字列だった場合、処理を行わない
if (searchWord == "") return;
// 検索開始位置を現在のカーソル位置から算出
int startIdx = textEdit.SelectionStart + textEdit.SelectionLength;
// テキストの終端まで達した場合、処理を行わない
if (startIdx > textEdit.Text.Length) return;
// 検索開始位置から検索を開始して、
// 最初に見つけた検索ワードの位置を取得
int wordIdx = textEdit.Text.IndexOf(searchWord, startIdx);
// 検索ワードを発見できなかった場合、処理を行わない
if (wordIdx < 0) return;
// 検索パネルのモードによって処理を変更する
switch (nowPanelMode)
{
case PanelMode.Search:
// 検索処理
break;
case PanelMode.Replace:
// 置換処理
break;
}
// カレット(カーソルの選択位置)が表示領域内に入るまでスクロールする
textEdit.ScrollToCaret();
// textEditにフォーカスを当てる
textEdit.Focus();
}
長いコードなので特に注意すべき点のみを抜き出して説明します。
入力されたテキストから対象となるワードを検索するのに、
// 検索開始位置から検索を開始して、
// 最初に見つけた検索ワードの位置を取得
int wordIdx = textEdit.Text.IndexOf(searchWord, startIdx);
// 検索に掛からなかった
if (wordIdx < 0) return;
パネルモードごとの処理を行った後、
// カレット(カーソルの選択位置)が表示領域内に入るまでスクロールする
textEdit.ScrollToCaret();
「検索」の実装
検索の実装は選択状態にするだけです。
// 検索ワードを選択状態に変更する
textEdit.Select(wordIdx, searchWord.Length);
「置換」の実装
次に置換の実装を行います。TextBoxコントロールには置換用のメソッドは無いため、
置換処理を行うWindows メッセージは、
コピーやペーストの時に実装した処理と違い、
// 検索ワードを選択します
textEdit.Select(wordIdx, searchWord.Length);
// 置換ワードの取得
string word = textReplaceWord.Text;
// 現在選択選択されているテキストに対して置換処理を行う
// Windows メッセージのIDを定義
int EM_REPLACESEL = 0x00C2;
// 引数wParamは、0の場合アンドゥを不可に、1の場合は可能にする
IntPtr wParam = new IntPtr(1);
// 引数lParamは、置換を行うテキストを指定する。
// マネージstringの内容をネイティブ向けのBSTRにコピーする
IntPtr lParam
= System.Runtime.InteropServices.Marshal.StringToBSTR(word);
Microsoft.WindowsCE.Forms.Message msg
= Microsoft.WindowsCE.Forms.Message.Create(textEdit.Handle,
EM_REPLACESEL,
wParam,
lParam);
Microsoft.WindowsCE.Forms.MessageWindow.SendMessage(ref msg);
// ネイティブ向けのBSTRは、解放が必要なので、
// 使用後は明示的に解放を行う。
System.Runtime.InteropServices.Marshal.FreeBSTR(lParam);
まとめ
今回は、
さて、
以上で今回は終わりです。ありがとうございました。