Windows Phoneアプリケーション開発入門

第4回Windows phoneでテキストエディタを作ろう!(2)

はじめに

前回は、フォームデザイナを使ってテキストエディタに見えるようにコントロールを配置しました。メニューアイテムもそのうちのひとつで、⁠コピー」をクリックするとClipboardクラスを利用してテキストのコピーを行うように実装しました。やり直し機能はTextBoxコントロールのUndoメソッドで実装しました。

「Windows phoneでテキストエディタを作ろう!」の2回目では、⁠切り取り」⁠貼り付け」を実装しましょう。今回も実装後のサンプルプログラムを用意しています。

切り取りと貼り付け機能の実装は難しい……

「切り取り」は選択されているテキストを切り取りクリップボードにコピーします。切り取られたテキストはTextBoxから消えます。⁠貼り付け」はそのクリップボードにコピーされたテキストをTextBoxに貼り付けます。

この「切り取り」「貼り付け」の実装は若干難しいです。.NET Compact Frameworkでは、デスクトップ版の.NET Frameworkと比べると実装されていないメソッド・プロパティ・イベントが存在しているというのは前回でも書きましたが、今回実装する「切り取り」⁠貼り付け」に関してもTextBoxコントロールにはそれ用のメソッドが存在しません。

TextBoxコントロールは入力したテキストをTextプロパティを通して取得したり設定したりすることが可能ですが、直接Textプロティの文章を消したり挿入すると、Undoメソッドでは元に戻すことができません。さらにCtrl+Xによる切り取り、Ctrl+Vによる貼り付けと挙動が違ってしまい違和感があります。

それでは困りました。さてどうしましょうか。

.NET Compact FrameworkでWindows メッセージに触れる

Windowsでは、1つのオブジェクトを1つのウィンドウとして扱って、ウィンドウ間を「マウスの座標が変わった」⁠とあるキーが押された」⁠再描画の要求」等のメッセージ・パッシングを行っています。このメッセージのことを「Windows メッセージ」と呼びます。Windows Mobileでも同じようにこのWindows メッセージが飛び交っています。

.NET Frameworkでは、基本的に直接Windows メッセージに触れなくてもよいようにと、メソッド化して隠蔽されています。サブセットである.NET Compact Frameworkでは、そのメソッド自体が実装されていないことが多々ありますので、自前で実装しなければいけません。

Microsoft.Windowsce.Forms 名前空間に、C#(マネージドコード)からWindowsメッセージを扱えるようにするMessage構造体とMessageWindowsクラスがあります。試しにコピー機能をClipboardクラスを使わずにWindows メッセージで処理させてみましょう。

参照の追加

Message構造体MessageWindowsクラスの解説の中に以下の記載があります。
名前空間Microsoft.WindowsCE.Forms
アセンブリMicrosoft.WindowsCE.Forms(Microsoft.WindowsCE.Forms.dll 内)

Microsoft.WindowsCE.Forms.dllというDLLアセンブリ内に存在していることを指しています。これらのクラスを使うには、Microsoft.WindowsCE.Forms.dllを参照する必要があります。

ソリューション エクスプローラーのプロジェクト以下にある参照設定を右クリックして、ポップアップから参照の追加を選択します。

図1 参照の追加
図1 参照の追加

参照の追加ダイアログが立ち上がりますので、.NETタブからMicrosoft.Windowsce.Formsを探して選択してください。

図2 ⁠参照の追加]ダイアログ
図2 [参照の追加]ダイアログ

参照設定にMicrosoft.Windowsce.Formsが追加されているのを確認します。

図3 Microsoft.Windowsce.Formsの確認
図3 Microsoft.Windowsce.Formsの確認

Windows メッセージを使ってコピーを実装する

テキストボックスで現在選択されているテキストをCF_TEXT フォーマットでクリップボードにコピーするメッセージIDは「WM_COPY(0x0301)」です。判りやすいように変数を宣言します。

    int WM_COPY = 0x0301;

Createメソッドを使って、メッセージの送信先になるtextEditのメッセージウィンドウのハンドルに対してWM_COPYを割り当てたWM_COPYの識別子を持つメッセージをラップしたMessage構造体作成します。

    Microsoft.WindowsCE.Forms.Message msg
        = Microsoft.WindowsCE.Forms.Message.Create(textEdit.Handle,
                                                   WM_COPY,
                                                   IntPtr.Zero,
                                                   IntPtr.Zero);

