Startsidan  ▸  Texter  ▸  Teknikblogg

Anders Hesselbom

Programmerare, skeptiker, sekulärhumanist, antirasist.
Författare till bok om C64 och senbliven lantis.
Röstar pirat.

Drag and drop GDI+ objects on a Panel

2010-11-04

This adventure takes place on a Panel that resides on a Form. I have a class that represents a GDI+ object (Thing). The Draw method that does the graphical representation of the object is very, very primitive, just enough to make it visible.

Public Class Thing

   Private m_X As Integer
   Private m_Y As Integer
   Private m_Width As Integer
   Private m_Height As Integer
   Private m_IsDragging As Boolean

   Public Sub New(ByVal Rnd As Random, ByVal Width As Integer, _
ByVal Height As Integer)
      Me.m_X = Rnd.Next(Width - 50)
      Me.m_Y = Rnd.Next(Height - 25)
      Me.m_Width = 100
      Me.m_Height = 50
   End Sub

   Public ReadOnly Property CenterX() As Integer
      Get
         Return Me.X + CType(Me.Width / 2, Integer)
      End Get
   End Property

   Public ReadOnly Property CenterY() As Integer
      Get
         Return Me.Y + CType(Me.Height / 2, Integer)
      End Get
   End Property

   Public Function GetDistance(ByVal FromX _
As Integer, ByVal FromY As Integer) As Double
      Dim DistX As Double = Math.Abs(Me.CenterX - FromX)
      Dim DistY As Double = Math.Abs(Me.CenterY - FromY)
      Dim Dist As Double = (DistX + DistY)
      If Dist = 0 Then
         Return 0
      Else
         Return Dist / 2
      End If
   End Function

   Public Property X() As Integer
      Get
         Return Me.m_X
      End Get
      Set(ByVal value As Integer)
         Me.m_X = value
      End Set
   End Property

   Public Property Y() As Integer
      Get
         Return Me.m_Y
      End Get
      Set(ByVal value As Integer)
         Me.m_Y = value
      End Set
   End Property

   Public Property Width() As Integer
      Get
         Return Me.m_Width
      End Get
      Set(ByVal value As Integer)
         Me.m_Width = value
      End Set
   End Property

   Public Property Height() As Integer
      Get
         Return Me.m_Height
      End Get
      Set(ByVal value As Integer)
         Me.m_Height = value
      End Set
   End Property

   Public Property IsDragging() As Boolean
      Get
         Return Me.m_IsDragging
      End Get
      Set(ByVal value As Boolean)
         Me.m_IsDragging = value
      End Set
   End Property

   Public Sub Draw(ByVal G As System.Drawing.Graphics)
      G.FillRectangle(Brushes.Green, Me.X, Me.Y, Me.Width, Me.Height)
      G.DrawRectangle(Pens.Black, Me.X, Me.Y, Me.Width, Me.Height)
      If Me.IsDragging Then
         G.DrawRectangle(Pens.Black, Me.X - 2, Me.Y - 2, Me.Width + 4, Me.Height + 4)
      End If
   End Sub

   Public Function HitTest(ByVal PosX As Integer, ByVal PosY As Integer) As Boolean
      Return (PosX >= Me.X _
AndAlso PosX <= (Me.X + Me.Width) _
AndAlso PosY >= Me.Y AndAlso PosY <= (Me.Y + Me.Height))
   End Function

End Class

The ThingList keeps track of all dragable objects, and makes sure that all are positioned within the visible area of the Panel.

