Нарисуйте прямоугольник в .NET - PullRequest
0 голосов
/ 14 июня 2010

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

Вот использование:

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

не работает ...

1 Ответ

2 голосов
/ 14 июня 2010

Подключите класс 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() родительского элемента управления при 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

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

...