How to run procedure with parameters in another thread using C#? - c#

I am stuck at trying to call a procedure and use some parameters in a new thread in C#. There is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Random_colored_rectangles
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Thread th;
Random rand;
System.Drawing.Color[] colors = new System.Drawing.Color[5] {Color.Orange, Color.Red, Color.Pink, Color.Black, Color.Gold };
private void DrawColor(Color color)
{
for (int i = 0; i < 100; i++)
{
DrawRectangle(color, 3 , rand.Next(0, this.Width), rand.Next(0, this.Height), 10, 10);
Thread.Sleep(100);
}
MessageBox.Show(color + " done");
}
private void DrawRectangle(Color barva, float width, int pos_x, int pos_y, int size_x, int size_y)
{
Pen myPen = new Pen(barva, width);
Graphics formGraphics;
formGraphics = plocha.CreateGraphics();
formGraphics.DrawRectangle(myPen, new Rectangle(pos_x, pos_y, size_x, size_y));
myPen.Dispose();
formGraphics.Dispose();
}
private void Form1_Load(object sender, EventArgs e)
{
rand = new Random();
}
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.R)
{
th = new Thread(DrawColor);
th.Name = Convert.ToString(threadCount);
threadList.Add(th);
threadCount = threadCount + 1;
th.Start(colors[rand.Next(0, colors.Length)]);
}
}
}
}
This code should (after pressing R) make 100 random colored rectangles (the color is chosen from an array of few colors). But, I am unable to make my thread start the procedure DrawColor with a parameter of the random color select.
Can you please help me?

You could do it by using a Task.
Color theColorToPass = someColor;
Task.Factory.StartNew(color => {
DrawColor(color);
}, theColorToPass);
You could aswell access the array directly from within the Task though. I see no point in passing it to the Thread.

Using the advice of those more familiar with the do's and don'ts of C# (that is not me trying to sound mean or anything), I have devised a way to accomplish what you want without the need of CreateGraphics() or Thread.Sleep(). Unfortunately, this throws an OutOfMemoryException when it hits e.Graphics.DrawRectangle(penToUse, rectanglesToUse[0]);. What does that mean?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace Colors
{
public partial class Form1 : Form
{
Timer timer = new Timer { Interval = 100 };
Random rand = new Random();
Color[] colors = new Color[5]
{
Color.Black,
Color.Blue,
Color.Green,
Color.Purple,
Color.Red
};
List<Pen> usedPens = new List<Pen>();
List<Rectangle> usedRectangles = new List<Rectangle>();
Pen penToUse;
List<Rectangle> rectanglesToUse = new List<Rectangle>();
public Form1()
{
InitializeComponent();
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
penToUse = new Pen(GetRandomColor(), 3);
rectanglesToUse.Clear();
for (int i = 0; i < 100; i++)
rectanglesToUse.Add(GetRandomRectangle());
this.Refresh();
}
}
private Color GetRandomColor()
{
return colors[rand.Next(0, colors.Length)];
}
private Rectangle GetRandomRectangle()
{
return new Rectangle(rand.Next(0, Width), rand.Next(0, Height), 10, 10);
}
protected override void OnPaint(PaintEventArgs e)
{
for (int i = 0; i < usedRectangles.Count; i++)
e.Graphics.DrawRectangle(usedPens[i % 100], usedRectangles[i]);
timer.Tick += delegate
{
if (rectanglesToUse.Count > 0)
{
e.Graphics.DrawRectangle(penToUse, rectanglesToUse[0]);
usedRectangles.Add(rectanglesToUse[0]);
rectanglesToUse.RemoveAt(0);
}
else
{
usedPens.Add(penToUse);
timer.Stop();
}
};
timer.Start();
}
}
}

Related

How to get the difference from two images in c#

