Ringowrote:
[...]
Then nothing ever draws. What am I missing.
Is this the correct way to do it, or was I closer the first time with
Draw_sonar2?
Well, what is "m_objDrawingSurface"?
Based on the "before" code, it seems to be some sort of Image object
(Bitmap, Metafile, whatever). It seems to me that the original code was
not actually all that bad. The one obvious thing I see is that you
should not need to erase the background in the Paint handler. The
control will get a separate event to do that. (But you do need to erase
the background in your image object, of course).
But other than that, the original code is actually more efficient,
because you draw once into some cached image object, and use that to
update the control whenever it actually needs updating. This way you
only update the image object when the data changes, and otherwise if the
control needs redrawing for some reason other than that (overlapping
windows being moved, for example) all you have to do is copy the image
that's already been drawn.
However, if you really want to fix the "after" code, you're going to
need to draw to the Graphics object in the event rather than the
"m_objDrawingSurface" object. If you do it that way, you should just
get rid of the "m_objDrawingSurface" altogether. There's no need to
have it if you are going to redraw everything every time the control
needs updating. (Getting rid of that object will also eliminate the bug
you have where you get a Graphics object from the "m_objDrawingSurface"
twice
).
Pete
Thanks Pete,
Here is the definition
private System.Drawing.Bitmap m_objDrawingSurface;
I commented out the line that erases the background, still get the
error.
Here is the exact error
"System.InvalidOperationException was unhandled
Message="Object is currently in use elsewhere."
Source="System.Drawing"
StackTrace:
at System.Drawing.Image.get_Width()
at EzExpander.Form1.DrawSonar2() in C:\Documents and Settings
\Ringo\My Documents\thumb\fw\sonarWizard\work\v1.0.0\SonarWizardApp
\SonarWizard\Form1.cs:line 94
at EzExpander.Form1.sp_DataReceived(Object sender,
SerialDataReceivedEventArgs e) in C:\Documents and Settings\Ringo\My
Documents\thumb\fw\sonarWizard\work\v1.0.0\SonarWizardApp\SonarWizard
\Form1.cs:line 283
at System.IO.Ports.SerialPort.CatchReceivedEvents(Object src,
SerialDataReceivedEventArgs e)
at
System.IO.Ports.SerialStream.EventLoopRunner.CallReceiveEvents(Object
state)
at
System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object
state)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at
System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object
state)
"
Is this saying that line 94 and 283 are conflicting?
94 is in Draw_sonar2 and 283 is calling Draw_sonar2. Is it a case
where a function is getting called again before it is finished?
Any ideas on how to fix it. It happens every few minutes, not all the
time.
Here is all the code from the form. I'll put the line numbers next to
those 2 lines.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace EzExpander
{
public partial class Form1 : Form
{
private System.Drawing.Bitmap m_objDrawingSurface;
SensorStruct SA = new SensorStruct();
TextBox[] Sonar = new TextBox[10];
Label[] SonarNum = new Label[10];
int robotDiameter = 50;
public Form1()
{
InitializeComponent();
}
private void button_test_Click(object sender, EventArgs e)
{
Graphics objGraphics;
Rectangle rectBounds;
int robotDiameter=50;
//int BeamWidth = 15;//degrees
//double Range = 100;//cm
int startX, startY;//, endX, endY;
//int angle=270;
//int xx, yy;
startX = m_objDrawingSurface.Width / 2 ;
startY = m_objDrawingSurface.Height - robotDiameter;
objGraphics = Graphics.FromImage(m_objDrawingSurface);
objGraphics.Clear(SystemColors.Control);
//draw robot
rectBounds = new Rectangle((m_objDrawingSurface.Width / 2)
- (robotDiameter/2), m_objDrawingSurface.Height- (robotDiameter),
robotDiameter,robotDiameter);
rectBounds.Inflate(-1, -1);
objGraphics.DrawEllipse(Pens.Orange, rectBounds);
for (int i = 0; i <= 9; i++)
{
SA.Range
= 100*int.Parse(textBox_scale.Text);
}
for (int i = 0; i <= 9; i++)
{
DrawSonar(SA.sensorAngle,SA.sensorBeamWidth,SA.Range);
Sonar.Text = SA.Range.ToString();
}
objGraphics.Dispose();
PB.Refresh();
}
private void DrawSonar(int Angle, int BeamWidth, double Range)
{
Graphics objGraphics;
// Rectangle rectBounds;
int startX, startY, endX, endY;
int angle;
startX = m_objDrawingSurface.Width / 2;
startY = m_objDrawingSurface.Height - robotDiameter/2;
objGraphics = Graphics.FromImage(m_objDrawingSurface);
for (int x = 0; x <= 9; x++)
{
if (Range <= int.Parse(textBox_maxRange.Text))
for (angle = (Angle - (BeamWidth / 2)); angle < (Angle
+ (BeamWidth / 2)); angle += 2)
{
endX = startX + (int)(Range * Math.Cos(angle *
6.28 / 360));
endY = startY + (int)(Range * Math.Sin(angle *
6.28 / 360));
objGraphics.DrawLine(Pens.Green, startX, startY,
endX, endY);
}
}
objGraphics.Dispose();
PB.Refresh();
PB.Invalidate();
}
private void DrawSonar2()
{
Graphics objGraphics;
objGraphics = Graphics.FromImage(m_objDrawingSurface);
objGraphics.Clear(SystemColors.Control);
int startX, startY, endX, endY;
int angle;
startX = m_objDrawingSurface.Width / 2; //line 94
startY = m_objDrawingSurface.Height - robotDiameter/2;
for (int x = 0; x <= 9; x++)
{
int Angle = SA.sensorAngle[x];
int BeamWidth = SA.sensorBeamWidth[x];
int Range = SA.Range[x]*int.Parse(textBox_scale.Text);
if (Range > int.Parse(textBox_maxRange.Text) *
int.Parse(textBox_scale.Text))
Range = int.Parse(textBox_maxRange.Text) *
int.Parse(textBox_scale.Text);
for (angle = (Angle - (BeamWidth / 2)); angle < (Angle
+ (BeamWidth / 2)); angle += 2)
{
endX = startX + (int)(Range * Math.Cos(angle *
6.28 / 360));
endY = startY + (int)(Range * Math.Sin(angle *
6.28 / 360));
objGraphics.DrawLine(Pens.Green, startX, startY,
endX, endY);
}
}
objGraphics.Dispose();
PB.Invalidate();
}
private void PB_Paint(object sender, PaintEventArgs e)
{
/////////////////////////////////
Graphics objGraphics;
objGraphics = e.Graphics;
// objGraphics.Clear(SystemColors.Control);
objGraphics.DrawImage(m_objDrawingSurface, 0, 0,
m_objDrawingSurface.Width, m_objDrawingSurface.Height);
// objGraphics.Dispose();
}
private void InitializeSurface()
{
Graphics objGraphics;
Rectangle rectBounds;
objGraphics = Graphics.FromImage(m_objDrawingSurface);
objGraphics.Clear(SystemColors.Control);
rectBounds = new Rectangle(0, 0,
m_objDrawingSurface.Width, m_objDrawingSurface.Height);
rectBounds.Inflate(-1, -1);
//objGraphics.DrawEllipse(Pens.Orange, rectBounds);
objGraphics.Dispose();
}
private void Form1_Load(object sender, EventArgs e)
{
SA.Range = new int[16];
SA.sensorAngle = new int[16];
SA.sensorBeamWidth = new int[16];
SA.sensortype = new int[16];
initialize_Sensors();
m_objDrawingSurface = new
Bitmap(PB.Width,PB.Height,System.Drawing.Imaging.PixelFormat.Format24bppRgb);
InitializeSurface();
sp.BaudRate = 19200;
// sp.PortName = "COM44";
sp.DataBits = 8;
sp.StopBits = System.IO.Ports.StopBits.One;
sp.Parity = System.IO.Ports.Parity.None;
sp.Encoding = Encoding.ASCII;
sp.DataReceived += new
System.IO.Ports.SerialDataReceivedEventHandler(sp_DataReceived);
string[] ports =
System.IO.Ports.SerialPort.GetPortNames();// sp.GetPortNames();
Console.WriteLine("The following serial ports were
found:");
foreach (string port in ports)
{
comboBox1.Items.Add(port);
Console.WriteLine(port);
comboBox1.Text = port;
}
}
public void initialize_Sensors()
{
int x;
for (x = 0; x <= 9; x++)
{
SA.sensorBeamWidth[x] = 15;
SA.sensorAngle[x] = 360-(x * 20);
SA.sensortype[x] = 1;//sonar
SA.Range[x] = 0;
Sonar[x] = new TextBox();
Sonar[x].Visible = true;
this.Controls.Add(Sonar[x]);
Sonar[x].Left = 587;
Sonar[x].Top = 165+(x * 25);
Sonar[x].Width = 50;
SonarNum[x] = new Label();
SonarNum[x].Visible = true;
this.Controls.Add(SonarNum[x]);
SonarNum[x].Left = 537;
SonarNum[x].Top = 165 + (x * 25);
SonarNum[x].Width = 50;
SonarNum[x].Text = "sonar" + x;
this.Visible = true;
}
for (x = 10; x <= 15; x++)
{
SA.sensorBeamWidth[x] = 3;
SA.sensorAngle[x] = 360-(x * 20);
SA.sensortype[x] = 2;//IR
SA.Range[x] = 0;
}
}
void sp_DataReceived(object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)
{
//received data looks like this
//0 159 1 154 2 156 3 159 4 152 5 159 6 155 7 155 8 151 9
153
// sensor_number range Sensor_number range....
string Mystring=sp.ReadLine();
int l = Mystring.Length;
Console.WriteLine("Received:{0} bytes {1}", l,Mystring);
int r=0;
int SensorNumber = 0;
int lowvalue=0;
int highvalue = 0;
int combinedvalue=0;
if (l >= 1)
{
if (radioButtonDirectConnect.Checked == true)
{
// line contains ten values, looks like this
// 16 34 0 69 45 15 7 6 5 6
// Console.WriteLine("direct connect");
SensorNumber = 0;
Mystring = Mystring.Trim();
// Mystring = Mystring.Replace('>', ' ');
string[] ranges = Mystring.Split(' ');
foreach (string range in ranges)
{
try
{
r = Convert.ToInt16(range);
// Console.WriteLine("Range: {0}", r);
SA.Range[SensorNumber] = r;
SensorNumber++;
}
catch(System.FormatException)
{
}
finally
{
}
}
} // end of direct connect
else //I2C
{
// line contains 20 8-bit values, Need to be
turned into 10 16bit
SensorNumber = 0;
Mystring = Mystring.Trim();
string[] ranges = Mystring.Split(' ');
for (int x = 0; x < ranges.Length; x += 2)
{
try
{
lowvalue = Convert.ToInt16(ranges[x]);
highvalue = Convert.ToInt16(ranges[x + 1]);
combinedvalue = ((highvalue * 255) +
lowvalue);
Console.WriteLine("Range: {0}",
combinedvalue);
SA.Range[SensorNumber] = combinedvalue;
SensorNumber++;
}
catch (System.FormatException)
{
}
finally
{
}
}
}
}
DrawSonar2(); //line 283
// PB.Invalidate();
}
private void PB_Click(object sender, EventArgs e)
{
}
private void button_stream_Click(object sender, EventArgs e)
{
// sp.Write("fw\r");
//sp.Write("f");
//System.Threading.Thread.Sleep(1);
//sp.Write("w");
//System.Threading.Thread.Sleep(1);
//sp.Write("\r");
//System.Threading.Thread.Sleep(2000);
sp.Write("streams\r");
//int delaytime = 10;
//sp.Write("s");
//System.Threading.Thread.Sleep(delaytime);
//sp.Write("t");
//System.Threading.Thread.Sleep(delaytime);
//sp.Write("r");
//System.Threading.Thread.Sleep(delaytime);
//sp.Write("e");
//System.Threading.Thread.Sleep(delaytime);
//sp.Write("a");
//System.Threading.Thread.Sleep(delaytime);
//sp.Write("m");
//System.Threading.Thread.Sleep(delaytime);
//sp.Write("s");
//System.Threading.Thread.Sleep(delaytime);
//sp.Write("\r");
}
private void timer1_Tick(object sender, EventArgs e)
{
for (int i = 0; i <= 9; i++)
Sonar.Text = SA.Range.ToString();
}
private void button_open_serial_port_Click(object sender,
EventArgs e)
{
sp.PortName = comboBox1.Text;
// sp.ReadTimeout = 0;
sp.Open();
}
private void vScrollBar1_Scroll(object sender, ScrollEventArgs
e)
{
textBox_scale.Text = vScrollBar1.Value.ToString();
}
private void radioButtonI2C_serializer_CheckedChanged(object
sender, EventArgs e)
{
}
private void button_readI2C_Click(object sender, EventArgs e)
{
sp.WriteLine("i2c r 100 20\r");
}
private void button_reset_Click(object sender, EventArgs e)
{
sp.Write("reset\r");
}
private void button_stop_Click(object sender, EventArgs e)
{
sp.Write("stop\r");
}
private void button_send_delay_Click(object sender, EventArgs
e)
{
sp.Write("delay " + tb_delay.Text + "\r");
}
}
}