2016-07-13 16 views
4

Eigentlich nach dem Klicken auf jeden Kreis möchte ich, dass seine Farbe geändert wird, zum Beispiel möchte ich, dass es in rot wird, Insgesamt möchte ich es als Kontrolle behandeln.Wie kann ich den Kreis nach dem Zeichnen als Steuerelement behandeln? - Verschieben und Auswählen von Formen

Ich kann die Kreise zeichnen, die die Knoten des Diagramms darstellen, wenn ich auf die Bildbox doppelklicke. Ich verwende den folgenden Code:

 public Form1() 
    { 
     InitializeComponent(); 

     pictureBox1.Paint += new PaintEventHandler(pic_Paint); 
    } 

    public Point positionCursor { get; set; } 
    private List<Point> points = new List<Point>(); 
    public int circleNumber { get; set; } 

    private void pictureBox1_DoubleClick(object sender, EventArgs e) 
    { 
     positionCursor = this.PointToClient(new Point(Cursor.Position.X - 25, Cursor.Position.Y - 25)); 

     points.Add(positionCursor); 
     Label lbl = new Label(); 
     lbl.BackColor = Color.Transparent; 
     lbl.Font = new Font("Arial", 7); 

     lbl.Size = new Size(20, 15); 

     if (circleNumber >= 10) 
     { 
      lbl.Location = new Point(points[circleNumber].X + 3, points[circleNumber].Y + 6); 
     } 
     else 
     { 
      lbl.Location = new Point(points[circleNumber].X + 7, points[circleNumber].Y + 7); 
     } 
     lbl.Text = circleNumber.ToString(); 
     pictureBox1.Controls.Add(lbl); 
     circleNumber++; 
     pictureBox1.Invalidate(); 
    } 

    private void pic_Paint(object sender, PaintEventArgs e) 
    { 
     Graphics g = e.Graphics; 
     g.SmoothingMode = SmoothingMode.AntiAlias; 

     using (var pen = new Pen(Color.DimGray, 2)) 
     { 
      foreach (Point pt in points) 
      { 
       g.FillEllipse(Brushes.White, pt.X, pt.Y, 25, 25); 
       g.DrawEllipse(pen, pt.X, pt.Y, 26, 26); 
      } 
     } 
    } 

enter image description here

+1

, wenn Sie es brauchen eine Kontrolle, dann eine Kontrolle vornehmen, die einen Kreis zieht .. dann Sie die neue Steuerung machen und es auf dem Formular platzieren, anstatt einen Kreis zeichnen – BugFinder

+0

Sie müssen Test für Kreise treffen und dann, wenn der Hit-Testpunkt in einem Kreis ist, zeichne ihn in roter Farbe. –

+0

@ BugFinder, Ihre Meinung, ich mache Benutzerkontrolle. –

Antwort

6

Sie benötigen einen Hit-Test zu überprüfen, um auszuführen, wenn ein Punkt in einem Kreis ist. Als Option können Sie einen Kreis zu einer GraphicsPath hinzufügen und die Methode IsVisible des Pfades verwenden, um zu überprüfen, ob der Punkt im Kreis ist.

Zum Beispiel eines ponit p als linke obere Lage eines Kreises mit einem Durchmesser mit d, können Sie überprüfen, ob Strom klickten Punkt im Kreis ist oder con auf diese Weise:

var result = false; 
using (var path = new GraphicsPath()) 
{ 
    path.AddEllipse(p.X, p.Y, d, d); 
    result = path.IsVisible(e.Location); 
} 

Probe Code

Ich sehe, dass Sie mehrere Fragen in diesem Thema gestellt haben. Hier teile ich einen Code, der dir hilft, in die richtige Richtung zu gehen.

definieren Variablen für Füllfarbe, ausgewählte Füllfarbe, Kreisgröße, Randbreite und usw., um sie einfach ändern zu können, wenn Sie benötigen.

List<Rectangle> Shapes = new List<Rectangle>(); 
int selectedIndex = -1; 
Size size = new Size(25, 25); 
Color fillColor = Color.White; 
Color selectedfillCOlor = Color.Red; 
Color borderColor = Color.Gray; 
int borderWidth = 2; 

Double

Hier fügen Kreisen der Shapes Liste. Es reicht aus, das Begrenzungsrechteck eines Kreises zur Liste hinzuzufügen.

private void pic_MouseDoubleClick(object sender, MouseEventArgs e) 
{ 
    var p = e.Location; 
    p.Offset(-size.Width/2, -size.Height/2); 
    Shapes.Add(new Rectangle(p, size)); 
    pic.Invalidate(); 
} 

