ものえおさむ

C#で作る、あなただけのメモ帳 ~コピー/ペーストの実装~

2009-01-15 15:25:00

はじめに
このブログでは、"Windows アプリケーションってどう作るのかよくわからない" といったプログラマ向けに Visual C# 2008 Express Edition (無償) を使用した Windows アプリケーションに作り方について説明しています。
Visual C# 2008 Express Edition (無償)(※) の入手方法については
この記事 を、プロジェクトのコンパイル方法については この記事を参照してください。

(※)大学生、専門学校生の方は DreamSpark で、商用の Visual Studio を無償で入手することもできます。

あけましておめでとうございます。

前回の記事の投稿からかなり時間がたってしまいました。

言い訳させていただくと以下のような事情がありました。

①年末年始業務が忙しかった(※1)
②このプログを書くのに使用している仮想マシンの入っている外付け HD が壊れた(※2)
tech・Days Japan 2009 の準備でさらに忙しい(※3)

※1 お酒を飲むのも仕事のうちらしいですよ。オトナって大変ですよね。
※2 このプログで紹介している開発環境は仮想マシン上の Visual C# Express Edtion を使用しています。ちなみに普段は物理マシンの Visual Studio 2008 Pro を使用しています。
※3 tech・Days 2009 では ASP.NET 4.0 の機能概要についてお話しします。このセッション、米国 PDC で行われた ASP.NET に関する 7 つのセッションを 1 つにまとめるという非常に無茶、じゃなくて、チャレンジングな内容になっております。ちなみに私、本職では Web (サーバーサイド) の開発啓発活動がメインです。

余談はこれくらいにして、今回は作成しているテキストエディタの [編集(&E)] メニューの [コピー(&C)][切り取り(&T)][貼り付け(&P)] の機能を実装したいと思います。

既に多くの方が御存じのとおり、Windows のコピー機能は、クリップボードと呼ばれる領域を介して行われます。

このクリップボード、複数のアプリケーションからアクセス可能な、いわば共有メモリのような態をなしており、Windows の各オブジェクトを、その固有の情報を持ったまま扱うことができます。

たとえば、Excel のワークシート内で複数のセルを含む領域を選択してコピーした場合、クリップボードには、選択された範囲のセルの数や、各セルの内容、フォント、罫線情報などのオブジェクト固有の情報が保持されます。

また、ペースト先のアプリケーションは、クリップボード内に保持されているデータから自分が処理可能なものでもっとも情報の損失が少ない形式のデータをクリップボードから取り出すことができます。

たとえば、前出の例のようにクリップボードに Excel シートの領域データがあった場合、ペースト先が Excel やその互換アプリケーション、またはオートメーション(※むかしは "OLE:Object Linking and Embedding" なんて言いましたっけね) をサポートするアプリケーションであった場合は、コピー元のセルそのままの情報が貼り付けられます。

また、貼り付けがメモ帳のようなテキスト情報しか扱えないものの場合は、セル内にあったテキストのみが貼り付けられます。

このように、Windows 内の各アプリケーションは、扱う情報の形式は違っても、クリップボードを介して情報のやり取りを行うことができるのです。

ちなみに、古(いにしえ)の Windows には "クリップボードビューア"(※) というアクセサリ ツールが付属しており、これを使用してその内容を確認することができました。

(※) Windows XP ではクリップブックという名前で、以下のパスにひっそりと存在しています。
C:WINDOWS\system32\clipbrd.exe

上記のように、このクリップボードへのアクセス機能は Windows のデスクトップアプリケーションであるならば当然サポートすべき機能であり、この機能をサポートしないと、標準的な Windows アプリケーションにあってしかるべき基本的な利便性を大きく欠くことになります。
 
たとえばあなたが、技術的にも優れ、深く感情を揺さぶられるような感動的なユーザー エクスペリンスを与える先進的なアプリケーションを使用していたとして、編集したデータのコピーや貼り付けができなかったとしたらどうでしょう?

