Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

'System.OutOfMemoryException' occurred in system.drawing.dll

650 views
Skip to first unread message

steve percival

unread,
Mar 1, 2002, 10:23:43 AM3/1/02
to
Sorry about this but this is going to be a long post.

I am trying to create a menuitem class that displays
icons. I have found several sources on the internet and
have cobbled together the following class. The problem I
have is that when I use it on a form it works for a while
but then starts giving the following exception:

An unhandled exception of
type 'System.OutOfMemoryException' occurred in
system.drawing.dll

Additional information: Out of memory.

Can anyone see a problem with the class. or the way I am
calling it


MENU ITEM CLASS

Imports System.Drawing.Text
Imports System.ComponentModel

Namespace NSIconMenuItem

Public Class IconMenuItem
Inherits System.Windows.Forms.MenuItem

#Region " Windows Form Designer generated code "

Private _DisplayIcon As Icon
#Region " Constructors "
Public Sub New()
MyBase.New()

'This call is required by the Windows Form
Designer.
InitializeComponent()

'Add any initialization after the
InitializeComponent() call
Me.OwnerDraw = True
End Sub
Public Sub New(ByVal text As String)
MyBase.New(text)

'This call is required by the Windows Form
Designer.
InitializeComponent()

'Add any initialization after the
InitializeComponent() call
Me.OwnerDraw = True
End Sub
Public Sub New(ByVal text As String, ByVal OnClick
As EventHandler)
MyBase.New(text, OnClick)

'This call is required by the Windows Form
Designer.
InitializeComponent()

'Add any initialization after the
InitializeComponent() call
Me.OwnerDraw = True
End Sub

Public Sub New(ByVal text As String, ByVal Items()
As MenuItem)
MyBase.New(text, Items)

'This call is required by the Windows Form
Designer.
InitializeComponent()

'Add any initialization after the
InitializeComponent() call
Me.OwnerDraw = True
End Sub

Public Sub New(ByVal text As String, ByVal OnClick
As EventHandler, ByVal Shortcut As Shortcut)
MyBase.New(text, OnClick, Shortcut)

'This call is required by the Windows Form
Designer.
InitializeComponent()

'Add any initialization after the
InitializeComponent() call
Me.OwnerDraw = True
End Sub

Public Sub New(ByVal MergeType As MenuMerge, ByVal
MergeOrder As Integer, ByVal Shortcut As Shortcut, _
ByVal text As String, ByVal OnClick As
EventHandler, ByVal OnPopup As EventHandler, _
ByVal OnSelect As EventHandler, ByVal Items()
As MenuItem)

MyBase.New(MergeType, MergeOrder, Shortcut,
text, OnClick, OnPopup, OnSelect, Items)

'This call is required by the Windows Form
Designer.
InitializeComponent()

