前回までスクロールバー付きのピクチャーボックスを作成して改造してきました。今回はこれを使った簡単なアプリをつくります。
どんなアプリかというと、左側のスクロールバー付きのピクチャーボックス(ScrollPictureBox)に画像ファイルをドラッグアンドドロップすると画像が表示されます。左側のピクチャーボックスをドラッグアンドドロップすると矩形が表示され、その部分が右側に送られます。
右側のスクロールバー付きのピクチャーボックスに画像が表示されるとトリミングで上下左右の切り捨てられた部分の長さとトリミングで得られた画像の幅、高さが表示されます。またトリミングできる部分はアップダウンコントロールでも設定できます。アップダウンコントロールの値がユーザーによって変更されるとトリミングされた画像が表示されます。
・・・というサンプルアプリ以上の何物でもないシンプルなアプリです。


左の黒枠部分がトリミングされています。また左と右では拡大率を変えていますが、うまくトリミングできていることがわかります。
最初にコンストラクタのなかで、イベントハンドラの設定と各コントロールに適切な値をいれます。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public partial class Form1 : Form {     public Form1()     {         InitializeComponent();         NumericUpDownLeft.ValueChanged += NumericUpDownLeft_ValueChanged;         NumericUpDownRight.ValueChanged += NumericUpDownRight_ValueChanged;         NumericUpDownLeft.Maximum = 1000;         NumericUpDownLeft.Minimum = 10;         NumericUpDownLeft.Value = 100;         NumericUpDownRight.Maximum = 1000;         NumericUpDownRight.Minimum = 10;         NumericUpDownRight.Value = 100;         NumericUpDownMarginTop.ValueChanged += NumericUpDownMarginTop_ValueChanged;         NumericUpDownMarginBottom.ValueChanged += NumericUpDownMarginBottom_ValueChanged;         NumericUpDownMarginLeft.ValueChanged += NumericUpDownMarginLeft_ValueChanged;         NumericUpDownMarginRight.ValueChanged += NumericUpDownMarginRight_ValueChanged;         ScrollPictureBoxLeft.DragOver += ScrollPictureBoxLeft_DragOver;         ScrollPictureBoxLeft.DragDrop += ScrollPictureBoxLeft_DragDrop;         // 左側のピクチャーボックスはドラッグして選択範囲を指定するとトリミング処理ができる         // 右側のピクチャーボックスはドラッグして選択範囲を指定できる機能は使わない         ScrollPictureBoxLeft.FinishedDragRectangle += ScrollPictureBoxLeft_FinishedDragRectangle;         ScrollPictureBoxRight.DoesDrawDragedRectangle = false;         ScrollPictureBoxLeft.FullScaleBitmapChanged += ScrollPictureBoxLeft_FullScaleBitmapChanged;         ScrollPictureBoxRight.FullScaleBitmapChanged += ScrollPictureBoxRight_FullScaleBitmapChanged;     } } | 
それでは最初に画像ファイルがドラッグアンドドロップされたら左のスクロールバー付きのピクチャーボックスに画像を表示させる処理を示します。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public partial class Form1 : Form {     private void ScrollPictureBoxLeft_DragOver(object sender, DragEventArgs e)     {         if(e.Data.GetDataPresent(DataFormats.FileDrop))             e.Effect = DragDropEffects.Copy;         else             e.Effect = DragDropEffects.None;     }     private void ScrollPictureBoxLeft_DragDrop(object sender, DragEventArgs e)     {         if (e.Data.GetDataPresent(DataFormats.FileDrop))         {             string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);             try             {                 Bitmap bitmap = new Bitmap(files[0]);                 ScrollPictureBoxLeft.FullScaleBitmap = new Bitmap(bitmap);                 bitmap.Dispose();             }             catch             {             }         }     } } | 
次に左側のスクロールバー付きのピクチャーボックス上でドラッグによって選択範囲が確定したときの処理を追加します。
ここではトリミングされた画像を右側のスクロールバー付きピクチャーボックスに表示させます。このときに元の画像から切り落とされた上下左右の長さも表示させます。あとコンストラクタのなかでFullScaleBitmapChangedイベントに対応できるようにしているので、別のイベントハンドラによって画像のサイズも表示されます。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public partial class Form1 : Form {     private void ScrollPictureBoxLeft_FinishedDragRectangle(object sender, TrimmedBitmapArgs e)     {         if (e.Bitmap == null)             return;         if (ScrollPictureBoxRight.FullScaleBitmap != null)             ScrollPictureBoxRight.FullScaleBitmap.Dispose();         ScrollPictureBoxRight.FullScaleBitmap = e.Bitmap;         SetNumericUpDownValue(NumericUpDownMarginTop, e.MarginTop);         SetNumericUpDownValue(NumericUpDownMarginBottom, e.MarginBottom);         SetNumericUpDownValue(NumericUpDownMarginLeft, e.MarginLeft);         SetNumericUpDownValue(NumericUpDownMarginRight, e.MarginRight);     } } | 
上記の処理でSetNumericUpDownValue(NumericUpDown num, int value)という自作メソッドを呼び出しています。アップダウンコントロールには上限下限の値があり、これを超える値がセットされると例外が発生します。以下でそうならないための処理をしています。
| 1 2 3 4 5 6 7 8 9 10 | public partial class Form1 : Form {     void SetNumericUpDownValue(NumericUpDown num, int value)     { 	    // NumericUpDown.Maximumを超える値がセットされそうになったらNumericUpDown.Maximumを変更する         if (num.Maximum < value)             num.Maximum = value;         num.Value = value;     } } | 
GetNumericUpDownValue(NumericUpDown num)メソッドはNumericUpDown.Valueで得られた値をint型にキャストするのが面倒くさい、ただそれだけでつくられたメソッドです。
| 1 2 3 4 5 6 7 | public partial class Form1 : Form {     int GetNumericUpDownValue(NumericUpDown num)     {          return (int)num.Value;     } } | 
左右のスクロールバー付きのピクチャーボックスの下にある表示倍率を示すアップダウンコントロールの値が変更されたときに対応するためのものです。ScrollPictureBox.Expansionrateプロパティを変更しているだけです。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public partial class Form1 : Form {     private void NumericUpDownLeft_ValueChanged(object sender, EventArgs e)     {         double value = (double)NumericUpDownLeft.Value;         double expansionrate = value / 100;         ScrollPictureBoxLeft.Expansionrate = expansionrate;     }     private void NumericUpDownRight_ValueChanged(object sender, EventArgs e)     {         double value = (double)NumericUpDownRight.Value;         double expansionrate = value / 100;         ScrollPictureBoxRight.Expansionrate = expansionrate;     } } | 
トリミングに関するアップダウンコントロールの値は左側のピクチャーボックスをドラッグしたときだけでなく、ユーザー自身が変更することもできます。この場合はトリミングされたBitmapを求めたあと、これを右側のスクロールバー付きのピクチャーボックスに表示させます。
上下左右の4つのアップダウンコントロールがありますが、やることは全部同じなのでOnNumericUpDownMarginChange()メソッドを作成して、ここで処理をしています。
またユーザーによって変更されたのか、プログラムによって変更されたかはアップダウンコントロールがアクティブかどうかで区別できます。イベントハンドラ NumericUpDownMarginRight_ValueChanged(object sender, EventArgs e)などでは、アップダウンコントロールがアクティブである場合にのみ、OnNumericUpDownMarginChange()を呼び出しています。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | public partial class Form1 : Form {     void OnNumericUpDownMarginChange()     {         int left = GetNumericUpDownValue(NumericUpDownMarginLeft);         int right = GetNumericUpDownValue(NumericUpDownMarginRight);         int top = GetNumericUpDownValue(NumericUpDownMarginTop);         int bottom = GetNumericUpDownValue(NumericUpDownMarginBottom);         Bitmap bitmap = TrimmedBitmap.GetTrimmedBitmap(ScrollPictureBoxLeft.FullScaleBitmap, left, top, right, bottom);         if (ScrollPictureBoxRight.FullScaleBitmap != null)             ScrollPictureBoxRight.FullScaleBitmap.Dispose();         ScrollPictureBoxLeft.ClearRectangle();         ScrollPictureBoxRight.FullScaleBitmap = bitmap;     }     private void NumericUpDownMarginRight_ValueChanged(object sender, EventArgs e)     {         if (NumericUpDownMarginRight == this.ActiveControl)             OnNumericUpDownMarginChange();     }     private void NumericUpDownMarginLeft_ValueChanged(object sender, EventArgs e)     {         if (NumericUpDownMarginLeft == this.ActiveControl)             OnNumericUpDownMarginChange();     }     private void NumericUpDownMarginBottom_ValueChanged(object sender, EventArgs e)     {         if (NumericUpDownMarginBottom == this.ActiveControl)             OnNumericUpDownMarginChange();     }     private void NumericUpDownMarginTop_ValueChanged(object sender, EventArgs e)     {         if (NumericUpDownMarginTop == this.ActiveControl)             OnNumericUpDownMarginChange();     } } | 
最後に左右のスクロールバー付きのピクチャーボックスのFullScaleBitmapプロパティが変更されたら、変更されたサイズを表示しなければなりません。これはScrollPictureBox.FullScaleBitmapChangedイベントを処理すれば簡単にできます。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public partial class Form1 : Form {     private void ScrollPictureBoxLeft_FullScaleBitmapChanged(object sender, FullScaleBitmapChangedArgs e)     {         LabelSourceWidth.Text = "SourceWidth = " + e.Width.ToString();         LabelSourceHeight.Text = "SourceHeight = " + e.Height.ToString();     }     private void ScrollPictureBoxRight_FullScaleBitmapChanged(object sender, FullScaleBitmapChangedArgs e)     {         LabelDestWidth.Text = "DestWidth = " + e.Width.ToString();         LabelDestHeight.Text = "DestHeight = " + e.Height.ToString();     } } | 