I'm just trying to get the difference between a live and a few sec delayed webcam image of my webcam, with AForge, to make a basic motion detection. But I got nothing, as result. How can I copy the image to be sure that is well processed? I want to present the difference-image and some percentage of the difference.
My code:
private void VideoCaptureDevice_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
if (justStarted == 1)
{
justStarted = 0;
picOld.Image = (Bitmap)eventArgs.Frame.Clone();
}
else
{
if (DateTime.Now.Second >= lastTime.Second + dTime)
{
picNew.Image = picOld.Image;
lastTime = DateTime.Now;
Bitmap tmp1 = new Bitmap(picNew.Image);
Bitmap tmp2 = new Bitmap(picOld.Image);
getTheDiff(tmp1, tmp2);
}
picOld.Image = (Bitmap)eventArgs.Frame.Clone();
}
}
private Thread thread2 = null;
private float inPercentage;
private void getTheDiff(Bitmap picold, Bitmap picnew)
{
Bitmap bm = new Bitmap(280, 110);
float diff = 0;
float tmpDiff = 0;
Bitmap img1 = new Bitmap(picold);
Bitmap img2 = new Bitmap(picnew);
Bitmap difference = new Bitmap(img1.Width, img1.Height);
for (int y = 0; y < img1.Height; y++)
{
for (int x = 0; x < img1.Width; x++)
{
Color pixel1 = img1.GetPixel(x, y);
Color pixel2 = img2.GetPixel(x, y);
tmpDiff += Math.Abs(pixel1.R - pixel2.R);
tmpDiff += Math.Abs(pixel1.G - pixel2.G);
tmpDiff += Math.Abs(pixel1.B - pixel2.B);
diff = tmpDiff;
if (tmpDiff > 0)
difference.SetPixel(x, y, pixel2);
}
}
inPercentage = diff; //100 * (diff / 255) / (img1.Width * img1.Height * 3);
thread2 = new Thread(new ThreadStart(SetText)); //write out the percentage
thread2.Start();
Thread.Sleep(100);
picDiff.Image = new Bitmap(difference); //present the differenece image
Console.WriteLine(diff);
}
I'm a newbie in image processing, so please forgive me if some basic stuff...
UPDATE
This is my whole code
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 AForge.Video;
using AForge.Video.DirectShow;
using AForge.Imaging.Filters;
using System.Drawing;
using System.Drawing.Imaging;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Text.RegularExpressions;
using AForge.Video;
using System.Diagnostics;
using AForge.Video.DirectShow;
using System.Collections;
using System.IO;
using System.Drawing.Imaging;
using System.IO.Ports;
using System.Globalization;
using System.Net;
namespace WebcamApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
filterInfoCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo filterInfo in filterInfoCollection)
cboCamera.Items.Add(filterInfo.Name);
cboCamera.SelectedIndex = 0;
videoCaptureDevice = new VideoCaptureDevice();
}
FilterInfoCollection filterInfoCollection;
VideoCaptureDevice videoCaptureDevice;
private int dTime = 0;
private DateTime lastTime;
private int justStarted = 0;
private void btnStart_Click(object sender, EventArgs e)
{
if (videoCaptureDevice.IsRunning == true)
{
videoCaptureDevice.Stop();
}
else
{
dTime = Convert.ToInt32(time.Text);
lastTime = DateTime.Now;
justStarted = 1;
videoCaptureDevice = new VideoCaptureDevice(filterInfoCollection[cboCamera.SelectedIndex].MonikerString);
videoCaptureDevice.NewFrame += VideoCaptureDevice_NewFrame;
System.Threading.Thread.Sleep(dTime);
videoCaptureDevice.Start();
}
}
private void VideoCaptureDevice_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
if (justStarted == 1)
{
justStarted = 0;
picOld.Image = (Bitmap)eventArgs.Frame.Clone();
}
else
{
if (DateTime.Now.Second >= lastTime.Second + dTime)
{
picNew.Image = picOld.Image;
lastTime = DateTime.Now;
Bitmap tmp1 = new Bitmap(picNew.Image);//sometimes buggy here...
Bitmap tmp2 = new Bitmap(picOld.Image);
compare(tmp1, tmp2);
}
picOld.Image = (Bitmap)eventArgs.Frame.Clone();
}
}
private Thread thread2 = null;
private float inPercentage;
private void compare(Bitmap picold, Bitmap picnew)
{
Bitmap bm = new Bitmap(280, 110);
float diff = 0;
Bitmap img1 = new Bitmap(picold);
Bitmap img2 = new Bitmap(picnew);
Bitmap difference = new Bitmap(img1.Width, img1.Height);
for (int y = 0; y < img1.Height; y++)
{
for (int x = 0; x < img1.Width; x++)
{
Color pixel1 = img1.GetPixel(x, y);
Color pixel2 = img2.GetPixel(x, y);
float tmpDiff = Math.Abs(pixel1.R - pixel2.R);
tmpDiff += Math.Abs(pixel1.G - pixel2.G);
tmpDiff += Math.Abs(pixel1.B - pixel2.B);
diff += tmpDiff;
if (tmpDiff > 0)
difference.SetPixel(x, y, pixel2);
}
}
inPercentage = diff; //100 * (diff / 255) / (img1.Width * img1.Height * 3);
thread2 = new Thread(new ThreadStart(SetText));
thread2.Start();
Thread.Sleep(100);
picDiff.Image = new Bitmap(difference);
Console.WriteLine(diff);
}
private delegate void SafeCallDelegate(string text);
private void SetText()
{
WriteTextSafe(inPercentage + "%");
}
private void WriteTextSafe(string text)
{
if (textBoxDifference.InvokeRequired)
{
var d = new SafeCallDelegate(WriteTextSafe);
textBoxDifference.Invoke(d, new object[] { text });
}
else
{
textBoxDifference.Text = text;
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (videoCaptureDevice.IsRunning == true)
videoCaptureDevice.Stop();
}
private void cboCamera_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void label1_Click_1(object sender, EventArgs e)
{
}
public void button1_Click(object sender, EventArgs e)
{
}
}
}

