2010-06-14 3 views
0

Я пытаюсь написать класс, который нарисует себя на элементе управления (.NET). Но эта «вещь» не перерисовывается должным образом (не делает недействительным родителя, как он должен).Нарисуйте прямоугольник в .NET.

Здесь использование:

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 

Вот код:

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 
  • Что я делаю неправильно?
  • Что лучше: использовать private Graphic g и установить его только один раз, когда родитель изменился, или создать g на каждом DrawInternal?
  • Возможно ли провести мероприятие Click?

CADRE v2 (после предложения Умберто):

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

Местоположение Пример:

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 

Не работает ...

+0

Я думаю, что вы недействительны в неподходящее время. Пусть система вызывается Paint() для вас и управляет системой через Parent.Invalidate() и Parent.Update(). Как только этот сценарий запущен, добавьте функциональность и протестируйте производительность. – Humberto

+0

@Humberto: Итак, где я должен позвонить Invalidate + Update? – serhio

+0

Назовите их изменениями состояния Cadre - свойствами 'Location' и' Size'. – Humberto

ответ

2

Хук Cadre класс к Paint событие _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() родительский контроль Upon Cadre изменения на его местоположение, размер, содержание и т.д.

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 

событие щелчка обрабатывается таким же образом. Добавьте обработчик для события _Parent.MouseDown и проверьте, находятся ли координаты мыши внутри вашего Cadre. Проверьте Control.MouseDown для получения дополнительной информации.

+0

Что вы думаете о: 'Private WithEvents _Parent As Control' и' Private Sub DrawInternal (ByVal sender As Object, ByVal e As PaintEventArgs) Ручки _Parent.Paint' – serhio

+0

Не уверен, что об этом думать, так как я не VB человек! – Humberto

+0

Я считаю, что я должен обновить прежнюю зону родителя, а не всех родителей. Представьте, что миллион Кадров - это родитель, который не меняет ... Есть ли такая возможность? – serhio

Смежные вопросы