それとStackにTransformの状態を積むことにより、状態を復元できるようにする。

とりあえず試しに時計でも作ってみた。もっとも普通の見やすい時計って文字は正立だし、矢印だって三角関数とか使えば良いのであんまりTransformのメリットは無いけど。
TranslateTransformで移動、ScaleTransformでスケーリング、RotateTransformで回転、ResetTransformで初期化、という感じ。あとは任意の位置でTransformをStackに詰めばその場所を復元することができる。うまく使わないと頭がごちゃごちゃするので注意すること。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace GraphicsStack
{
public partial class Form1 : Form
{
Bitmap bmp;
Graphics gra;
DateTime NowDate { get { return (DateTime.Now); } }
//DateTime NowDate { get { return (new DateTime(2016, 5, 6, 10, 8, 37, 0)); } }
public Form1()
{
InitializeComponent();
bmp = new Bitmap(512, 512);
gra = Graphics.FromImage(bmp);
MaximumSize = MinimumSize = Size = Size + bmp.Size - pictureBox1.Size;
pictureBox1.Image = bmp;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
gra.ResetTransform();
DateTime now = NowDate;
using (StringFormat center = new StringFormat(StringFormat.GenericTypographic))
using (Font font1 = new Font(DefaultFont.Name, 25))
using (Font font2 = new Font(DefaultFont.Name, 18))
using (Pen pen1 = new Pen(Color.Gray, 3))
using (Pen pen2 = new Pen(Color.Black, 8))
using (Pen pen3 = new Pen(Color.Red, 5))
{
center.Alignment = center.LineAlignment = StringAlignment.Center;
pen2.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
Stack<System.Drawing.Drawing2D.Matrix> Stack = new Stack<System.Drawing.Drawing2D.Matrix>();
Stack.Push(gra.Transform);
gra.Clear(Color.LightGray);
gra.TranslateTransform(256, 256);
Stack.Push(gra.Transform);
for (int i = 0; i < 60; i++)
{
gra.RotateTransform(360 / 60);
gra.DrawLine(pen1, 0, -230, 0, -240);
}
for (int i = 1; i <= 12; i++)
{
gra.RotateTransform(360 / 12);
gra.DrawLine(pen1, 0, -210, 0, -240);
gra.DrawString(i.ToString(), font1, pen1.Brush, 0, -190, center);
gra.DrawLine(pen1, -15, -170, 15, -170);
}
gra.Transform = Stack.Pop();
Stack.Push(gra.Transform);
gra.TranslateTransform(120, 0);
gra.DrawRectangle(Pens.Black, -45, -15, 90, 30);
gra.DrawString(
now.DayOfWeek.ToString().Substring(0, 3).ToUpper() +
now.Day.ToString(" 00"),
font2, pen1.Brush, 0, 0, center);
gra.Transform = Stack.Pop();
#region 針 float hour = now.Hour * 30 + now.Minute * 0.5f;
float minute = now.Minute * 6;
float second = now.Second * 6;
float subsec = now.Millisecond / (1000 / 360f);
Stack.Push(gra.Transform);
gra.RotateTransform(hour);
gra.DrawLine(pen2, 0, 50, 0, -150);
gra.Transform = Stack.Pop();
Stack.Push(gra.Transform);
gra.RotateTransform(minute);
gra.DrawLine(pen2, 0, 100, 0, -210);
gra.Transform = Stack.Pop();
Stack.Push(gra.Transform);
gra.RotateTransform(second);
gra.DrawLine(pen3, 0, 50, 0, -150);
gra.FillEllipse(pen3.Brush, -10, -10, 20, 20);
gra.Transform = Stack.Pop();
Stack.Push(gra.Transform);
gra.TranslateTransform(90, 90);
gra.RotateTransform(subsec);
gra.DrawLine(pen3, 0, 10, 0, -30);
gra.FillEllipse(pen3.Brush, -10, -10, 20, 20);
gra.Transform = Stack.Pop();
#endregion
gra.Transform = Stack.Pop();
#if DEBUG
if (Stack.Count != 0) { throw new Exception("Stackが異常です"); }
#endif
}
pictureBox1.Refresh();
}
}
}
float hour = now.Hour * 30 + now.Minute * 0.5f;
float minute = now.Minute * 6;
float second = now.Second * 6;
float subsec = now.Millisecond / (1000 / 360f);
Stack.Push(gra.Transform);
gra.RotateTransform(hour);
gra.DrawLine(pen2, 0, 50, 0, -150);
gra.Transform = Stack.Pop();
Stack.Push(gra.Transform);
gra.RotateTransform(minute);
gra.DrawLine(pen2, 0, 100, 0, -210);
gra.Transform = Stack.Pop();
Stack.Push(gra.Transform);
gra.RotateTransform(second);
gra.DrawLine(pen3, 0, 50, 0, -150);
gra.FillEllipse(pen3.Brush, -10, -10, 20, 20);
gra.Transform = Stack.Pop();
Stack.Push(gra.Transform);
gra.TranslateTransform(90, 90);
gra.RotateTransform(subsec);
gra.DrawLine(pen3, 0, 10, 0, -30);
gra.FillEllipse(pen3.Brush, -10, -10, 20, 20);
gra.Transform = Stack.Pop();
#endregion
gra.Transform = Stack.Pop();
#if DEBUG
if (Stack.Count != 0) { throw new Exception("Stackが異常です"); }
#endif
}
pictureBox1.Refresh();
}
}
}
0 件のコメント:
コメントを投稿