Program not drawing graphics

I've been following the instructions for an assignment and I can't see any issues with the code (no error messages and the program runs without crashing), but the program does not draw the graphics. It's supposed to random out 200 random numbers between 1-100, and then sort them into a graph with a bubble sort
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 WindowsFormsApp6
{
public partial class Form1 : Form
{
int[] number = new int[200];
Random generator = new Random();
public Form1()
{
InitializeComponent();
}
private void btnGenerate_Click(object sender, EventArgs e)
{
for (int i = 0; i < number.Length; i++)
{
number[i] = generator.Next(1, 101);
}
Invalidate();
}
private void btnSort_Click(object sender, EventArgs e)
{
BubbleSort(number);
Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
//Assigns origo
Point origo = new Point(40,150);
//Draw x and y axes
e.Graphics.DrawLine(Pens.Black, origo.X, origo.Y, origo.X, origo.Y - 100);
e.Graphics.DrawLine(Pens.Black, origo.X, origo.Y, origo.X + 200, origo.Y);
//Draw all points
for(int i = 0; i < number.Length; i++)
{
e.Graphics.FillEllipse(Brushes.Red, origo.X + i, origo.Y - number[i], 2, 2);
}
}
public void BubbleSort(int[] list)
{
for (int m = list.Length - 1; m > 0; m--)
{
for (int n = 0; n < m; n++)
{
if (list[n] > list[n + 1])
{
int temp = list[n];
list[n] = list[n + 1];
list[n + 1] = temp;
}
}
}
}
}
}
The program should draw 200 points when you press the button "Generate" and then sort them into a line/graph when you press "Sort", but the program isn't drawing anything when I press the buttons.

Real-time draw.lines using serial port data

