A form with a panel and boxes drawn on, the user clicks a box and a label appears for a moment to say "box hit".
I have a working version of the code but I tried to rearrange it to experiment with making it more efficient, and I find I am currently getting this exception.
I do not understand why this exception is occurring, and I would like to be able to troubleshoot it but I don't know how to do that either. I have narrowed it down to what line it is. But beyond that I don't know.
The error occurs when a box is clicked.. So the panel's mousedown is executed.
All the controls e.g. panel, label, are programmatically generated, such that it should hopefully be possible for anybody to copy/paste the code change the classname and reproduce the exception that I get.
I have read online that the pen might generate an outofmemoryexception even when it's not really out of memory, but it's just throwing that exception, though that still doesn't tell me why or how it can be avoided, so that I can understand how to write code where the pen doesn't throw that exception.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace WindowsFormsApplication17
{
public partial class Form1 : Form
{
Label lbl1;
Panel panel;
Timer timer1;
Point[][] points = new Point[9][];
GraphicsPath[] gps = new GraphicsPath[9];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
panel = new Panel();
lbl1 = new Label();
timer1 = new Timer();
this.Controls.Add(panel);
Label alias = lbl1;
alias.Text = "box clicked";
alias.Visible = false;
panel.BackgroundImageLayout = ImageLayout.Stretch;
this.Height = 500; this.Width = 500;
panel.Controls.Add(lbl1);
panel.MouseDown += p_MouseDown;
timer1.Tick += timer1_Tick;
panel.BackColor = Color.White;
panel.Height = 400;
panel.Width = 400;
for (int i = 0; i < 9; i++) points[i] = new Point[4];
points[0][0] = new Point(19, 262);
points[0][1] = new Point(28, 257);
points[0][2] = new Point(27, 284);
points[0][3] = new Point(16, 285);
points[1][0] = new Point(52, 253);
points[1][1] = new Point(62, 250);
points[1][2] = new Point(61, 277);
points[1][3] = new Point(49, 278);
points[2][0] = new Point(87, 249);
points[2][1] = new Point(100, 248);
points[2][2] = new Point(99, 275);
points[2][3] = new Point(86, 274);
points[3][0] = new Point(126, 250);
points[3][1] = new Point(140, 252);
points[3][2] = new Point(139, 279);
points[3][3] = new Point(126, 277);
points[4][0] = new Point(164, 257);
points[4][1] = new Point(175, 260);
points[4][2] = new Point(175, 287);
points[4][3] = new Point(164, 284);
points[5][0] = new Point(197, 265);
points[5][1] = new Point(209, 269);
points[5][2] = new Point(209, 295);
points[5][3] = new Point(198, 292);
points[6][0] = new Point(228, 273);
points[6][1] = new Point(241, 275);
points[6][2] = new Point(240, 300);
points[6][3] = new Point(229, 300);
points[7][0] = new Point(262, 274);
points[7][1] = new Point(274, 273);
points[7][2] = new Point(275, 300);
points[7][3] = new Point(262, 301);
points[8][0] = new Point(297, 272);
points[8][1] = new Point(308, 268);
points[8][2] = new Point(311, 295);
points[8][3] = new Point(298, 296);
panel.Paint += thepanel_Paint;
// I can see that I can remove all the braces, but anyhow.
for (int i = 0; i < 9; i++)
{
using (gps[i] = new GraphicsPath())
using (Pen pen = new Pen(Color.Black, 1)) //this pen is not for drawing. but for the logic re graphicspath
{
gps[i].AddPolygon(points[i]);
}
}
}
void p_MouseDown(object sender, EventArgs e)
{
MouseEventArgs mea = (MouseEventArgs)e;
//GraphicsPath[] gps = new GraphicsPath[9];
bool boxhit = false;
for (int i = 0; i < 9; i++)
{
using (Pen pen = new Pen(Color.Black, 1)) //this pen is not for drawing. but for the logic re graphicspath
{
bool cond1=false;
bool cond2=false;
cond1 = gps[i].IsOutlineVisible(new Point(mea.X, mea.Y), pen);
cond2 = gps[i].IsVisible(new Point(mea.X, mea.Y));
if (cond1 == true ||
cond2 == true)
{
boxhit = true;
lbl1.Visible = true;
timer1.Enabled = true;
}
}
} //for
// if (boxhit == false) MessageBox.Show("no box hit");
}
private void timer1_Tick(object sender, EventArgs e)
{
lbl1.Visible = false; timer1.Enabled = false;
}
private void thepanel_Paint(object sender, PaintEventArgs e)
{
GraphicsPath[] gps = new GraphicsPath[9];
Graphics gg = panel.CreateGraphics();
for (int i = 0; i < 9; i++)
using (gps[i] = new GraphicsPath())
{
gps[i].AddPolygon(points[i]);
gg.DrawPath(new Pen(Color.Blue, 1), gps[i]);
}
}
}
}
As a side note, here is the code prior to rearrangement, where it works, it doesn't throw an exception (though it's perhaps inefficient in that every mousedown it adds polygons to determine which is clicked, when really that only needs to be done once).
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace WindowsFormsApplication15
{
public partial class Form1 : Form
{
Label lbl1;
Panel panel;
Timer timer1;
Point[][] points = new Point[9][];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
panel = new Panel();
lbl1 = new Label();
timer1 = new Timer();
this.Controls.Add(panel);
Label alias = lbl1;
alias.Text = "box clicked";
alias.Visible = false;
panel.BackgroundImageLayout = ImageLayout.Stretch;
this.Height = 500; this.Width = 500;
panel.Controls.Add(lbl1);
panel.MouseDown += p_MouseDown;
timer1.Tick += timer1_Tick;
panel.BackColor = Color.White;
panel.Height = 400;
panel.Width = 400;
for (int i = 0; i < 9; i++) points[i] = new Point[4];
points[0][0] = new Point(19, 262); //left top
points[0][1] = new Point(28, 257); //right top
points[0][2] = new Point(27, 284); //right bottom
points[0][3] = new Point(16, 285); //left bottom
points[1][0] = new Point(52, 253);
points[1][1] = new Point(62, 250);
points[1][3] = new Point(49, 278);
points[1][2] = new Point(61, 277);
points[2][0] = new Point(87, 249);
points[2][1] = new Point(100, 248);
points[2][3] = new Point(86, 274);
points[2][2] = new Point(99, 275);
points[3][0] = new Point(126, 250);
points[3][1] = new Point(140, 252);
points[3][3] = new Point(126, 277);
points[3][2] = new Point(139, 279);
points[4][0] = new Point(164, 257);
points[4][1] = new Point(175, 260);
points[4][3] = new Point(164, 284);
points[4][2] = new Point(175, 287);
points[5][0] = new Point(197, 265);
points[5][1] = new Point(209, 269);
points[5][3] = new Point(198, 292);
points[5][2] = new Point(209, 295);
points[6][0] = new Point(228, 273);
points[6][1] = new Point(241, 275);
points[6][3] = new Point(229, 300);
points[6][2] = new Point(240, 300);
points[7][0] = new Point(262, 274);
points[7][1] = new Point(274, 273);
points[7][3] = new Point(262, 301);
points[7][2] = new Point(275, 300);
points[8][0] = new Point(297, 272);
points[8][1] = new Point(308, 268);
points[8][3] = new Point(298, 296);
points[8][2] = new Point(311, 295);
panel.Paint += thepanel_Paint;
}
void p_MouseDown(object sender, EventArgs e)
{
MouseEventArgs mea = (MouseEventArgs)e;
GraphicsPath[] gps = new GraphicsPath[9];
bool boxhit = false;
for (int i = 0; i < 9; i++)
{
using (gps[i] = new GraphicsPath())
using (Pen pen = new Pen(Color.Black,1)) //this pen is not for drawing. but for the logic re graphicspath
{
gps[i].AddPolygon(points[i]);
if (gps[i].IsOutlineVisible(new Point(mea.X, mea.Y), pen) == true || gps[i].IsVisible(new Point(mea.X, mea.Y)))
{
boxhit = true;
lbl1.Visible = true;
timer1.Enabled = true;
}
}
} //for
// if (boxhit == false) MessageBox.Show("no box hit");
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
lbl1.Visible = false; timer1.Enabled = false;
}
private void thepanel_Paint(object sender, PaintEventArgs e)
{
GraphicsPath[] gps = new GraphicsPath[9];
Graphics gg = panel.CreateGraphics();
for (int i = 0; i < 9; i++)
using (gps[i] = new GraphicsPath())
{
gps[i].AddPolygon(points[i]);
gg.DrawPath(new Pen(Color.Blue, 1), gps[i]);
}
}
}
}
Added
In reply to Hans's comment.
I see I missed a using
there for that graphics object in the panel paint procedure. But if I add it, so, with this code.
using(Graphics gg = panel.CreateGraphics())
for (int i = 0; i < 9; i++)
using (gps[i] = new GraphicsPath())
{
gps[i].AddPolygon(points[i]);
gg.DrawPath(new Pen(Color.Black, 1), gps[i]);
}
I still get the same exception on the cond1 = gps[i].IsOutlineVisible(new Point(mea.X, mea.Y), pen);
line in the p_MouseDown
procedure.
Added further
the Q is answered, but a further weird thing.. I tried to create a simple program that gives the same exception, but the program didn't crash or run correctly so maybe whether a runtime error occurs or not isn't that clearly predicatable. Here i'd expect an outofmemoryexception, or at least two messageboxes not just one, and I get no exception and just one messagebox.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace blah
{
public partial class Form1 : Form
{
Pen p;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
MessageBox.Show("sadf"); //displays
MessageBox.Show(p.Color.ToString()); // doesn't display a messagebox at all!
}
}
}