'Add any initialization after the
InitializeComponent() call
Me.OwnerDraw = True
End Sub
#End Region
Protected Overloads Overrides Sub Dispose(ByVal
disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
_DisplayIcon.Dispose()
_DisplayIcon = Nothing
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As
System.ComponentModel.IContainer

'NOTE: The following procedure is required by the
Windows Form Designer
'It can be modified using the Windows Form
Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private
Sub InitializeComponent()
'
'
'
components = New
System.ComponentModel.Container()

End Sub

#End Region
Public Property DisplayIcon() As Icon
Get
DisplayIcon = _DisplayIcon
End Get
Set(ByVal Value As Icon)
_DisplayIcon = Value
End Set
End Property


Protected Overrides Sub OnMeasureItem(ByVal e As
System.Windows.Forms.MeasureItemEventArgs)
MyBase.OnMeasureItem(e)
Dim sf As StringFormat = New StringFormat()

Dim fnt As Font = SystemInformation.MenuFont

sf.HotkeyPrefix = HotkeyPrefix.Show
sf.SetTabStops(50, New Single() {0})

If Me.DisplayIcon.Height > fnt.Height Then
e.ItemHeight = Me.DisplayIcon.Height + 6
Else
e.ItemHeight = fnt.Height + 6
End If
e.ItemWidth = CInt(e.Graphics.MeasureString
(AppendShortcut(), _
fnt, 1000, sf).Width) +
Me.DisplayIcon.Width + 5

sf.Dispose()

sf = Nothing
End Sub

Protected Overrides Sub OnDrawItem(ByVal e As
System.Windows.Forms.DrawItemEventArgs)
MyBase.OnDrawItem(e)
Dim sf As StringFormat
sf = New StringFormat()
Try
sf.HotkeyPrefix = HotkeyPrefix.Show
sf.SetTabStops(50, New Single() {0})
If ((e.State And
System.Windows.Forms.DrawItemState.Selected) <> 0) Then

e.Graphics.FillRectangle(New SolidBrush
(SystemColors.Highlight), e.Bounds)

e.Graphics.DrawString(AppendShortcut
(), SystemInformation.MenuFont, New SolidBrush
(SystemColors.HighlightText), New PointF(e.Bounds.Height +
2, CType((e.Bounds.Height - e.Graphics.MeasureString
(Me.Text, SystemInformation.MenuFont).Height), Integer) /
2), sf)
Else
e.Graphics.FillRectangle(New SolidBrush
(SystemColors.Menu), e.Bounds)
e.Graphics.DrawString(AppendShortcut
(), SystemInformation.MenuFont, New SolidBrush
(SystemColors.MenuText), New PointF(e.Bounds.Height + 2,
CType((e.Bounds.Height - e.Graphics.MeasureString(Me.Text,
SystemInformation.MenuFont).Height), Integer) / 2), sf)
End If

If Not (Me.DisplayIcon Is Nothing) Then
e.Graphics.DrawIcon(Me.DisplayIcon,
New Rectangle(0, 0, e.Bounds.Height, e.Bounds.Height))
End If
Catch x As Exception
MessageBox.Show(x.StackTrace)
End Try
sf.Dispose()
sf = Nothing
End Sub

Private Function AppendShortcut() As String
Dim s As String
s = Me.Text
' Check to see if you have a shortcut
' If so, append it to your existing text
If Me.ShowShortcut And Me.Shortcut <>
Shortcut.None Then
Dim k As Keys = CType(Shortcut, Keys)
s = s & Convert.ToChar(9) & _
TypeDescriptor.GetConverter(GetType
(Keys)).ConvertToString(k)
End If
Return s
End Function

End Class
End Namespace

FORM CLASS

Imports nsIconMenuItem
Public Class Form1
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form
Designer.
InitializeComponent()

'Add any initialization after the
InitializeComponent() call
End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal
disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the
Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.

Friend WithEvents MainMenu1 As
System.Windows.Forms.MainMenu
Friend WithEvents MenuItem1 As
System.Windows.Forms.MenuItem
Friend WithEvents MenuItem2 As IconMenuItem
Friend WithEvents MenuItem3 As
System.Windows.Forms.MenuItem
Friend WithEvents MenuItem4 As
System.Windows.Forms.MenuItem

<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.MainMenu1 = New System.Windows.Forms.MainMenu()
Me.MenuItem1 = New System.Windows.Forms.MenuItem()
Me.MenuItem2 = New IconMenuItem()
Me.MenuItem3 = New System.Windows.Forms.MenuItem()
Me.MenuItem4 = New System.Windows.Forms.MenuItem()

'
'MainMenu1
'
Me.MainMenu1.MenuItems.AddRange(New
System.Windows.Forms.MenuItem() {Me.MenuItem1})
'
'MenuItem1
'
Me.MenuItem1.Index = 0
Me.MenuItem1.MenuItems.AddRange(New
System.Windows.Forms.MenuItem() {Me.MenuItem2,
Me.MenuItem3, Me.MenuItem4})
Me.MenuItem1.Text = "&File"
'
'MenuItem2
'
Me.MenuItem2.Index = 0
Me.MenuItem2.Text = "&Open"
Me.MenuItem2.DisplayIcon = New Icon("C:\Documents
and Settings\steveip.CORPOFLONDON\My Documents\Visual
Studio Projects\MenuTest\new.ico")
Me.MenuItem2.Shortcut = Shortcut.CtrlO
'
'MenuItem3
'
Me.MenuItem3.Index = 1
Me.MenuItem3.Text = "-"
'
'MenuItem4
'
Me.MenuItem4.Index = 2
Me.MenuItem4.Text = "E&xit"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5,
13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Menu = Me.MainMenu1
Me.Name = "Form1"
Me.Text = "Form1"

End Sub

#End Region

Private Sub Form1_Load(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles MyBase.Load

End Sub

Private Sub MenuItem2_Click(ByVal sender As Object,
ByVal e As System.EventArgs) Handles MenuItem2.Click
MessageBox.Show("icon clicked", "menu icon",
MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
End Class


Shawn Burke [MSFT]

unread,
Mar 1, 2002, 1:25:42 PM3/1/02
to
Which line of code is throwing the exception? Go to debug >> exceptions..
>> Common Language Runtime Exceptions, and in the bottom box that says "When
Exceptions are Thrown", set "Break". This should stop on the problematic
line of code. Maybe that will give you a clue as to what the problem is, if
not, post back. GDI+ throws OutOfMemoryExceptions a little too liberally
(they don't always mean OutOfMemory...)

--

This posting is provided "AS IS" with no warranties, and confers no rights.
You assume all risk for your use. © 2001 Microsoft Corporation. All rights
reserved.


"steve percival" <steve.p...@corpoflondon.gov.uk> wrote in message
news:a19e01c1c135$129b7550$9ae62ecf@tkmsftngxa02...

steve percival

unread,
Mar 4, 2002, 4:34:17 AM3/4/02
to
Shawn,
I have tried what you suggested but it did not make a
difference I could not find which line caused the error.

I also did a bit of playing around with the code and found
that the following scenario caused the problem.

in the IconMenuItem classes method ondrawitem put the
following lines of code.

dim a as integer =0
a = 32/a

this will cause an exception. now remove the lines of
code. and re run the program the out of memory exception
in System.Drawing.dll will appear. the only thing that
will cure it is a reboot. Also the above will also screw
up context menus on the desktop. (This was tested using a
win2000 pro)

Could this be a bug is the Framework?

Steve.

>> IconMenuItem

>> InitialiÍ{ wð!h ,_¶ zeComponent() call

Shawn Burke [MSFT]

unread,
Mar 4, 2002, 5:43:35 PM3/4/02
to
Hi Steve --

Good debugging...that helped a lot. You are correct with your diagnosis;
the exception being thrown (in this case DivideByZeroException, but it
doesn't matter) is the core problem here. Doing so does break context menus
in the Windows Shell (ouch! I'll follow up on that one to see if we can't
stop that from happening...).

The OutOfMemoryException you're seeing seems to only occur after those
steps. When I fire up your code from the previous posting, it works great.
If I then throw the exceptoin from the MenuItem.DrawItem event, Windows is
now in a pretty unhappy state and GDI+ fails to get a hold of a drawing
surface and you get the results you're seeing.

Shawn

--

This posting is provided "AS IS" with no warranties, and confers no rights.
You assume all risk for your use. © 2001 Microsoft Corporation. All rights
reserved.


"steve percival" <steve.p...@corpoflondon.gov.uk> wrote in message

news:ac4b01c1c35f$c1898850$9ae62ecf@tkmsftngxa02...

0 new messages