I want my simple program to take X and Y coordinates from serial port and draw them in window (like paint but with other device than mouse).
I managed to create code that recive and transforms data however I can't handle drawing that data on form.
Program works until Form1 window shows up. Then i recieve only "data_recived" and data value in console but rest of the datarecived event don't execute.
I know it is something wrong with DataReceivedHandler but i tried so many solution and none of them worked. (in comments you can see my attempts to use timer trigerred event to do that).
Could anyone give me at least some tips how to solve my problem? I would be really grateful
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO.Ports;
using System.Threading;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public string data;
private List<Point> points;
private Bitmap bmp;
private Pen pen;
private PictureBox pictureBox1 = new PictureBox();
//private System.Timers.Timer _timer;
//private DateTime _startTime;
public Form1()
{
InitializeComponent();
SerialPort serialPort1 = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
serialPort1.Open();
serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
DoubleBuffered = true;
pen = new Pen(Color.Black, 3);
points = new List<Point>();
// _startTime = DateTime.Now;
// _timer = new System.Timers.Timer(100); // 0.1 s
// _timer.Elapsed += new System.Timers.ElapsedEventHandler (timer_Elapsed);
// _timer.Start();
// Console.WriteLine("Czas Start");
}
public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort serialPort1 = (SerialPort)sender;
Console.WriteLine("data_recived");
data = serialPort1.ReadLine();
Console.WriteLine(data);
pointlist_reciver();
}
// void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
//{
// Console.WriteLine("Czas");
// TimeSpan timeSinceStart = DateTime.Now - _startTime;
//string output = string.Format("{0},{1}\r\n", DateTime.Now.ToLongDateString(), (int)Math.Floor(timeSinceStart.TotalMinutes));
// pointlist_reciver();
// }
public void pointlist_reciver()
{
int x1;
int y1;
points = new List<Point>();
string[] coordinates = new string[2];
coordinates = data.Split(',');
string x = coordinates[0];
string y = coordinates[1];
Int32.TryParse(x, out x1);
Int32.TryParse(y, out y1);
points.Add(new Point(x1, y1));
if (points.Count >= 2)
{
this.Paint += new PaintEventHandler(Form1_Paint);
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
PaintP(e);
}
public void PaintP ( PaintEventArgs e)
{
bmp = new Bitmap(1500, 1500);
using (Graphics g = Graphics.FromImage(bmp))
g.Clear(Color.White);
e.Graphics.DrawLines(pen, points.ToArray());
points.Clear();
}
}
}
points.Count >= 2
would never happen
this.Paint += new PaintEventHandler(Form1_Paint)
this does not make sense here, you need to register it only once on form load. What you are looking for is Invalidate(). Just beware you may be on different thread, so may need to Invoke first.
bmp = new Bitmap(1500, 1500);
using (Graphics g = Graphics.FromImage(bmp))
g.Clear(Color.White);
e.Graphics.DrawLines(pen, points.ToArray());
points.Clear();
you create bitmap you do not even use. Not sure what exactly you are trying to achieve here.
Example
You have two options. Either you draw on bitmap and paste that bitmap on the form. Or you just draw on the form. I made a simple example how to use the latter option. When you move mouse on the form it draws points. Just register the eventhandlers - Load, MouseMove, Paint.
List<Point> points = new List<Point>();
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
points.Add(e.Location);
Invalidate();
}
private void Form1_Load(object sender, EventArgs e)
{
this.DoubleBuffered = true;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
int radius = 3;
for (int i = points.Count - 1; i >= 0; --i)
{
Point p = points[i];
p.Y += 1;
if (p.Y > Height)
{
points.RemoveAt(i);
continue;
}
points[i] = p;
e.Graphics.FillEllipse(
Brushes.Red,
p.X - radius,
p.Y - radius,
2 * radius,
2 * radius
);
}
}
I managed to make my code work thanks to your suggestions. It still needs some work becasue it draws seperate lines instead of continuous one.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO.Ports;
using System.Threading;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public string data;
private List<Point> points = new List<Point>();
public string[] coordinates;
private Pen pen;
public Bitmap obrazek;
public int i = 0;
public Form1()
{
InitializeComponent();
obrazek = new Bitmap(1000, 1000);
using (Graphics g = Graphics.FromImage(obrazek))
g.Clear(Color.White);
SerialPort serialPort1 = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
serialPort1.Open();
serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
DoubleBuffered = true;
pen = new Pen(Color.Black, 3);
points = new List<Point>();
}
public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort TempSerialPort = (SerialPort)sender;
//Console.WriteLine("data_recived");
data = TempSerialPort.ReadLine();
Console.WriteLine(data);
pointlist_reciver();
//this.Invalidate();
pictureBox2.Invalidate();
}
public void pointlist_reciver()
{
int x1;
int y1;
string[] coordinates = data.Split(',');
string x = coordinates[0];
string y = coordinates[1];
Int32.TryParse(x, out x1);
Int32.TryParse(y, out y1);
points.Add(new Point(x1, y1));
Console.WriteLine(points.Count.ToString());
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(obrazek, 0, 0);
if (points.Count >= 2)
{
List<Point> points2 = points.GetRange(0, 2);
using (Graphics g = Graphics.FromImage(obrazek))
g.DrawLines(pen, points2.ToArray());
points.Clear();
}
}
}
}
Later i will post final version.

Write text in Array of PictureBox

