2010-06-14 7 views
0

J'essaie d'écrire une classe qui va se dessiner sur un contrôle (.NET). Mais cette "chose" ne se repeint pas correctement (n'invalide pas le parent comme il se doit).Dessiner un rectangle dans .NET

Voici l'utilisation:

Public Class Form1 
    Dim myCadre As New Cadre 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
    For i As Integer = 0 To 100 
     myCadre.Location = New Point(myCadre.Location.X + 1, myCadre.Location.Y + 1) 
     System.Threading.Thread.Sleep(500) 
    Next i 
    End Sub 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
    myCadre.Location = New Point(10, 10) 
    myCadre.Size = New Size(60, 90) 
    myCadre.Parent = Me 
    End Sub 
End Class 

Voici le code:

Public Class Cadre 
    Private _Rectangle As Rectangle 
    Private _Parent As Control 
    Public Event ParentChanged As EventHandler 
    Private _Location As Point 

    Public ReadOnly Property DisplayRectangle() As Rectangle 
    Get 
     Return _Rectangle 
    End Get 
    End Property 

    Public Property Location() As Point 
    Get 
     Return _Rectangle.Location 
    End Get 
    Set(ByVal value As Point) 
     _Rectangle.Location = value 
     DrawInternal() 
    End Set 
    End Property 

    Public Property Size() As Size 
    Get 
     Return _Rectangle.Size 
    End Get 
    Set(ByVal value As Size) 
     _Rectangle.Size = value 
     DrawInternal() 
    End Set 
    End Property 

    Public Property Parent() As Control 
    Get 
     Return _Parent 
    End Get 
    Set(ByVal value As Control) 
     If _Parent IsNot value Then 
     _Parent = value 
     OnParentChanged(Me, EventArgs.Empty) 
     End If 
    End Set 
    End Property 

    Overridable Sub OnParentChanged(ByVal sender As Object, ByVal e As EventArgs) 
    DrawInternal() 
    RaiseEvent ParentChanged(sender, e) 
    End Sub 

    Private Sub DrawInternal() 
    If _Parent Is Nothing Then Return 
    Dim g As Graphics = _Parent.CreateGraphics() 

    g.DrawRectangle(Pens.Black, Me._Rectangle) 
    End Sub 
End Class 
  • Qu'est-ce que je fais mal?
  • ce qui est mieux: utiliser le jeu private Graphic g et qu'une fois changé quand parent, ou créer g à chaque DrawInternal? Est-il possible d'avoir l'événement Click?

v2 CRARDE (après suggestions Humberto):

Public Class Cadre 
    Private _FormerRectangle As Rectangle 
    Private _Rectangle As Rectangle 
    Private WithEvents _Parent As Control 
    Public Event ParentChanged As EventHandler 
    Private _Location As Point 

    Public Sub New() 
    _FormerRectangle = New Rectangle 
    _Rectangle = _FormerRectangle 
    End Sub 

    Private Sub DrawInternal(ByVal sender As Object, ByVal e As PaintEventArgs) Handles _Parent.Paint 
    If _FormerRectangle <> _Rectangle Then 
     _Parent.Invalidate(_FormerRectangle, False) ' !!! does not work ' 
    End If 

    e.Graphics.DrawRectangle(Pens.Black, Me._Rectangle) 
    _FormerRectangle = Me._Rectangle 
    End Sub 

    Public ReadOnly Property DisplayRectangle() As Rectangle 
    Get 
     Return _Rectangle 
    End Get 
    End Property 

    Public Property Location() As Point 
    Get 
     Return _Rectangle.Location 
    End Get 
    Set(ByVal value As Point) 
     _Rectangle.Location = value 
    End Set 
    End Property 

    Public Property Size() As Size 
    Get 
     Return _Rectangle.Size 
    End Get 
    Set(ByVal value As Size) 
     _Rectangle.Size = value 
    End Set 
    End Property 

    Public Property Parent() As Control 
    Get 
     Return _Parent 
    End Get 
    Set(ByVal value As Control) 
     If _Parent IsNot value Then 
     _Parent = value 
     OnParentChanged(Me, EventArgs.Empty) 
     End If 
    End Set 
    End Property 

    Overridable Sub OnParentChanged(ByVal sender As Object, ByVal e As EventArgs) 
    RaiseEvent ParentChanged(sender, e) 
    End Sub 

End Class 

Edit3

Localisation Exemple:

Public Property Location() As Point 
    Get 
     Return _Rectangle.Location 
    End Get 
    Set(ByVal value As Point) 
     If _Parent IsNot Nothing Then 
     _Parent.Invalidate(_Rectangle, False) ' 1st Call with former ' 
     End If 
     _Rectangle.Location = value 
     If _Parent IsNot Nothing Then 
     _Parent.Invalidate(_Rectangle, False) ' 2nd Call with new ' 
     _Parent.Update() 
     End If 
    End Set 
    End Property 

ne fonctionne pas ...

+0

Je pense que vous invalidez au mauvais moment. Laissez le système appeler Paint() pour vous et contrôlez le système via Parent.Invalidate() et Parent.Update(). Une fois ce scénario en cours, ajoutez des fonctionnalités et testez les performances. – Humberto

+0

@Humberto: Alors, où dois-je appeler Invalidate + Update? – serhio

+0

Appelez-les lors de changements dans l'état de Cadre - les propriétés 'Location' et' Size'. – Humberto

Répondre

2

Accrochez la classe Cadre auévénementdu membre _Parent:

Public Property Parent() As Control 
    Get 
     Return _Parent 
    End Get 

    Set(ByVal value As Control) 
     If _Parent IsNot Nothing Then 
      RemoveHandler _Parent.Paint, AddressOf Me.Cadre_Paint 
     End If 

     _Parent = value 

     If _Parent IsNot Nothing Then 
      AddHandler _Parent.Paint, AddressOf Me.Cadre_Paint 
     End If 
    End Set 
End Property 

Private Sub Cadre_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) 
    Dim g As Graphics = e.Graphics 
    g.DrawRectangle(Pens.Black, Me._Rectangle) 
End Sub 

Refresh() le contrôle des parents sur Cadre changements sur son emplacement, la taille, le contenu etc.

Public Property Size() As Size 
    Get 
     Return _Rectangle.Size 
    End Get 
    Set(ByVal value As Size) 
     _Rectangle.Size = value 

     If _Parent IsNot Nothing Then 
      _Parent.Refresh() 
     End If 
    End Set 
End Property 

L'événement click est manipulé d'une manière similaire. Ajoutez un gestionnaire pour l'événement _Parent.MouseDown et vérifiez si les coordonnées de la souris sont à l'intérieur de votre Cadre. Vérifiez Control.MouseDown pour plus d'informations.

+0

Que pensez-vous de: 'Private WithEvents _Parent As Control' et' Private Sub DrawInternal (Expéditeur ByVal en tant qu'objet, ByVal e As PaintEventArgs) Traite _Parent.Paint' – serhio

+0

Vous ne savez pas quoi penser de ces choses, car je ne suis pas VB homme! – Humberto

+0

Je crois que je devrais rafraîchir sur l'ancienne zone du parent, pas tous les parents. Imaginez-vous qu'un million de Cadres est le parent qui ne change pas ... Y a-t-il une telle possibilité? – serhio

Questions connexes