深く裏切られた気分にまではならないとしても、なぜ??? と疑問に思わざるを得ないでしょう。少なくとも開発者に文句の一つも言いたくなることと思います。人によっては怒りにまかせて、とてもここには書けないような誹謗とともに、開発者が愛情を注いで作ったアプリケーションをにべもなくアンインストールしてしまうかも知れません。

そういった意味でも、"Windows アプリケーション"と名乗るのであればコピー/ペースト機能は実装すべきと思うのです。あなたが自分の作るアプリケーションを愛しているならなおさらです。

.NET におけるクリップボードの操作

Windows におけるコピー、貼り付け(ペースト)の処理は、"クリップボードにデータを送る"、"クリップボードからデータを取りだす"、という処理に他なりません。
.NET Framework ではクリップボードを扱うために Clipboard クラス が用意されています。

.NET Framework クラス ライブラリ -『Clipboard クラス
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.clipboard(VS.71).aspx

クリップボードにデータを送るには SetDataObject メソッド、クリップボードからデータを取り出すには GetDataObject メソッドを使用します。

2 つのメソッドの使い方は難しくはありませんがクリップボードには様々なデータが格納されている可能性があるため、データを取り出す際には自分が扱えるデータであるかどうか確認する必要があります。

たとえばクリップボードに保持されたデータがテキストとして扱えるかどうかを確認するためのコードは以下のとおりです。

//クリップボードに保持されている情報を取り出す
IDataObject iData = Clipboard.GetDataObject();
 
//クリップボードに保持されている情報がテキスト形式で取り出せるが確認
if(iData.GetDataPresent(DataFormats.Text))
{
   //文字列にキャストして取り出し
   textBox.Text = (String)iData.GetData(DataFormats.Text);
}

それでは早速アプリケーションに実装してみましょう。

 

テキストエディタへの実装

前の文で "クリップボードを扱うために Clipboard クラス.." と書きましたが、TextBox コントロールに コピー/ ペースト機能を実装するのに Clipboard クラスは使用しません。

なぜならフォーム上に配置されている TextBox コントロールには、コピー/ペースト/削除/元に戻す などの機能がメソッドとしてインプリされており、Clipboard クラスを使用する際に必要な手続きは TextBox コントロール内部で "よしな" に処理してくれているからです。

.NET Framework クラス ライブラリ -『TextBox メソッド
http://msdn.microsoft.com/ja-jp/library/microsoft.office.interop.excel.textbox_methods(VS.80).aspx

スパルタンでコード・ウォリアな開発者の方々は、.NET Windows フォームコントロール が持つこのような機能に対し、"過保護だ" と不快な感情を抱くかもしれませんがここはひとつ TextBox コントロールが持つ気の利いた機能に気持ちよく甘えてみましょう。

Windows 上のテキスト編集処理に使用される機能で、TextBox コントロールに用意されているメソッドは以下のとおりです。

メソッド 機能
Copy コピー
Cut 切り取り
Paste 貼り付け
SelectAll すべて選択
Undo 元に戻す

以降、作成中のテキストエディタに各機能を実装するには、メニューアイテムのイベントハンドラに TextBox コントロールの対応する各機能を記述していきます。

具体的な実装手順を以降で説明します。

前回のこのプログの記事をみて作業されている方は、作業中のプロジェクトを Visual Studio でオープンしてください。

今回からプロジェクトの作成をやってやってみたい方はここからプロジェクトのサンプルをダウンロードしてください。

 

今回の実装の準備- [元に戻す(&U)] メニューの追加

[編集(&E)] メニューに [元に戻す(&U)] アイテムを追加していませんでしたので追加します。
なおメニューアイテムの追加の方法についてはこの記事の内容を参考に行ってください。

追加するメニューアイテム [元に戻す(&U)] に設定を行う各プロパティと値は以下のとおりです。