Public Class ThingList
   Inherits System.Collections.CollectionBase

   Public Function Add(ByVal O As Thing) As Integer
      Return List.Add(O)
   End Function

   Default Public ReadOnly Property Item(ByVal Index As Integer) As Thing
      Get
         Return CType(List(Index), Thing)
      End Get
   End Property

   Public Sub Draw(ByVal G As System.Drawing.Graphics)
      For Each O As Thing In Me
         O.Draw(G)
      Next
   End Sub

   Public Function GetObjectAt(ByVal MouseX As Integer, ByVal MouseY As_
 Integer) As Thing
      If Me.Count > 0 Then
         For Each O As Thing In Me
            If O.HitTest(MouseX, MouseY) Then
               Return O
            End If
         Next
         Return Nothing
      Else
         Return Nothing
      End If
   End Function

   Public Function GetObjectIfClose(ByVal MouseX As Integer, _
ByVal MouseY As Integer) As Thing
      If Me.Count > 0 Then
         Dim CloseIndex As Integer = -1
         Dim CloseDistance As Double = 60
         For I As Integer = 0 To Me.Count - 1
            Dim Distance As Double = Me(I).GetDistance(MouseX, MouseY)
            If Distance < CloseDistance Then
               CloseDistance = Distance
               CloseIndex = I
            End If
         Next
         If CloseIndex >= 0 Then
            Return Me(CloseIndex)
         Else
            Return Nothing
         End If
      Else
         Return Nothing
      End If
   End Function

   Public Sub ResetIsDragging()
      For Each O As Thing In Me
         O.IsDragging = False
      Next
   End Sub

   Public Function MoveToVisibleArea(ByVal S As Size) As Boolean
      Dim Ret As Boolean = False
      For Each O As Thing In Me
         If O.X < 0 Then
            O.X += 2
            Ret = True
         End If
         If O.Y < 0 Then
            O.Y += 2
            Ret = True
         End If
         If (O.X + O.Width) > S.Width Then
            O.X -= 2
            Ret = True
         End If
         If (O.Y + O.Height) > S.Height Then
            O.Y -= 2
            Ret = True
         End If
      Next
      Return Ret
   End Function

End Class

The form (contains a panel named Panel1) basically keeps track of mouse actions. This does not include the drag and drop events of the Control class, because that deals with dragging and dropping controls, not GDI+ objects.

Public Class Form1

   Private L As ThingList
   Private IsDragging As Boolean
   Private DragObject As Thing = Nothing
   Private DragOffsetX As Integer
   Private DragOffsetY As Integer

   Private Sub Form1_Load(ByVal sender As _
System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      L = New ThingList()
      Dim Rnd As New Random()
      L.Add(New Thing(Rnd, Panel1.Width, Panel1.Height))
      L.Add(New Thing(Rnd, Panel1.Width, Panel1.Height))
      L.Add(New Thing(Rnd, Panel1.Width, Panel1.Height))
   End Sub

   Private Sub Panel1_MouseDown(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseDown
      Me.DragObject = L.GetObjectIfClose(e.X, e.Y)
      If Not DragObject Is Nothing Then
         Me.DragOffsetX = e.X - Me.DragObject.X
         Me.DragOffsetY = e.Y - Me.DragObject.Y
         Me.DragObject.IsDragging = True
         Me.IsDragging = True
         Panel1.Invalidate()
      End If
   End Sub

   Private Sub Panel1_MouseMove(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseMove
      If Me.IsDragging And Not Me.DragObject Is Nothing Then
         Me.DragObject.X = e.X - Me.DragOffsetX
         Me.DragObject.Y = e.Y - Me.DragOffsetY
         Panel1.Invalidate()
      End If
   End Sub

   Private Sub Panel1_MouseUp(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseUp
      If Me.IsDragging Then
         Me.IsDragging = False
         L.ResetIsDragging()
         Me.DragObject = Nothing
      End If
      L.MoveToVisibleArea(Panel1.Size)
      Panel1.Invalidate()
   End Sub

   Private Sub Panel1_Paint(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
      e.Graphics.FillRectangle(Brushes.White, 0, 0, Me.Width, Me.Height)
      L.Draw(e.Graphics)
   End Sub

   Private Sub Panel1_Resize(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Resize
      If Not L Is Nothing Then
         If L.MoveToVisibleArea(Panel1.Size) Then
            Panel1.Invalidate()
         End If
      End If
   End Sub

End Class

Now you can play around with three green boxes in the panel.

Categories: Visual Basic 9

Tags: GDI+

Leave a Reply

Your email address will not be published. Required fields are marked *



En kopp kaffe!

Bjud mig på en kopp kaffe (20:-) som tack för bra innehåll!

Bjud på en kopp kaffe!

Om...

Kontaktuppgifter, med mera, finns här.

Följ mig

Twitter Instagram
GitHub RSS

Public Service

Folkbildning om public service.

Hem   |   linktr.ee/hesselbom   |   winsoft.se   |   80tal.se   |   Filmtips