I try to put text from 0 to 11 on 12 pictureboxes have a ball image, but get the text 11 on all.
How can I get the text on the balls from 0 to 11 ?
here is my code:
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 wfballs2
{
public partial class Form1 : Form
{
String s;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
PictureBox[] Shapes = new PictureBox[12];
for (int i = 0; i < 12; i++)
{
s = Convert.ToString(i);
Shapes[i] = new PictureBox();
Shapes[i].Name = "ball" + i.ToString();
Shapes[i].Location = new Point(10 + 45 * i, 300);
Shapes[i].Size = new Size(40, 40);
Shapes[i].Image = Image.FromFile(# "C:\Users\Eiko\Desktop\ball\ball.jpg");
Shapes[i].SizeMode = PictureBoxSizeMode.CenterImage;
Shapes[i].Visible = true;
this.Controls.Add(Shapes[i]);
Shapes[i].Paint += new PaintEventHandler((sender2, e2) =>
{
e2.Graphics.DrawString(s, Font, Brushes.Black, 10, 13);
});
}
}
}
}
The variable s is an instance in your form, so its value is shared by the form and all the shapes you create.
Everytime one of your shape is painted, this code:
e2.Graphics.DrawString(s, Font, Brushes.Black, 10, 13);
will run. That s is an instance variable of your Form. It will show for all shapes the last value that it was set to. In your case that happens in the last iteration of your for loop, hence the 11.
To fix this you have to capture the loop variable in a local variable before the anonymous eventhandler and then use that local var to do the Convert.ToString(val) in the event handler, like so:
var val = i; // capture variable
Shapes[i].Paint += new PaintEventHandler((sender2, e2) =>
{
// use captured variable here
e2.Graphics.DrawString(Convert.ToString(val), Font, Brushes.Black, 10, 13);
});
This will generate the string with the local variable based on val.
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace wfballs2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
int k = 0;
PictureBox[] Shapes = new PictureBox[12];
for (int i = 0; i < 12; i++)
{
Shapes[i] = new PictureBox();
Shapes[i].Name = "ball" + i.ToString();
Shapes[i].Location = new Point(10 + 45 * i, 300);
Shapes[i].Size = new Size(40, 40);
Shapes[i].Image = Image.FromFile(# "C:\Users\Eiko\Desktop\ball\ball.jpg");
Shapes[i].SizeMode = PictureBoxSizeMode.CenterImage;
Shapes[i].Visible = true;
this.Controls.Add(Shapes[i]);
Shapes[i].Paint += new PaintEventHandler((sender2, e2) =>
{
e2.Graphics.DrawString(k.ToString(), Font, Brushes.Black, 10, 13);
k++;
});
}
}
}
}

Replacing old values when drawing

