文字を描画する C#で簡易画像編集ソフトをつくる(その10)

では画像のなかに文字をいれることができるようになりましたが、文字の位置を変えることができません。そこで文字の位置を変更できるようにします。

選択範囲を移動させるためのBitmapRectangleプロパティ

そのためには領域が選択されている状態でドラッグするとその部分を移動できるようにすることが必要です。これまでBitmapRectangleプロパティを使ってきましたが、これは描画したものを移動させるためにつくられたものです。

移動しているものを再度固定させるのは範囲選択されている部分以外の部分がクリックされたときです。Windowsに標準搭載されているPaintも追加された矩形、楕円、文字などをドラッグすれば移動させることができ、それ以外の部分をクリックすると固定されます。

BitmapRectangleクラスにプロパティを追加する

そこでBitmapRectangleクラスにプロパティを追加します。これで移動させることができるようになります。

選択範囲の移動開始がおこなわれる条件とは?

UserControlImageがクリックされたらBitmapRectangleプロパティを調べます。もしnullであれば移動可能なものは存在しないということになります。

もしBitmapRectangle != nullであるならクリックされたのは矩形の内部かどうか調べます。矩形の内部であればドラッグによる移動がはじまると判断して、現在の矩形の位置とマウスクリックされた場所を調べます。ドラッグされている最中とこれが終わったときにマウス座標とクリックされた位置を比較すればどれだけ移動したのかがわかります。

イベントハンドラPictureBox1_MouseDownの修正

以下はこの処理に必要なフィールド変数と機能が追加されたイベントハンドラPictureBox1_MouseDownです。最後のほうにあるIsPointInRectangleメソッドはクリックされた場所が範囲選択されている部分なのかどうかを判定するものです。そして範囲選択されている部分がクリックされたときはOnMouseDownInBitmapRectangleメソッドを、範囲選択されていない部分であれば OnMouseDownOutOfSelectionメソッドを呼びます。

IsPointInRectangleメソッドは以下のようになっています。

移動の開始を知る

OnMouseDownInBitmapRectangleメソッドはOnMouseDownForMoveSelectionメソッドを呼び出します。

OnMouseDownForMoveSelectionメソッドは移動のためにマウスボタンが押されていることを示すisMouseDownForMoveフラグをセットして現在のBitmapRectangleの位置とクリックされた座標(ビットマップ上の座標)をフィールド変数に保存します。

移動元を白抜きにする

これは範囲選択するためのドラッグが終了したときに呼ばれるOnMouseUpForSelectRectangleメソッドですが、最後にCreateBlankBitmapメソッドを呼んでいます。

これは空白部分を挿入するためのものです。こうすることで移動している部分が元の位置から外れて移動しているようにみせかけることができます。

CreateBlankBitmapメソッドを示します。透明の部分は透明にして、それ以外の部分は白にしています。

イベントハンドラPictureBox1_MouseMoveの修正

PictureBox1_MouseMoveメソッドはマウスがピクチャーボックスの上を移動したときに呼び出されるイベントハンドラです。ここに選択されている部分を移動させるための機能を追加しました。(OnMouseMoveForMoveSelectionメソッド)

それからドラッグされているときだけでなくマウスが通過しているだけでも処理をしています。範囲選択されている部分の上を通過するときはカーソルの形が変わります。ChangeCursorWhenMouseMoveOnSelectionメソッドはそのためのものです。

移動可能であればマウスポインタの形状を変更する

ChangeCursorWhenMouseMoveOnSelectionメソッドは以下のようになっています。BitmapRectangleプロパティがnullでないことを確認してからIsPointInRectangleメソッドをつかってマウスポインタの位置がBitmapRectangle.Rectangleの内部かどうかを調べています。

ドラッグされ選択範囲を移動させるOnMouseMoveForMoveSelectionメソッド

一方、ドラッグされているとき(= isMouseDownForMoveフラグがセットされているとき)に呼び出されるOnMouseMoveForMoveSelectionメソッドは以下のようになっています。

マウス座標がビットマップ上であればどこに対応するかを求めて、これとクリック時に保存しておいたフィールド変数rectangleMoveStartMousePosX、rectangleMoveStartMousePosYと比較してどれだけ移動したかを調べています。そしてBitmapのコピーとBitmapRectangle.Bitmapを適切な位置で合成します。

こうすることで選択領域が移動しているように見せかけています。

ドラッグによる移動が終了したときに呼び出されるOnMouseUpForMoveSelectionメソッド

最後にドラッグが終了したときの処理を示します。

移動のためのドラッグが終わるときはOnMouseUpForMoveSelectionメソッドが呼ばれます。

OnMouseUpForDrawRectangleメソッドはBitmapRectangleオブジェクト上に矩形や楕円を描画します。このときは位置は確定されていません。そのためドラッグ&ドロップで移動させることができます。

OnMouseUpForMoveSelectionメソッドはisMouseDownForMoveフラグをクリアしてBitmapRectangle.UpdatePositionメソッドを呼びます。

移動が終わったとしてもそこからさらにもう一度移動される可能性があります。そのときは移動先の位置が新たな移動元になります。そこで座標やサイズを保存しなおしているのです。

選択部分の移動が確定するときとは?

本当にBitmapプロパティが更新されるのは範囲選択が解除されたときです。UniteBitmapRectangleメソッドはBitmapプロパティとBitmapRectangleプロパティを完全に統合させるものです。これによって移動した選択範囲の位置が確定します。

使われなくなったBitmapRectangleとblankBitmapはDisposeされ、そのなかに格納されていたビットマップデータもDisposeされます。