Click

Hier führen Hit-Test zu prüfen, ob der Punkt in einem der circles.Check ist, wenn die Ctrl-Taste gedrückt ist, wenn klicken, eine Auswahl zu treffen, dann ist die Ergebnismenge Index als selectedIndex, um es beim Malen zu verwenden.

private void pic_MouseClick(object sender, MouseEventArgs e) 
{ 
    if (ModifierKeys != Keys.Control) 
     return; 
    selectedIndex = -1; 
    for (int i = 0; i < Shapes.Count; i++) 
    { 
     using (var path = new GraphicsPath()) 
     { 
      path.AddEllipse(Shapes[i]); 
      if (path.IsVisible(e.Location)) 
       selectedIndex = i; 
     } 
    } 
    pic.Invalidate(); 
} 

Farbe

Set SmoothingMode von Grafiken AntiAlias Objekt eine glattere Zeichnung zu haben. Zeichnen Sie dann Formen in eine for-Schleife und achten Sie auf , um eine andere Füllfarbe für die ausgewählte Form zu verwenden.

Um den Text zu zeichnen, brauchen Sie keine label verwenden und Sie können einfach Text mit TextRenderer Klasse zeichnen.

private void pic_Paint(object sender, PaintEventArgs e) 
{ 
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; 
    for (int i = 0; i < Shapes.Count; i++) 
    { 
     var selected = (selectedIndex == i); 
     using (var brush = new SolidBrush(selected ? selectedfillCOlor : fillColor)) 
      e.Graphics.FillEllipse(brush, Shapes[i]); 
     using (var pen = new Pen(borderColor, borderWidth)) 
      e.Graphics.DrawEllipse(pen, Shapes[i]); 
     TextRenderer.DrawText(e.Graphics, (i + 1).ToString(), 
       this.Font, Shapes[i], Color.Black, 
       TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter); 
    } 
} 

Einige Anmerkungen

  • Es ist besser, Codes in einer neuen Steuerung von PictureBox abgeleitet zu kapseln oder abgeleitet Control und setzen DoubleBuffered auf true.

  • Es ist eine gute Option, Circle in einer Circle Klasse zu verkapseln, die Hit-Test und Rendern eines Kreises durchführt. Besonders, wenn Sie sie später verschieben oder andere Interaktionen durchführen wollen oder jeder Kreis seine eigenen Eigenschaften wie Farbe usw.

Musterkreis Klasse

Hier ist ein Beispiel Kreisklasse, die ein guter Startpunkt sein kann.

public class Circle 
{ 
    private Color selectedFillColor = Color.Red; 
    private Color normalFillColor = Color.Red; 
    private Color borderColor = Color.Red; 
    private int borderWidth = 2; 
    public Point Location { get; set; } 
    public int Diameter { get; set; } 
    public Rectangle Bounds 
    { 
     get 
     { 
      return new Rectangle(Location, new Size(Diameter, Diameter)); 
     } 
    } 
    public bool HitTest(Point p) 
    { 
     var result = false; 
     using (var path = new GraphicsPath()) 
     { 
      path.AddEllipse(Bounds); 
      result = path.IsVisible(p); 
     } 
     return result; 
    } 
    public bool Selected { get; set; } 
    public void Draw(Graphics g) 
    { 
     using (var brush = new SolidBrush(
      Selected ? selectedFillColor : normalFillColor)) 
      g.FillEllipse(brush, Bounds); 
     using (var pen = new Pen(borderColor, 2)) 
      g.DrawEllipse(pen, Bounds); 
    } 
} 
+0

Vielen Dank, Ihre Meinung, Welches der Bücher habe ich gelesen? Grafikprogrammierung mit GDI + oder Pro .NET 2.0 Grafikprogrammierung. Haben Sie einen besseren Vorschlag? –

+0

Gern geschehen :) - Das ist ein gutes Buch. Es kann jedoch viele Informationen enthalten, die Sie in der aktuellen Aufgabe nicht benötigen. Also, wenn Sie das Buch oder irgendwelche Artikel lesen möchten, lesen Sie einfach die Teile, die mit Ihrer Aufgabe in Verbindung stehen. Wie auch immer, ich fügte der Antwort auch eine Beispiel- "Circle" -Klasse hinzu. –

+0

Weitere Informationen zum Erstellen eines Benutzersteuerelements und zum Verarbeiten von Benutzersteuerelementen finden Sie in [diesem Beitrag] (http://stackoverflow.com/a/38297293/3110834). –