これまで作成してきたイメージエディタは大きなサイズの画像を編集しようとすると動作が遅いです。

たとえば範囲選択されている部分をドラッグで移動させる処理はこのようになっています。Bitmapのコピーを作成してそこに移動中のデータを書き込み、これをPictureBox.Imageにセットする、このような処理をマウスが動くたびに繰り返すわけですから遅くなるのは当然です。

そこでPaintイベントを利用して処理を高速化することを考えます。

まずはPaintイベントを捕捉したときの処理です。

これまでビットマップをピクチャーボックス上に表示するために使ってきたShowBitmap(Bitmap bitmap)メソッドはInvalidatePictureBoxメソッドを呼ぶためだけに変更しました。

フィールド変数linePointsに格納されたデータが必要なのでOnMouseUpForSelectFreeAreaメソッドのなかでクリアするのはやめることにします。Bitmapプロパティが変更されたときには明らかに不要になっているので、ここでクリアします。

では各メソッドについてそれぞれみていきましょう。

DrawBoderRectangleメソッドは選択されている部分の境界線を描画するメソッドです。引数がGraphicsになっているだけでやっていることはほとんど同じです。startPoint, endPointの2点から矩形を取得して描画しています。ビットマップに描画するのではなくピクチャーボックスの上に描画しています。

DrawFreeLineメソッドはstartPoint, endPointの2点から直線を描画するメソッドです。

DrawFreeLineメソッドは記憶された点のリストから自由曲線を描画します。

DrawRectangleメソッドは矩形と楕円の描画(枠だけ、ぬりつぶしの両方)をするためのメソッドです。

最後にビットマップを描画するメソッドを示します。スクロールバー位置よりビットマップをトリミングして表示します。また選択されている部分の移動先が確定するまえは移動元の画像があった部分は空白で表示するのですが、自由曲線で囲まれた部分はSetPixelメソッドで処理をしていました。これでは時間がかかりすぎるのでBitmapReatangle型に変換して、Graphics.DrawImageメソッドで処理ができるようにしてます。

DrawFieldGripメソッドはフィールドのサイズ変更のためのグリッパーを描画するためのものです。

つぎに呼び出し側ですが、ビットマップ上に描画するのをやめてPictureBox.Invalidateメソッドを呼び出して上記の処理をおこなわせています。

それから文字を挿入する処理も修正しました。ただし[範囲選択(矩形)]が選択されていないと移動させることができません。そこで文字を挿入したら自動的に[範囲選択(矩形)]が選択されるようにしました。

編集モードにあわせてメニューにチェックをいれるメソッドです。メニューがドロップダウンされたときに編集モードを調べてメニューにチェックマークをつけます。

ところでPictureBox.Invalidateメソッドを引数なしで呼び出すとビットマップの範囲外であっても矩形が描画されてしまいます。もちろん描画されるだけで実際に移動できるわけではありません。そこで引数つきでPictureBox.Invalidateメソッドを呼び出しています。これならビットマップの範囲外には描画されません。

スクロールバーがクリックされたときもVScrollBar1_ScrollメソッドやHScrollBar1_Scroll内で特別な処理はしないで、PictureBox.Invalidateメソッドを呼び出して適切な描画をさせることにしました。

UndoとRedoに関する処理です。BitmapRectangle == nullでないときはこれを一体化させ、そうでないときはUndo、Redoの処理をしています。BitmapRectangleをクリアしたときとBitmapプロパティが変化したときはPictureBox.Invalidate()メソッドでこれをピクチャーボックスに描画させています。