アイテムのテキスト ショートカット (Name)プロパティ
[元に戻す(&U)] [Ctrl] + [Z] menuUndo

追加する位置は[編集(&E)] メニューの先頭で、区切り線も追加した方が見栄えも良いでしょう。[元に戻す(&U)]アイテムをドラッグ&ドロップして位置を移動し、以下のように配置してください。

 

アウトラインの追加

記述したコードの量も増え、ソースコードもなかなか煩雑になってきたと思いますので、#region を追加してコードを見やすくしましょう。#region を使用すると Visual Studio コード エディタのアウトライン機能を使用して、以下のように折りたたみや展開ができます。

(折り畳んだところ)

メニューごとに #region を記述し、その間に各メニューに関連するイベントハンドラをカット&ペーストで移動してください。
なお、#region内のハンドラの並びは実際のメニューアイテムと同じ並び順にした方が分かりやすくてお勧めです。

//[ファイル(&F)]メニュー関連のイベントハンドラ
#region FileMenu handlers

(※ここに [新規作成(&N)]、[開く(&O)...] などのイベントハンドラを
カット&ペーストで移動)

#endregion

 

メニューアイテムへの実装

それでは実際にメニューアイテムに実装していきましょう。

各メニューアイテムの機能に対応した TextBox コントロールのメソッドを記述していくだけですので簡単です。

この記事の項目 [メニューアイテムへのイベント ハンドラの設定] の内容を参考に、各メニューアイテムのイベントハンドラに以下のコードを記述してください。

//[編集(&E)]メニュー関連のイベントハンドラ
#region EditMenu handlers

        //[元に戻す]メニューの処理
        private void menuUndo_Click(object sender, EventArgs e)
        {
            if (textBox1.CanUndo) //元に戻すことが可能であれば
            {
                textBox1.Undo();
                textBox1.ClearUndo();
            }
        }

        //[切り取り]メニューの処理
        private void menuCut_Click(object sender, EventArgs e)
        {
            if (textBox1.SelectedText != "") textBox1.Cut();
        }

        //[コピー]メニューの処理
        private void menuCopy_Click(object sender, EventArgs e)
        {
            if (textBox1.SelectedText != "") textBox1.Copy();
        }

        //[貼り付け]メニューの処理
        private void menuPaste_Click(object sender, EventArgs e)
        {
     //クリップボードの内容がテキストで扱えるのであれば貼り付けを
            if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Text))
                      textBox1.Paste();
        }

        //[削除]メニューの処理
        private void menuDelete_Click(object sender, EventArgs e)
        {
            textBox1.Cut();
            Clipboard.Clear();
        }

        //[全て選択] メニューの処理
        private void menuAllSelect_Click(object sender, EventArgs e)
        {
            textBox1.SelectAll();
        }
#endregion 

コードの記述が終わったら [F5] キーを押下してプロジェクトを実行してみましょう。

テキストボックスに文字列を入力後、[編集(&E)] メニューの各機能が正常に動作するか試してみてください。

うまくいかない場合は、サンプルを用意しましたので以下のリンクからダウンロードしてお試しください。

[サンプルプロジェクトのダウンロード]

 

次回は検索機能の実装について書きたいと思いますが、UI の作成手順を書くのが大変なので、サンプルをダウンロードしていただいてコードの解説でもしようかと思ってます。

ではまた。

※マイクロソフト社員のコミュニティ参加について

※このエントリは ブロガーにより投稿されたものです。朝日インタラクティブ および ZDNet Japan編集部の見解・意向を示すものではありません。
  • 3件のコメント
#1   2009-02-19 16:46:11
基本の操作がわかりやすく身近な題材で学べます。
次の検索&置換も楽しみにしています。
#2 何それ?わざとか?   2012-01-28 22:33:38
イベントハンドラの開き方まで教えないとわからないでしょ?
わかる?
#3   2013-03-27 13:36:14
勉強になります