In my app I paint rectangles on a picturebox in diferent locations. I can drag them around with the mouse and even rotate them with the mouse wheel.
At first I used pictureboxes, but rotating them became a hassle, so I created my own class instead. My class holds the drawing point points of the object and in the paint event I create paths from these points and paint them.
To get mouse event I created regions in the paint event and stored them in a pointer array so I can use
PtInRegion()
to check if a mouse is over an object.
Great it all works. Object are painted, moved and rotated. I only needed to do the math for scaling the whole lot but then i got an out of memmory error.
What I have tried:
Using Process Explorer I traced the problem to this line:
ptrRegion(sx) = rgn.GetHrgn(g)
This is where I store a handle to the region in a pointer array.
In Proccess Explorer my GDI handle count skyrockets every time I move the objects.
Comenting the line out solves the GDI Handle problem but then I cannot drag the objects anymore.
Here is my paint event:
Try
Dim g As Graphics = e.Graphics
For Each Drop As MyPictureBox In DropList
With Drop
Dim sx As Integer
sx = .ArrayIndex 'array index of drop
Dim mypath, fillPath As New System.Drawing.Drawing2D.GraphicsPath
Dim curvepoints As Point() = {.BorderPoint1, .BorderPoint2, .BorderPoint3, .BorderPoint4}
Dim fillPoint As Point() = {.FillPoint1, .FillPoint2, .FillPoint3, .FillPoint4}
Dim rPoint = .DrawCentre
mypath.AddPolygon(curvepoints)
fillPath.AddPolygon(fillPoint)
Dim mymatrix As New System.Drawing.Drawing2D.Matrix
mymatrix.RotateAt(.ShelfRotation, rPoint)
mypath.Transform(mymatrix)
fillPath.Transform(mymatrix)
Dim rgn As System.Drawing.Region
rgn = New Region(mypath)
'If ptrRegion(sx) = 0 Then
ptrRegion(sx) = rgn.GetHrgn(g) 'if I comment this line out promblem disappears but I cannot move the objects anymore.
'End If
g.FillPath(.BorderSolidBrush, mypath)
g.FillPath(.FillSolidBrush, fillPath)
rgn.Dispose()
mypath.Dispose()
fillPath.Dispose()
mymatrix.Dispose()
End With
Next
Catch ex As Exception
MsgBox("Error:" & ex.ToString)
End Try
And on mouse move:
Private Sub picFloor_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picFloor.MouseMove
lblCoordinates.Text = "Mouse is at X: " & e.X & " Y: " & e.Y
Dim id As Integer
id = 9999 'mouse pointing at background
For Each Drop As MyPictureBox In DropList
Dim x As Integer
x = Drop.ArrayIndex
If (PtInRegion(ptrRegion(x), e.X, e.Y)) Then
id = x 'mouse is pointing to an object
picFloor.ContextMenuStrip = rightClickMenu
Exit For
End If
Next
mouseOverID = id
lblmouseid.Text = mouseOverID
If drag = True Then
picFloor.ContextMenuStrip = Nothing
'Scroll the map on mouse right button
If e.Button = Windows.Forms.MouseButtons.Right Then
Dim DeltaX As Integer = (startPos.X - e.X)
Dim DeltaY As Integer = (startPos.Y - e.Y)
'Set the new autoscroll position.
DropPannel.AutoScrollPosition = New Drawing.Point((DeltaX - DropPannel.AutoScrollPosition.X), (DeltaY - DropPannel.AutoScrollPosition.Y))
panelScrollPoss = New Drawing.Point((DeltaX - DropPannel.AutoScrollPosition.X), (DeltaY - DropPannel.AutoScrollPosition.Y))
End If
'Drag the shelf on left button
If (dragID <> 9999) Then
If e.Button = Windows.Forms.MouseButtons.Left Then
Dim Drop As MyPictureBox = DropList.Find(Function(c) c.ArrayIndex = dragID)
If Drop.PositionLocked = False Then
Dim diference = New Point(e.X - startPos.X, e.Y - startPos.Y) 'distance that the mouse moved.
Drop.DrawCentre = New Point(startPos.X + diference.X - mouseOfset.X, startPos.Y + diference.Y - mouseOfset.Y)
Drop.SetCentrePoint()
Me.Refresh()
End If
End If
End If
Else
picFloor.Focus()
DropPannel.AutoScrollPosition = panelScrollPoss 'Return scrollbars to its last position
End If
End Sub
I tried to use region.translate instead of creating a new region every time, but couldn't figure it out. Can anyone please tell me how do I release the DGI handles? In my code at the end of the paint event, I dispose of everything I used but the GDI handle count still maxes when I move the map or othe objects on it.