Graphic Abstract Class


Graphic Abstract Class
C#-Code:
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());
    }
}

link : http://www.mycsharp.de/wbb2/thread.php?threadid=29081

คำสำคัญ (Tags): #graphic abstract class
หมายเลขบันทึก: 93885เขียนเมื่อ 2 พฤษภาคม 2007 16:18 น. ()แก้ไขเมื่อ 11 กุมภาพันธ์ 2012 18:26 น. ()สัญญาอนุญาต:


ความเห็น (2)

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 ;-)

พบปัญหาการใช้งานกรุณาแจ้ง LINE ID @gotoknow
ขอแนะนำ ClassStart
ระบบจัดการการเรียนการสอนผ่านอินเทอร์เน็ต
ทั้งเว็บทั้งแอปใช้งานฟรี