如何释放指针数组中GDI区域的句柄? [英] How do I release a handle to a GDI region in a pointer array?

查看:71
本文介绍了如何释放指针数组中GDI区域的句柄?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我在不同位置的图片框上绘制矩形。我可以用鼠标拖动它们,甚至用鼠标滚轮旋转它们。



起初我使用了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 with

ptrRegion(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