Bitmap上に4角形のオブジェクトを配置するマップエディタを作成しているのですが、
配置したオブジェクトの大きさや座標をNumericUpDownで連続で変更すると例外が発生します。
再描画の度にBitmapを新規作成していることが原因のようなので、
Bitmapを新規作成しないor描画間隔を少なくする といった方法は思いつくのですが、
どうすれば実装できるかがわかりません。どなたかアドバイスをお願いいたします。
例外が起こるのはCanvasクラスのdraw関数です。
class Canvas
{
/** 四角形オブジェクトリスト */
private List<RectangleObject> recList = null;
private Bitmap orgCanvas = null;
private Brush brushColor
= new SolidBrush(
Color.FromArgb( Byte.MaxValue / 2 ,Color.White)
);
private bool selectFlag = false;
private int selectElem = 0;
private Canvas()
{
}
public Canvas(PictureBox parentBox)
{
orgCanvas = new Bitmap(parentBox.Width, parentBox.Height );
recList = new List<RectangleObject>();
}
/** クリック判定 */
public void clickDecision(Point p)
{
int elemNum = recList.FindIndex(
delegate (RectangleObject rec)
{
return rec.clickDecision(p);
});
selectFlag = (elemNum != -1);
selectElem = elemNum;
}
public void addRectangle( int id, Point point, Size size ,float angle = 0.0f)
{
selectFlag = true;
selectElem = recList.Count;
recList.Add( new RectangleObject( id,point,size,angle ) );
}
public void reposition( Point p )
{
if(selectFlag)
{
recList[selectElem].setPoint(p);
}
}
public void resize(Size s)
{
if (selectFlag)
{
recList[selectElem].setSize(s);
}
}
public void reangle(float angle)
{
if (selectFlag)
{
recList[selectElem].setAngle(angle);
}
}
/** 問題箇所、コントロールで値が変更される度にこの処理が呼ばれ再描画される */
public void draw( PictureBox pictureBox )
{
/** bitmap新規作成時にArgumentException */
Bitmap canvas = new Bitmap(this.orgCanvas.Width, this.orgCanvas.Height);
for (int i = 0; i < recList.Count; i++)
{
Pen FrameColor;
bool isSelect = selectFlag;
/** 選択中のオブジェクトはオレンジで描画 */
isSelect &= ( selectElem == i );
if ( isSelect ) {
FrameColor = Pens.Orange;
} else
{
FrameColor = Pens.Black;
}
recList[i].draw(FrameColor,brushColor,canvas);
}
pictureBox.Image = canvas;
}
}
class RectangleObject
{
/** 中心座標 */
private Point centerP;
/** 識別id */
private int id;
/** 四角形 */
private Rectangle rect;
private Graphics graphics = null;
/** 判定 */
private const int radius = 10;
private Size dicisionSize = new Size(radius, radius);
private Rectangle dicisionRect;
private float angle;
private RectangleObject()
{
}
public RectangleObject( int objectId, Point point,Size size,float objectAngle = 0.0f)
{
id = objectId;
centerP = point;
angle = objectAngle;
rect = createRect(point, size);
dicisionRect = createRect(point, dicisionSize);
}
/** クリック判定 */
public bool clickDecision(Point p)
{
double diffX = (double)( centerP.X - p.X );
double diffY = (double)( centerP.Y - p.Y );
double distance = Math.Sqrt( Math.Pow(diffX, 2.0) + Math.Pow(diffY, 2.0));
return distance < ( radius / 2.0 );
}
public void setSize( Size size )
{
rect = createRect(centerP, size);
dicisionRect = createRect(centerP, dicisionSize);
}
public void setAngle(float objectAngle)
{
angle = objectAngle;
}
public void setPoint( Point point )
{
centerP = point;
Point rectP = culcUpperLeftPoint(centerP, rect.Size);
rect.X = rectP.X;
rect.Y = rectP.Y;
Point dicP = culcUpperLeftPoint(centerP, dicisionRect.Size);
dicisionRect.X = dicP.X;
dicisionRect.Y = dicP.Y;
}
/** 描画 */
public void draw(Pen frameColor,Brush fillColor,Bitmap canvas)
{
graphics = RotateGraphics(canvas, angle);
graphics.FillRectangle(fillColor, rect);
graphics.DrawRectangle(frameColor, rect);
graphics.DrawEllipse(frameColor, dicisionRect);
}
private Graphics RotateGraphics(Bitmap canvas, float angle)
{
Graphics g = Graphics.FromImage(canvas);
int x = centerP.X; int y = centerP.Y;
g.TranslateTransform(-x, -y);
g.RotateTransform(angle, System.Drawing.Drawing2D.MatrixOrder.Append);
g.TranslateTransform(x, y, System.Drawing.Drawing2D.MatrixOrder.Append);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
return g;
}
private Rectangle createRect(Point point, Size size)
{
Size s = new Size(size.Width * 2, size.Height * 2);
Rectangle r = new Rectangle( culcUpperLeftPoint(centerP,s), s );
return r;
}
private Point culcUpperLeftPoint( Point center , Size size )
{
Point point = new Point(center.X, center.Y);
point.X -= size.Width / 2;
point.Y -= size.Height / 2;
return point;
}
}