using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms;
public abstract class MyGraphicObject { /// <summary> /// Dieses Pen-Objekt wird verwendet um zu überprüfen, ob ein /// Punkt über der Linie des Objekts liegt. Die Farbe ist /// hierfür irrelevant. Als Breite hat sich 4 als sinnvoll erwiesen. /// </summary> static Pen HitTestPen = new Pen(Brushes.Black, 4); Pen _pen; bool _bVisible = true; GraphicsPath _path = new GraphicsPath();
public MyGraphicObject(Pen pen) { _pen = pen; }
protected GraphicsPath Path { get { return _path; } }
public Pen Pen { get { return _pen; } }
public bool Visible { get { return _bVisible; } set { _bVisible = value; } }
/// <summary> /// Befindet sich der angegebene Punkt über der Linie des Objekts? /// </summary> public virtual bool Hit(Point pt) { return _path.IsOutlineVisible(pt, HitTestPen); }
/// <summary> /// Befindet sich der angegebene Punkt innerhalb des Objekts? /// </summary> public virtual bool Contains(Point pt) { return _path.IsVisible(pt); }
public virtual void Draw(Graphics g) { g.DrawPath(_pen, _path); }
/// <summary> /// Bewegt das Objekt um deltaX in x-Richtung und deltaY in y-Richtung. /// </summary> public virtual void Move(int deltaX, int deltaY) { Matrix mat = new Matrix(); mat.Translate(deltaX, deltaY); _path.Transform(mat); } }
public class MyRectangle : MyGraphicObject { public MyRectangle(Pen pen, Rectangle rect) : base(pen) { Path.AddRectangle(rect); } }
public class MyCircle : MyGraphicObject { public MyCircle(Pen pen, Point center, int radius) : base(pen) { Path.AddEllipse(center.X - radius, center.Y - radius, 2 * radius, 2 * radius); } }
public class MyLine : MyGraphicObject { public MyLine(Pen pen, Point start, Point end) : base(pen) { Path.AddLine(start, end); } }
public class MyText : MyGraphicObject { public MyText(Pen pen, string text, FontFamily family, FontStyle style, float emSize, Point origin) : base(pen) { Path.AddString(text, family, (int)style, emSize, origin, null); }
public override void Draw(Graphics g) { g.FillPath(Pen.Brush, Path); }
public override bool Hit(Point pt) { return Contains(pt) || base.Hit(pt); } }
public class MainForm : Form { Button _btnAddRectangle; Button _btnAddCircle; Button _btnAddLine; Button _btnAddText; TextBox _txtText; Label _lblMouseLocation; List<MyGraphicObject> _graphicObjects = new List<MyGraphicObject>(); Rectangle _canvas; Random _random = new Random();
public MainForm() { InitializeComponent(); }
private void InitializeComponent() { _lblMouseLocation = new Label(); _btnAddCircle = new Button(); _btnAddLine = new Button(); _btnAddRectangle = new Button(); _btnAddText = new Button(); _txtText = new TextBox();
// Label, das die Maus-Position anzeigt _lblMouseLocation.AutoSize = true; _lblMouseLocation.Location = new Point(10, 195); _lblMouseLocation.Anchor = AnchorStyles.Left | AnchorStyles.Bottom;
// Button um einen zufälligen Kreis hinzuzufügen _btnAddCircle.Text = "Add Circle"; _btnAddCircle.Width = 100; _btnAddCircle.Location = new Point(10, 210); _btnAddCircle.Anchor = AnchorStyles.Left | AnchorStyles.Bottom; _btnAddCircle.Click += new EventHandler(AddCircle);
// Button um eine zufällige Linie hinzuzufügen _btnAddLine.Text = "Add Line"; _btnAddLine.Width = 100; _btnAddLine.Location = new Point(120, 210); _btnAddLine.Anchor = AnchorStyles.Left | AnchorStyles.Bottom; _btnAddLine.Click += new EventHandler(AddLine);
// Button um ein zufälliges Rechteck hinzuzufügen _btnAddRectangle.Text = "Add Rectangle"; _btnAddRectangle.Width = 100; _btnAddRectangle.Location = new Point(230, 210); _btnAddRectangle.Anchor = AnchorStyles.Left | AnchorStyles.Bottom; _btnAddRectangle.Click += new EventHandler(AddRectangle);
// Button um Text an einer zufälligen Position hinzuzufügen _btnAddText.Text = "Add Text"; _btnAddText.Width = 100; _btnAddText.Location = new Point(120, 235); _btnAddText.Anchor = AnchorStyles.Left | AnchorStyles.Bottom; _btnAddText.Click += new EventHandler(AddText);
// TextBox, in die man den text eingeben kann der durch _btnAddText hinzugefügt wird _txtText.Text = "Text"; _txtText.Width = 100; _txtText.Location = new Point(10, 237); _txtText.Anchor = AnchorStyles.Left | AnchorStyles.Bottom;
this.Controls.Add(_lblMouseLocation); this.Controls.Add(_btnAddCircle); this.Controls.Add(_btnAddLine); this.Controls.Add(_btnAddRectangle); this.Controls.Add(_btnAddText); this.Controls.Add(_txtText); this.Size = new Size(400, 320); // Damit geht das Neuzeichnen viel flüssiger this.DoubleBuffered = true; }
protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); e.Graphics.SmoothingMode = SmoothingMode.HighQuality; // Der Bereich, der neugezeichnet werden soll, wird auf die Zeichenfläche // beschränkt, damit Objekte, die darüber hinausschauen abgeschnitten werden. Region clip = new Region(_canvas); clip.Intersect(e.Graphics.Clip); e.Graphics.Clip = clip; e.Graphics.Clear(Color.White); foreach (MyGraphicObject go in _graphicObjects) { go.Draw(e.Graphics); } }
Point _lastMouseLocation; MyGraphicObject _movingGraphicObject;
protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); // Wenn die Maus außerhalb der Zeichenfläche gedrückt wurde, wird abgebrochen. if (!_canvas.Contains(e.Location)) return; // Anderenfalls wird die Liste mit den gezeichneten Objekten von hinten (damit // das oberste Objekte gefunden wird) durchgegangen und geprüft, über welchem // Objekt die Maus sich befindet. for (int i = _graphicObjects.Count - 1; i >= 0; i--) { MyGraphicObject go = _graphicObjects[i]; if (go.Hit(e.Location)) { _movingGraphicObject = go; break; } } _lastMouseLocation = e.Location; }
protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (_movingGraphicObject != null) { // Wenn gerade ein Objekt verschoben werden soll, wird die Differenz zur letzten // Mausposition ausgerechnet und das Objekt um diese verschoben. _movingGraphicObject.Move(e.X - _lastMouseLocation.X, e.Y - _lastMouseLocation.Y); _lastMouseLocation = e.Location; // Hier könnte man noch optimieren, indem man immer nur den Bereich // neuzeichnet, in dem das Objekt bewegt wurde. this.Invalidate(); } if (_canvas.Contains(e.Location)) { _lblMouseLocation.Text = string.Format("x = {0}; y= {1}", e.X, e.Y); } }
protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); _movingGraphicObject = null; }
protected override void OnSizeChanged(EventArgs e) { base.OnSizeChanged(e); // Wenn sich die Größe des Fensters ändert, wird die Größe der Zeichenfläche angepasst. _canvas = new Rectangle(new Point(0, 0), new Size(this.ClientSize.Width, this.ClientSize.Height - 70)); this.Invalidate(); }
void AddCircle(object sender, EventArgs e) { // Erstellt einen Kreis mit zufälligen Werten für Mittelpunkt, Radius // (mindestens 10 Pixel) und Farbe, der komplett zu sehen ist. int x = _random.Next(0, _canvas.Width); int y = _random.Next(0, _canvas.Height); int radius = _random.Next(10, Math.Max(11, Math.Min(Math.Min(_canvas.Width - x, x), Math.Min(_canvas.Height - y, y)))); Pen p = new Pen(Color.FromArgb(_random.Next(0, 256), _random.Next(0, 256), _random.Next(0, 256)), 1); _graphicObjects.Add(new MyCircle(p, new Point(x, y), radius)); this.Invalidate(); }
void AddLine(object sender, EventArgs e) { // Erstellt eine Linie mit zufälligen Werten für Start-, Endpunkt und // Farbe, die komplett zu sehen ist. int x1 = _random.Next(0, _canvas.Width); int x2 = _random.Next(0, _canvas.Width); int y1 = _random.Next(0, _canvas.Height); int y2 = _random.Next(0, _canvas.Height); Pen p = new Pen(Color.FromArgb(_random.Next(0, 256), _random.Next(0, 256), _random.Next(0, 256)), 1); _graphicObjects.Add(new MyLine(p, new Point(x1, y1), new Point(x2, y2))); this.Invalidate(); }
void AddRectangle(object sender, EventArgs e) { // Erstellt ein Rechteck mit zufälligen Werten für Position, Breite/Höhe // (mindestens 15 Pixel) und Farbe, das komplett zu sehen ist. int x = _random.Next(0, _canvas.Width); int y = _random.Next(0, _canvas.Height); int w = _random.Next(15, Math.Max(16, _canvas.Width - x)); int h = _random.Next(15, Math.Max(16, _canvas.Height - x)); Pen p = new Pen(Color.FromArgb(_random.Next(0, 256), _random.Next(0, 256), _random.Next(0, 256)), 1); _graphicObjects.Add(new MyRectangle(p, new Rectangle(x, y, w, h))); this.Invalidate(); }
void AddText(object sender, EventArgs e) { // Erstellt ein Text-Objekt mit dem eingegebenen Text und zufälligen // Werten für Position und Farbe. if (string.IsNullOrEmpty(_txtText.Text)) return; int x = _random.Next(0, _canvas.Width - 30); int y = _random.Next(0, _canvas.Height - 30); int size = _random.Next(10, 75); Pen p = new Pen(Color.FromArgb(_random.Next(0, 256), _random.Next(0, 256), _random.Next(0, 256)), 1); _graphicObjects.Add(new MyText(p, _txtText.Text, FontFamily.GenericSerif, FontStyle.Regular, size, new Point(x, y))); this.Invalidate(); } }
static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } } |
|
Ich bemerke gerade in diesem Moment dass ich euren Blog wesentlich mehr aufrufen müsste :-) - da komme ich echt auf krasse Einfälle
Krass dass das tatsächlich wirklich funktioniert ;-)