編集に関する情報を表示させます。具体的にはUndoとRedoが可能な回数、ビットマップの表示倍率と実際のサイズ、マウスの座標の位置、その場所の色、範囲選択がされている場合、その左上の座標と幅、高さなどです。
まずデザイナでステータスバーを追加します。
UndoRedoの可能回数を表示させる
はじめにUndoとRedoが可能な回数ですが、これはBitmapプロパティが変更されるときです。そこで以下のようにします。
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 |
public partial class UserControlImage : UserControl { public event EventHandler BitmapChanged; Bitmap _bitmap = null; public Bitmap Bitmap { get { return _bitmap; } set { linePoints = null; if(_bitmap != value && _bitmap != null) { if(IsNewBitmap(_bitmap, value)) { // Undoバッファを追加 UndoBufs.InsertUndoBuf(new UndoBuf(_bitmap, DragDropRectangle)); UndoBufs.ClearRedoBufs(); } } _bitmap = value; pictureBox1.Invalidate(); // イベントを発生させる BitmapChanged?.Invoke(this, new EventArgs()); } } } |
それからUndoとRedoの処理はBitmapプロパティをつかわず別の方法でおこなっています。そこでUndo()とRedo()のなかでもイベントを発生させる必要があります。またUndoバッファがクリアされるときもイベントを発生させています。
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
public partial class UserControlImage : UserControl { public void Undo() { if(BitmapRectangle != null) { ClearBitmapRectangle(); pictureBox1.Invalidate(); return; } if(UndoBufs.CanUndo()) { if(_bitmap != null) UndoBufs.InsertRedoBuf(new UndoBuf(_bitmap, DragDropRectangle)); UndoBuf undoBuf = UndoBufs.RemoveUndoBuf(); _bitmap = undoBuf.Bitmap; startPoint = new Point(-1, -1); endPoint = new Point(-1, -1); if(_bitmap != null) { OptimizationScrloolBar(Bitmap); pictureBox1.Invalidate(); } BitmapChanged?.Invoke(this, new EventArgs()); } } public void Redo() { if(BitmapRectangle != null) { ClearBitmapRectangle(); pictureBox1.Invalidate(); return; } if(UndoBufs.CanRedo()) { UndoBufs.InsertUndoBuf(new UndoBuf(_bitmap, DragDropRectangle)); UndoBuf redoBuf = UndoBufs.RemoveRedoBuf(); _bitmap = redoBuf.Bitmap; startPoint = new Point(-1, -1); endPoint = new Point(-1, -1); if(_bitmap != null) { OptimizationScrloolBar(Bitmap); pictureBox1.Invalidate(); } BitmapChanged?.Invoke(this, new EventArgs()); } } public void ClearUndoBufs() { UndoBufs.ClearUndoBufs(); BitmapChanged?.Invoke(this, new EventArgs()); } } |
そしてイベントが発生したらUndoバッファを表示させます。イベントハンドラはUserControlImage1_BitmapChangedとします。これでUndoバッファに関する情報と編集中のビットマップに関する情報がステータスバーに表示されます。
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 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); UndoRedoStatusLabel.Text = ""; BitmapSizeStatusLabel.Text = ""; MousePositionStatusLabel.Text = ""; MousePositionColorStatusLabel.Text = ""; userControlImage1.BitmapChanged += UserControlImage1_BitmapChanged; } private void UserControlImage1_BitmapChanged(object sender, EventArgs e) { ShowBitmapInfo(); } void ShowBitmapInfo() { int undoCount = userControlImage1.UndoBufCount; int redoCount = userControlImage1.RedoBufCount; if(userControlImage1.Bitmap != null) { UndoRedoStatusLabel.Text = String.Format("Undo ={0} Redo={1}", undoCount, redoCount); BitmapSizeStatusLabel.Text = String.Format("{0} × {1} ({2}倍)", userControlImage1.Bitmap.Width, userControlImage1.Bitmap.Height, userControlImage1.DisplayMagnification); } } } |
それから表示倍率もいっしょに表示させていますが、これがかわるのはメニューを選択したときです。そこでそのときもShowBitmapInfo()メソッドを呼び出します。
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 |
public partial class Form1 : Form { private void Show100MenuItem_Click(object sender, EventArgs e) { userControlImage1.DisplayMagnification = 1.0F; ShowBitmapInfo(); } private void Show75MenuItem_Click(object sender, EventArgs e) { userControlImage1.DisplayMagnification = 0.75F; ShowBitmapInfo(); } private void Show50MenuItem_Click(object sender, EventArgs e) { userControlImage1.DisplayMagnification = 0.5F; ShowBitmapInfo(); } private void Show150MenuItem_Click(object sender, EventArgs e) { userControlImage1.DisplayMagnification = 1.5F; ShowBitmapInfo(); } private void Show200MenuItem_Click(object sender, EventArgs e) { userControlImage1.DisplayMagnification = 2.0F; ShowBitmapInfo(); } private void Show300MenuItem_Click(object sender, EventArgs e) { userControlImage1.DisplayMagnification = 3.0F; ShowBitmapInfo(); } } |
マウスポインタの座標と対応する色を表示させる
つぎにマウスポインタがある位置の座標と色を表示する方法ですが、まずピクチャーボックスの上でマウスが移動したときのイベントを作成します。イベントハンドラの引数はマウスの位置に相当する点の座標です。PictureBox1_MouseMoveメソッド内でイベントハンドラの引数は取得できます。
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 |
public partial class UserControlImage : UserControl { public class PictureBoxMouseMoveEventArgs : EventArgs { public PictureBoxMouseMoveEventArgs(int x, int y) { X = x; Y = y; } public int X { get; protected set; } public int Y { get; protected set; } } public delegate void PictureBoxMouseMoveHandler(object sender, PictureBoxMouseMoveEventArgs e); public event PictureBoxMouseMoveHandler PictureBoxMouseMove; private void PictureBox1_MouseMove(object sender, MouseEventArgs e) { if(Bitmap == null) return; int x = (int)(e.X / DisplayMagnification); int y = (int)(e.Y / DisplayMagnification); PictureBoxMouseMove?.Invoke(this, new PictureBoxMouseMoveEventArgs(x + ScrollBarPosX, y + ScrollBarPosY)); // 以下省略(これまでと同じ) } } |
点の座標からその場所の色を求めるメソッドも作成します。ビットマップ内であれば色を調べてそれを返します。ビットマップの外であればColor.Emptyを返します。また範囲選択されているときは白または透明を返します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class UserControlImage : UserControl { public Color GetColorFromPoint(int x, int y) { if(blankBitmap != null) { int minX = blankBitmap.Rectangle.Left; int minY = blankBitmap.Rectangle.Top; if(blankBitmap.Rectangle.Left <= x && x < blankBitmap.Rectangle.Right && blankBitmap.Rectangle.Top <= y && y < blankBitmap.Rectangle.Bottom) return blankBitmap.Bitmap.GetPixel(x - minX, y - minY); } if(x < Bitmap.Width && y < Bitmap.Height) return Bitmap.GetPixel(x, y); else return Color.Empty; } } |
自作したイベントPictureBoxMouseMoveを捕捉して処理をおこないます。座標と色を調べてこれをMousePositionStatusLabelとMousePositionColorStatusLabelに表示させます。
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 42 43 44 45 46 47 48 49 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); userControlImage1.PictureBoxMouseMove += UserControlImage1_PictureBoxMouseMove; } private void UserControlImage1_PictureBoxMouseMove(object sender, UserControlImage.PictureBoxMouseMoveEventArgs e) { ShowPointInfo(e.X, e.Y); } void ShowPointInfo(int x, int y) { Bitmap bitmap = userControlImage1.Bitmap; if(bitmap != null && userControlImage1.BitmapRectangle != null) { // 範囲選択されているときは選択範囲の座標、幅、高さを表示する BitmapRectangle rect = userControlImage1.BitmapRectangle; MousePositionStatusLabel.Text = String.Format("( {0}, {1}) ( {2}, {3})", rect.X, rect.Y, rect.Width, rect.Height); // BackColorを反映させるためにはなにかをTextに設定する必要がある MousePositionColorStatusLabel.Text = " "; // 範囲選択されているときは左上の座標の色を表示する if(0 <= rect.X && rect.X < userControlImage1.Bitmap.Width && 0 <= rect.Y && rect.Y < userControlImage1.Bitmap.Height) MousePositionColorStatusLabel.BackColor = userControlImage1.GetColorFromPoint(rect.X, rect.Y); else MousePositionColorStatusLabel.BackColor = Color.Empty; } else if(bitmap != null && x < userControlImage1.Bitmap.Width && y < userControlImage1.Bitmap.Height) { // 範囲選択されていないときはマウスポインタの位置を表示する MousePositionStatusLabel.Text = String.Format("( {0}, {1})", x, y); MousePositionColorStatusLabel.Text = " "; MousePositionColorStatusLabel.BackColor = userControlImage1.GetColorFromPoint(x, y); } else { // マウスポインタの位置がビットマップの外であるなら「-」を表示する MousePositionStatusLabel.Text = "-"; MousePositionColorStatusLabel.Text = " "; MousePositionColorStatusLabel.BackColor = Color.Empty; } } } |
それから方向キーがおされたときも選択されている部分が移動するので、このときも選択部分の座標を表示させます。
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 42 |
public partial class Form1 : Form { protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if(keyData == Keys.Escape) { userControlImage1.ClearBitmapRectangle(true); return true; } if(keyData == Keys.Up) { userControlImage1.OnKeyDownUp(); if(userControlImage1.BitmapRectangle != null) ShowPointInfo(userControlImage1.BitmapRectangle.X, userControlImage1.BitmapRectangle.Y); return true; } if(keyData == Keys.Down) { userControlImage1.OnKeyDownDown(); if(userControlImage1.BitmapRectangle != null) ShowPointInfo(userControlImage1.BitmapRectangle.X, userControlImage1.BitmapRectangle.Y); return true; } if(keyData == Keys.Right) { userControlImage1.OnKeyDownRight(); if(userControlImage1.BitmapRectangle != null) ShowPointInfo(userControlImage1.BitmapRectangle.X, userControlImage1.BitmapRectangle.Y); return true; } if(keyData == Keys.Left) { userControlImage1.OnKeyDownLeft(); if(userControlImage1.BitmapRectangle != null) ShowPointInfo(userControlImage1.BitmapRectangle.X, userControlImage1.BitmapRectangle.Y); return true; } } } |