Как освободить дескриптор для области GDI в массиве указателей?
В моем приложении Я рисую прямоугольники на picturebox в разных местах. Я могу перетаскивать их с помощью мыши и даже вращать колесиком мыши.
Сначала я использовал pictureboxes, но вращать их стало хлопотно, поэтому я создал свой собственный класс. Мой класс содержит точки рисования объекта, и в событии paint я создаю пути из этих точек и рисую их.
Чтобы получить событие мыши, я создал области в событии paint и сохранил их в массиве указателей, чтобы использовать
PtInRegion()чтобы проверить, находится ли мышь над объектом.
Отлично все это работает. Объекты окрашиваются, перемещаются и вращаются. Мне нужно было только сделать математику для масштабирования всей партии, но потом я получил ошибку out of memmory.
Что я уже пробовал:
Используя Process Explorer я проследил проблему до этой строки:
ptrRegion(sx) = rgn.GetHrgn(g)Здесь я храню дескриптор области в массиве указателей.
В Proccess Explorer Мой счетчик дескрипторов GDI взлетает до небес каждый раз, когда я перемещаю объекты.
Comenting The line out решает проблему дескриптора GDI, но тогда я больше не могу перетаскивать объекты.
Вот мое событие краски:
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
И на перемещения мыши:
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
Я попытался использовать region. translate вместо того, чтобы каждый раз создавать новый регион, но не смог этого понять. Может ли кто-нибудь сказать мне, как мне освободить ручки DGI? В моем коде в конце события paint я избавляюсь от всего, что использовал, но количество дескрипторов GDI все еще увеличивается, когда я перемещаю карту или другие объекты на ней.
Randor
Вам нужно вызвать Windows API DeleteObject (), чтобы удалить объект GDI. Я не такой VB.NET программист, поэтому я не знаю, встроено ли это в ваш фреймворк. Попробуйте вызвать его и посмотреть, что произойдет.
Regg Fulton
Спасибо. Никогда раньше не работал с вдовами Апис. Давай я погуглю и проверю. Область Мысли.Предполагается, что Dispose будет выполнять очистку.