2012-12-27 8 views
9

Sto facendo un programma di test per vedere quanto posso aggiungere eventi a un oggetto System.Windows.Form.Control disegnato. Dovrei fare bene con questo, quindi posso fare qualcosa di più avanzato per dopo.Windows Form: qual è il modo giusto per consentire i controlli sovrapposti?

Il problema che sto avendo riguarda l'immagine allegata. Ho disegnato due cerchi volutamente vicini l'uno all'altro. L'obiettivo è quello di sovrapporre un cerchio a un altro. Ai fini di questo programma di test, non mi interessa quale cerchio si sovrapponga a quale. Tuttavia, mi preoccupo per gli angoli.

Wish that the two circles just overlapped properly instead of having the jutting corners.

L'immagine sopra mostra che il cerchio centrale è sepolto dal cerchio sinistro, ma il cerchio di sinistra è inoltre elaborando angoli e copre il cerchio centrale con loro. Spero di nascondere quegli angoli, o almeno renderli trasparenti. Ho letto che c'è un modo per make a control transparent, ma l'uso di Color.Transparent sul BackColor mi dava il nero per qualche motivo invece di trovare corrispondenza con il colore del pannello.

Di seguito è riportata la parte del codice della GUI (il progettista non è incluso, ma le parti chiave dovrebbero essere ovvie).

namespace PaintingFirstAttempt 
{ 
    using System; 
    using System.Drawing; 
    using System.Windows.Forms; 

    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void BtnExit_Click(object sender, EventArgs e) 
     { 
      this.Close(); 
     } 

     private void BtnClear_Click(object sender, EventArgs e) 
     { 
      Graphics g1 = this.paintPanel.CreateGraphics(); 
      g1.Clear(this.paintPanel.BackColor); 
      g1.Dispose(); 
     } 

     private void PaintPanel_MouseDown(object sender, MouseEventArgs e) 
     { 
      this.paintPanel.Controls.Add(new EventableCircle { Location = new Point(e.X - 16, e.Y - 16), Size = new Size(32, 32) }); 
     } 
    } 
} 

Di seguito è riportato il cerchio personalizzato.

namespace PaintingFirstAttempt 
{ 
    using System; 
    using System.Drawing; 
    using System.Windows.Forms; 

    public class EventableCircle : Control 
    { 
     public EventableCircle() 
     { 
      this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); 
      // this.BackColor = Color.Transparent; 
     } 

     private static SolidBrush fillColor = new SolidBrush(Color.Red); 
     protected override void OnClick(EventArgs e) 
     { 
      MessageBox.Show("TODO: Bring up a combo box on right click."); 
     } 

     private void DrawCircle(Pen pen) 
     { 
      Graphics g = this.CreateGraphics(); 
      g.Clear(this.BackColor); 
      g.FillRectangle(new SolidBrush(Color.Transparent), 0, 0, 32, 32); 
      g.FillEllipse(fillColor, 0, 0, 32, 32); 
      g.DrawEllipse(pen, 0, 0, 32, 32); 
      g.Dispose(); 

     } 

     protected override void OnPaint(PaintEventArgs e) 
     { 
      this.DrawCircle(Pens.Black); 
     } 

     protected override void OnMouseEnter(EventArgs e) 
     { 
      base.OnMouseEnter(e); 
      this.DrawCircle(Pens.Blue); 
     } 

     protected override void OnMouseLeave(EventArgs e) 
     { 
      base.OnMouseLeave(e); 
      this.DrawCircle(Pens.Black); 
     } 
    } 
} 

Con queste informazioni in mente, come faccio a ottenere sia gli angoli dei cerchi di non mostrare, o trovare un modo per ovviare a questo?

+1

Questo dovrebbe aiutare: http://www.c-sharpcorner.com/UploadFile/mahesh/DrawTransparentImageUsingAB10102005010514AM/DrawTransparentImageUsingAB.aspx - anche in considerazione tenere un elenco delle coordinate per la rilevazione di clic e ridisegno gli oggetti grafici, piuttosto che derivare da 'Control' –

+0

Non capisco qualcosa con il tuo commento Jeremy. In primo luogo, quel collegamento funzionerebbe anche senza usare un'immagine? Desidero generare ancora da zero per ora. Secondo, qual è esattamente il vantaggio di elencare le coordinate? Stai suggerendo di calcolare semplicemente quando sono in circolo? – Wolfman2000

+1

Avrei dovuto essere più chiaro. Disegnare cerchi rossi usando un elenco di coordinate in memoria è molto più efficiente della creazione di una serie di controlli utente di Red Circle. Sembra che sia necessario solo dipingere gli oggetti grafici e quindi essere in grado di rilevare e reagire agli eventi di clic. Penso che sia anche qui il problema, disegnare oggetti in quanto Control perde il controllo della trasparenza ed è per questo che consiglio di considerarli come oggetti grafici. Ulteriori letture [Programmazione grafica C# con Rod Stephens] (http://www.amazon.com/C-Graphics-Programming-ebook/dp/B004GXC85W). –

risposta

3

OK, basta inserire un form in mainform1, non ha bisogno di alcun codice. Ecco il codice per l'usercontrol, Disegna 3 o 4 sul modulo in modo che possano sovrapporsi se si spostano a destra.

Quindi fare clic su di loro! Ci sono inefficienze, ma il bambino sta piangendo e io devo andare, e batte facendo il tuo editor di oggetti conservato!

enter image description here

Public Class linectl 

    Public Sub DrawMe(ByVal g As Graphics, ByVal otherctl As Control) 
     Dim where As New Rectangle(otherctl.Left - Left, otherctl.Top - Top, otherctl.Width - 1, otherctl.Height - 1) 
     g.FillEllipse(Brushes.Red, where) 
     g.DrawEllipse(Pens.Black, where) 
    End Sub 

    Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs) 
     MyBase.OnPaintBackground(e) 
     DrawMe(e.Graphics, Me) 
     drawneighbors() 
    End Sub 

    Private Sub linectl_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click 
     Me.Left += 10 
    End Sub 

    Private Sub linectl_MoveResize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Move, Me.Resize 
     If Parent IsNot Nothing Then 
      For Each c In From ctl In Parent.Controls Where TypeOf ctl Is linectl Select CType(ctl, linectl) 
       Using g = c.CreateGraphics 
        g.Clear(c.BackColor) 
        c.DrawMe(g, c) 
        c.drawneighbors() 
       End Using 
      Next 
     End If 
    End Sub 

    Public Sub drawneighbors() 
     If Parent IsNot Nothing Then 
      Dim ctls = (From ctl In Parent.Controls Where TypeOf ctl Is linectl Let c = CType(ctl, linectl) _ 
         Select New With {.ctl = c, _ 
          .rect = New Rectangle(c.Left, c.Top, c.Width, c.Height)}).ToArray.Reverse 
      For Each ctl In ctls 
       Dim ctl_unclosed = ctl 
       For Each ictl In (From c In ctls Where ctl_unclosed.rect.IntersectsWith(c.rect)) 
        Using g = ictl.ctl.CreateGraphics 
         ictl.ctl.DrawMe(g, Me) 
        End Using 
        Using g = Me.CreateGraphics 
         Me.DrawMe(g, ictl.ctl) 
        End Using 
       Next 
      Next 
     End If 
    End Sub 

End Class