如何释放指针数组中GDI区域的句柄? [英] How do I release a handle to a GDI region in a pointer array?
问题描述
在我的应用程序中,我在不同位置的图片框上绘制矩形。我可以用鼠标拖动它们,甚至用鼠标滚轮旋转它们。
起初我使用了pictureboxes,但旋转它们变得很麻烦,所以我创建了自己的类。我的类保存了对象的绘制点,在paint事件中,我从这些点创建路径并绘制它们。
要获取鼠标事件,我在绘制事件并将它们存储在指针数组中,这样我就可以使用
PtInRegion()
来检查鼠标是否在某个对象上。
这一切都很棒。对象被绘制,移动和旋转。我只需要进行数学计算以缩放整个批次,但之后我得到了一个记忆错误。
我尝试了什么:
使用Process Explorer我将问题追溯到这一行:
ptrRegion(sx)= rgn.GetHrgn(g)
这是我在指针数组中存储区域句柄的地方。
在Proccess Explorer中,每次移动对象时,我的GDI句柄数都会突然增加。
输出线路解决了GDI Handle问题但是我不能再拖动物体了。
这是我的油漆事件:
试试
Dim g As Graphics = e.Graphics
For Each Drop As MyPictureBox In DropList
With Drop
Dim sx As Integer
sx = .ArrayIndex'array index 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)
'如果ptrRegion(sx)= 0那么
ptrRegion(sx)= rgn .GetHrgn(g)'如果我评论这条线路问题就会消失,但我不能再移动这些物体了。
'结束如果
g.FillPath(.BorderSolidBrush,mypath)
g.FillPath(.FillSolidBrush,fillPath)
rgn.Dispose()
mypath.Dispose()
fillPath.Dispose()
mymatrix.Dispose()
End with
Next
Catch ex As Exception
MsgBox(错误:& ex.ToString)
结束尝试
鼠标移动:
Private Sub picFloor_MouseMove(ByVal sender As Object,ByVal e As System.Windows.Forms.MouseEventArgs)处理picFloor.MouseMove
lblCoordinates.Text =鼠标位于X:& e.X& Y:& eY
Dim id As Integer
id = 9999'鼠标指向背景
For Each Drop As MyPictureBox In DropList
Dim x As Integer
x = Drop .ArrayIndex
If(PtInRegion(ptrRegion(x),eX,eY))然后
id = x'鼠标指向一个对象
picFloor.ContextMenuStrip = rightClickMenu
退出
结束如果
下一个
mouseOverID = id
lblmouseid.Text = mouseOverID
如果drag = True则
picFloor.ContextMenuStrip = Nothing
'在鼠标右键滚动地图
如果e.Button = Windows.Forms.MouseButtons.Right那么
Dim DeltaX As Integer =(startPos.X - eX)
Dim DeltaY As Integer =(startPos.Y - eY)
'设置新的自动滚动位置。
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))
结束如果
'拖动左边的按钮
If(dragID<> 9999)然后
如果e.Button = Windows.Forms.MouseButtons.Left则
Dim Drop As MyPictureBox = DropList.Find(Function(c)c.ArrayIndex = dragID)
If Drop.PositionLocked = False Then
Dim diference = New Point(eX - startPos.X,eY - startPos.Y)'鼠标移动的距离。
Drop.DrawCentre =新点(startPos.X + diference.X - mouseOfset.X,startPos.Y + diference.Y - mouseOfset.Y)
Drop.SetCentrePoint()
Me。刷新()
结束如果
结束如果
结束如果
否则
picFloor.Focus()
DropPannel.AutoScrollPosition = panelScrollPoss'将滚动条返回到最后position
End if
End Sub
我试图使用region.translate而不是每个都创建一个新区域时间,但无法弄清楚。任何人都可以告诉我如何发布DGI句柄?在我在paint事件结束时的代码中,我处理了我使用的所有内容,但是当我移动地图或其中的对象时,GDI句柄计数仍然最大。
< blockquote>没关系。我解决了这个问题。解决方案非常容易。我取消了
ptrRegion(sx)= rgn.GetHrgn(g)
而是将该区域和指向该区域的指针作为我的类中名为BorderRegion和BorderRegionPtr的属性。然后替换这个
Dim rgn As System.Drawing.Region
rgn = New Region(mypath)
'如果ptrRegion(sx)= 0那么
ptrRegion (sx)= rgn.GetHrgn(g)
使用此代码
Dim rgn As System.Drawing.Region
rgn = New Region(mypath)
If(Drop.BorderRegionPtr = 0)然后
'区域尚未创建。
其他
Drop.BorderRegion.ReleaseHrgn(Drop.BorderRegionPtr)
结束如果
Drop.BorderRegion = rgn
Drop.BorderRegionPtr = rgn.GetHrgn(g)
使用区域和区域指针我现在可以使用Region.releaseHrgn来释放GDI句柄。
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.
Never mind. I solved the problem. The solution was ridiculously easy. I did away withptrRegion(sx) = rgn.GetHrgn(g)instead keepig the region and a pointer to the region as properties in my class called BorderRegion and BorderRegionPtr. Then replace this
Dim rgn As System.Drawing.Region rgn = New Region(mypath) 'If ptrRegion(sx) = 0 Then ptrRegion(sx) = rgn.GetHrgn(g)with this code
Dim rgn As System.Drawing.Region rgn = New Region(mypath) If (Drop.BorderRegionPtr = 0) Then 'Region not created yet. Else Drop.BorderRegion.ReleaseHrgn(Drop.BorderRegionPtr) End If Drop.BorderRegion = rgn Drop.BorderRegionPtr = rgn.GetHrgn(g)using the region and the region pointer I can now use Region.releaseHrgn to release the GDI handle.
这篇关于如何释放指针数组中GDI区域的句柄?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!