このmsgを引数にして、MessageWindowsクラスのSendMessageメソッドで実行します。SendMessageメソッドは、メッセージをパッシングして処理が終わるまで待機します。

    Microsoft.WindowsCE.Forms.MessageWindow.SendMessage(ref msg);

以上のコードをまとめてCopyExメソッドを作りました。

private void CopyEx()
{
    // エディットコントロール現在選択されているテキストを
    // CF_TEXT フォーマットでクリップボードにコピー
    int WM_COPY = 0x0301;
    
    // メッセージの送信先になるtextEditのメッセージウィンドウの
    // ハンドルに対して、WM_COPYの識別子を持つWindows メッセージの作成
    Microsoft.WindowsCE.Forms.Message msg
        = Microsoft.WindowsCE.Forms.Message.Create(textEdit.Handle,
                                                   WM_COPY,
                                                   IntPtr.Zero,
                                                   IntPtr.Zero);
    
    // メッセージをパッシングしてメッセージを処理するまで待機
    Microsoft.WindowsCE.Forms.MessageWindow.SendMessage(ref msg);
}

「切り取り」「貼り付け」の実装

切り取り機能や貼り付け機能を実装する場合も、同様に定義されているメッセージIDを使います。Windows メッセージは古くから使われているのでWebで検索するのもよいかもしれませんが、せっかくなのでWindows Mobile SDKではどのような形で定義されているのか調べてみましょう。

Windows Mobile SDK 6 Professionalをインストールしていれば、以下のパスに格納されています。

C:\Program Files (x86)\Windows Mobile 6 SDK\PocketPC\Include\Armv4i\winuser.h

C/C++向けのヘッダファイルですが、.NET Compact Frameworkアプリケーションの開発でも参考にできると思います。以下のように定義されていますので参考にしてください。

#define WM_CUT                          0x0300
#define WM_COPY                         0x0301
#define WM_PASTE                        0x0302

さて前置きが長くなってしまいましたが、Windows メッセージを使って実装したコピーと同様に「切り取り」⁠貼り付け」の実装を行いましょう。それぞれの中身はCopyExメソッドをベースにしています。

private void menuCut_Click(object sender, EventArgs e)
{
    // エディットコントロールでテキストを現在選択されていれば
    // その部分のテキストをエディットコントロールから削除し、
    // CF_TEXT フォーマットでクリップボードにコピー
    int WM_CUT = 0x0300;
    
    Microsoft.WindowsCE.Forms.Message msg
        = Microsoft.WindowsCE.Forms.Message.Create(textEdit.Handle,
                                                   WM_CUT,
                                                   IntPtr.Zero,
                                                   IntPtr.Zero);
    Microsoft.WindowsCE.Forms.MessageWindow.SendMessage(ref msg);
}

private void menuPaste_Click(object sender, EventArgs e)
{
    // エディットコントロールまたはコンボボックスの
    // 現在のキャレットの位置にクリップボードの内容をコピーします。
    int WM_PASTE = 0x0302;
    
    Microsoft.WindowsCE.Forms.Message msg
        = Microsoft.WindowsCE.Forms.Message.Create(textEdit.Handle,
                                                   WM_PASTE,
                                                   IntPtr.Zero,
                                                   IntPtr.Zero);
    Microsoft.WindowsCE.Forms.MessageWindow.SendMessage(ref msg);
}

これで実装ができました。エミュレータ上で実行すると、テキストの切り取りをした後に、Ctrl+Vで元に戻せるようになっていることが確認できます。

まとめ

今回は、Windows メッセージを使って簡易テキストエディタの「切り取り」⁠貼り付け」の実装をおこないました。.NET Comapct Frameworkでは実装されていないイベントを補うために、サブクラス化と呼ばれる技術が往々にして使われます。その中でWindows メッセージが出てきますので、本連載中に紹介したいと思います。

次回はテキストの「開く」「保存」の実装をしましょう。

以上で今回は終わりです。ありがとうございました。

おすすめ記事

記事・ニュース一覧