I am using Windows Form application and using one button to generate random number and draw on form. when button is clicked, It is adding a random number using Graphics.Drawing method. Problem is when I hit the button first time it works fine and add a random number i.e 11111. When I hit button again it will add a new random number (on next position) but it will also change previous numbers to new generated random number.
Updated: (Added Complete Code)
Edit: I have moved Random outside of scoop so now it does not generate same number but still its changing old random numbers to other ones.
Main Class:
using System;
using System.Collections;
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 DrawingText
{
public partial class Form1 : Form
{
private Point mouseDownPosition = new Point(0, 0);
private Point mouseMovePosition = new Point(0, 0);
private int mousePressdDown;
private ArrayList drawnItemsList;
Random rnd;
public Form1()
{
InitializeComponent();
drawnItemsList = new ArrayList();
this.rnd = new Random();
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
mouseMovePosition = e.Location;
if (e.Button == MouseButtons.Left)
mousePressdDown = 1;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
mouseDownPosition = e.Location;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (mousePressdDown == 1)
{
label1.Text = "X: " + mouseMovePosition.X.ToString();
label2.Text = "Y: " + mouseMovePosition.Y.ToString();
this.Invalidate();
}
DrawingData a = new DrawingData(mouseMovePosition, mouseDownPosition);
drawnItemsList.Add(a);
mousePressdDown = 0;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (DrawingData a in drawnItemsList)
{
draw(e.Graphics, a.old, a.cur);
}
draw(e.Graphics, mouseDownPosition, mouseMovePosition);
}
private void draw(Graphics e, Point mold, Point mcur)
{
Pen p = new Pen(Color.Black, 2);
using (Font useFont = new Font("Gotham Medium", 28, FontStyle.Bold))
{
string header2 = rnd.Next().ToString();
RectangleF header2Rect = new RectangleF();
int moldX = mold.X - 5;
int moldY = mold.Y;
header2Rect.Location = new Point(moldX, moldY);
header2Rect.Size = new Size(600, ((int)e.MeasureString(header2, useFont, 600, StringFormat.GenericTypographic).Height));
e.DrawString(header2, useFont, Brushes.Black, header2Rect);
}
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}
Drawing Data Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace DrawingText
{
[Serializable]
class DrawingData
{
private Point mold; // mouseDown position
private Point mcur; // mouseUp poslition
public DrawingData()
{
mold = new Point(0, 0);
mcur = new Point(0, 0);
}
public DrawingData(Point old, Point cur)
{
mold = old;
mcur = cur;
}
public Point old
{
get
{
return mold;
}
set
{
mold = value;
}
}
public Point cur
{
get
{
return mcur;
}
set
{
mcur = value;
}
}
}
}
3 times button clicked and it replaced old value with new one:
You need to store the random value with the point values in the DrawingData class, like this:
Main Class:
namespace DrawingText
{
public partial class Form1 : Form
{
private Point mouseDownPosition = new Point(0, 0);
private Point mouseMovePosition = new Point(0, 0);
private int mousePressdDown;
private ArrayList drawnItemsList;
Random rnd;
public Form1()
{
InitializeComponent();
drawnItemsList = new ArrayList();
this.rnd = new Random();
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (mousePressdDown == 1)
{
label1.Text = "X: " + mouseMovePosition.X.ToString();
label2.Text = "Y: " + mouseMovePosition.Y.ToString();
this.Invalidate();
}
DrawingData a = new DrawingData(mouseMovePosition, mouseDownPosition, rnd.Next().ToString());
drawnItemsList.Add(a);
mousePressdDown = 0;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (DrawingData a in drawnItemsList)
{
draw(e.Graphics, a);
}
draw(e.Graphics, mouseDownPosition, mouseMovePosition);
}
private void draw(Graphics e, DrawingData a)
{
Pen p = new Pen(Color.Black, 2);
using (Font useFont = new Font("Gotham Medium", 28, FontStyle.Bold))
{
RectangleF header2Rect = new RectangleF();
int moldX = a.old.X - 5;
int moldY = a.old.Y;
header2Rect.Location = new Point(moldX, moldY);
header2Rect.Size = new Size(600, ((int)e.MeasureString(header2, useFont, 600, StringFormat.GenericTypographic).Height));
e.DrawString(a.Rand, useFont, Brushes.Black, header2Rect);
}
}
}
}
Drawing Data Class:
namespace DrawingText
{
[Serializable]
public class DrawingData
{
private Point mold; // mouseDown position
private Point mcur; // mouseUp poslition
private string randValue; // random data value
public DrawingData()
{
mold = new Point(0, 0);
mcur = new Point(0, 0);
randValue = String.Empty;
}
public DrawingData(Point old, Point cur, string rand)
{
mold = old;
mcur = cur;
randValue = rand;
}
public Point old
{
get
{
return mold;
}
set
{
mold = value;
}
}
public Point cur
{
get
{
return mcur;
}
set
{
mcur = value;
}
}
public sting Rand
{
get
{
return randValue;
}
set
{
randValue = value;
}
}
}
You are recreating your random each time in the loop which will cause it to have the same seed, and the same first number. That's why all your numbers are the same. You should.
Move your random outside of the method and loop, and use it instead. Change the line Random rnd = new Random() to rnd = new Random(). You already have a variable in the class to hold the random.
If you want the previous random numbers to remain the same as the last time, you need to store them in a list somewhere and draw them on paint. You are currently creating a new set of random numbers each time.
This is made on the fly using graphics path:
GraphicsPath gp;
int moldX = 10;
int moldY = 10;
public Form1()
{
InitializeComponent();
gp = new GraphicsPath();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.FillPath(Brushes.Black, gp);
// if you want the numbers outlined do e.Graphics.DrawPath
}
private void button1_Click(object sender, EventArgs e)
{
AddToPath();
Invalidate();
}
private void AddToPath()
{
using (Font useFont = new Font("Gotham Medium", 28, FontStyle.Bold))
{
Random rnd = new Random();
string header2 = rnd.Next().ToString();
int strsize = TextRenderer.MeasureText(header2, useFont).Height;
StringFormat format = StringFormat.GenericDefault;
gp.AddString(header2, useFont.FontFamily, 1, 28, new Point(moldX, moldY), format);
moldX += 5;
moldY += strsize;
}
}

Categories