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)
{
}
}
}
Related
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.
I am creating a c# piano which when clicking on a music key, an image of the music note is outputted on the form, however no image is being outputted. I am sure that the image path for the bitmap images is correct so I am not sure whether I have done something wrong in the code or I need to add some events to the form itself.Can somebody help me with this please ?
This is the Form class:
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.Media;
using System.Threading;
namespace NewPiano
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
SoundPlayer sp = new SoundPlayer();
int count;
private Control mn;
int xLoc = 50;
int yLoc = 30;
List<MusicNote> notes = new List<MusicNote>();
private void Form1_Load(object sender, System.EventArgs e)
{
MusKey mk;
BlackMusKey bmk;
int[] whitePitch = { 1, 3, 5, 6, 8, 10, 12, 13, 15, 17, 18, 20, 22, 24 };
int[] blackPitch = new int[] { 2, 4, 7, 9, 11, 14, 16, 19, 21, 23 };
int[] xPos = new int[] { 10, 30, 70, 90, 110, 150, 170, 210, 230, 250 };
for (int k = 0; k < 7; k++)
{
int iNote = whitePitch[k];
int xpos = k * 40;
mk = new MusKey(iNote, xpos + 225, 300);
mk.MouseDown += new System.Windows.Forms.MouseEventHandler(this.button1_MouseDown);
mk.MouseUp += new System.Windows.Forms.MouseEventHandler(this.button1_MouseUp);
this.panel1.Controls.Add(mk);
}
int xOffs = 20;
for (int k = 0; k < 5; k++)
{
int iNote = blackPitch[k];
int xpos = xPos[k] * 2;
bmk = new BlackMusKey(iNote, xpos + 225, 300);
bmk.MouseDown += new System.Windows.Forms.MouseEventHandler(this.button1_MouseDown);
bmk.MouseUp += new System.Windows.Forms.MouseEventHandler(this.button1_MouseUp);
this.panel1.Controls.Add(bmk);
this.panel1.Controls[this.panel1.Controls.Count - 1].BringToFront();
}
}
private void button1_MouseDown(object sender, MouseEventArgs e)
{
foreach(MusKey mk in this.panel1.Controls.OfType<MusKey>())
{
if(sender == mk)
{
if(e.Button == MouseButtons.Left)
{
timer1.Enabled = true;
count = 0;
timer1.Start();
sp.SoundLocation = #"C:/Users/Kim/Desktop/Notes-Sound files/mapped/" + mk.musicNote + ".wav"; //change this to the location of your "mapped" folder
sp.Load();
sp.Play();
}
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
count ++;
}
private void button1_MouseUp(object sender, MouseEventArgs e)
{
foreach(MusKey mk in this.panel1.Controls.OfType<MusKey>())
{
if (sender == mk)
{
if (e.Button == MouseButtons.Left)
timer1.Enabled = false;
textBox1.Text = count.ToString();
sp.Stop();
string bNoteShape = null;
int duration = 0;
//Insert note lengths
if (count >= 16)
{
bNoteShape = "SemiBreve";
duration = (16 + 20) / 2;
}
else if ((count >= 11) && (count <= 15))
{
bNoteShape = "DotMin";
duration = (11 + 15) / 2; //average
}
else if ((count >= 6) && (count <= 10))
{
bNoteShape = "Minim";
duration = (6 + 10) / 2; //average
}
else if ((count >= 3) && (count <= 5))
{
bNoteShape = "Crotchet";
duration = (3 + 5) / 2; //average
}
else if ((count == 2))
{
bNoteShape = "Quaver";
duration = 2; //average
}
else if ((count >= 0) || (count <= 1))
{
bNoteShape = "SemiQuaver";
duration = 1;
}
//copied from handout
MusicNote mn = new MusicNote(mk.musicNote, duration, bNoteShape, xLoc);
notes.Add(mn);
mn.Location = new Point(xLoc, yLoc);
this.panel1.Controls.Add(this.mn);
xLoc = xLoc + 40;
}
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
System.Drawing.Graphics graphicsObj;
graphicsObj = this.panel1.CreateGraphics();
Pen myPen = new Pen(System.Drawing.Color.Black, 1);
for (int k = 0; k < 5; k++)
{
int ypos = (k * 15) + 20;
graphicsObj.DrawLine(myPen, 20, ypos, 550, ypos);
}
}
private void button1_Click(object sender, EventArgs e)
{
foreach (MusicNote mn in notes)
{
sp.SoundLocation = #"C:/Users/Kim/Desktop/Notes-Sound files/mapped/" + mn.pitch + ".wav"; //change this to the location of your "mapped" folder
sp.Play();
Thread.Sleep(mn.duration * 150);
}
}
}
}
This is the Music Note class:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace NewPiano
{
public class MusicNote : PictureBox
{
Boolean isDragging = false;
public int pitch = 0;
public string noteshape = "";
public int duration = 0;
internal Point Location;
public int xLocation = 0;
public MusicNote(int notePitch, int duration, string bNoteShape, int xLoc) : base()
{
this.noteshape = bNoteShape;
this.duration = duration;
this.pitch = notePitch;
Location = new Point(xLoc, pitch);
this.Size = new Size(30, 30);
Bitmap bmp = new Bitmap(#"C:/Users/Kim/Desktop/Notes-Images/" + noteshape + ".bmp");
this.Image = bmp;
this.MouseDown += new MouseEventHandler(StartDrag);
this.MouseUp += new MouseEventHandler(StopDrag);
this.MouseMove += new MouseEventHandler(NoteDrag);
}
private void StartDrag(object sender, MouseEventArgs e) {
if(e.Button == MouseButtons.Left) {
isDragging = true;
pitch = e.Y;
this.Location = new Point(this.Location.X, pitch);
}
}
private void StopDrag(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
isDragging = false;
pitch = e.Y;
}
}
private void NoteDrag(object sender, MouseEventArgs e)
{
if (isDragging)
{
this.Top = this.Top + (e.Y - this.pitch);
}
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
}
}
Hi I've C# forms application. I want to Load an Image into a picturebox and Drag the Image where I want. When I'm done with Dragging I added a checkbox
to let users to click on a checkbox.
Then, user can use mouse to select a portion of image. That portion will be shown inside another picturebox. So, I did some search and came up with a solution
which actually doesn't work.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace HCRLibrarytest
{
public partial class MainForm : Form
{
private Point startingPoint = Point.Empty;
private Point movingPoint = Point.Empty;
private bool panning = false;
Image _OrginalBitmap;
Image _NewBitmap;
private bool IsSelecting = false;
private int X0, Y0, X1, Y1;
static bool isimagepositioned = false;
public MainForm()
{
InitializeComponent();
}
private void btn_openimage_Click(object sender, EventArgs e)
{
OpenFileDialog dialog2 = new OpenFileDialog
{
Filter = "Bitmap Image (*.jpeg)|*.jpeg"
};
using (OpenFileDialog dialog = dialog2)
{
if (dialog.ShowDialog() == DialogResult.OK)
{
try
{
using (StreamReader reader = new StreamReader(dialog.FileName))
{
this._OrginalBitmap = new Bitmap(dialog.FileName);
this.pb_fullimage.Image = this._OrginalBitmap;
}
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString());
}
}
}
}
private void pb_fullimage_MouseUp(object sender, MouseEventArgs e)
{
if (_OrginalBitmap != null)
{
if(!isimagepositioned)
{
panning = false;
}
else
{
if (!IsSelecting) return;
IsSelecting = false;
pb_fullimage.Image = _OrginalBitmap;
int wid = Math.Abs(X0 - X1);
int hgt = Math.Abs(Y0 - Y1);
if ((wid < 1) || (hgt < 1)) return;
Bitmap area = new Bitmap(wid, hgt);
using (Graphics gr = Graphics.FromImage(area))
{
Rectangle source_rectangle = new Rectangle(Math.Min(X0, X1), Math.Min(Y0, Y1), wid, hgt);
Rectangle dest_rectangle = new Rectangle(0, 0, wid, hgt);
gr.DrawImage(pb_fullimage.Image, dest_rectangle, source_rectangle, GraphicsUnit.Pixel);
}
pb_selectedportion.Image = area;
}
}
}
private void pb_fullimage_MouseDown(object sender, MouseEventArgs e)
{
if (_OrginalBitmap != null)
{
if (!isimagepositioned)
{
panning = true;
startingPoint = new Point(e.Location.X - movingPoint.X,e.Location.Y - movingPoint.Y);
}
else
{
_NewBitmap = new Bitmap(pb_fullimage.Image);
IsSelecting = true;
X0 = e.X;
Y0 = e.Y;
}
}
}
private void pb_fullimage_MouseMove(object sender, MouseEventArgs e)
{
if (_OrginalBitmap != null)
{
if (!isimagepositioned)
{
if (panning)
{
movingPoint = new Point(e.Location.X - startingPoint.X,e.Location.Y - startingPoint.Y);
pb_fullimage.Invalidate();
}
}
else
{
if (!IsSelecting) return;
X1 = e.X;
Y1 = e.Y;
Bitmap bm = new Bitmap(_NewBitmap);
using (Graphics gr = Graphics.FromImage(bm))
{
gr.DrawRectangle(Pens.Red, Math.Min(X0, X1), Math.Min(Y0, Y1), Math.Abs(X0 - X1), Math.Abs(Y0 - Y1));
}
pb_fullimage.Image = bm;
}
}
}
private void pb_fullimage_Paint(object sender, PaintEventArgs e)
{
if (_OrginalBitmap != null && !isimagepositioned)
{
e.Graphics.Clear(Color.White);
e.Graphics.DrawImage(_OrginalBitmap, movingPoint);
}
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked)
{
isimagepositioned = true;
}
else
{
isimagepositioned = false;
}
}
}
}
when I drag and check 'Image Positioned' and select using mouse move. It always gives me the the image that is relative to the original image position.
So, Can somebody help to fix this.
Since nobody answered me, I found an answer. This worked for me.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace HCRLibrarytest
{
public partial class MainForm : Form
{
public Point startingPoint = Point.Empty;
public Point movingPoint = Point.Empty;
public bool panning = false;
Image _OrginalBitmap;
public static Image _NewBitmap;
public bool IsSelecting = false;
public int X0, Y0, X1, Y1;
public MainForm()
{
InitializeComponent();
}
public void btn_openimage_Click(object sender, EventArgs e)
{
OpenFileDialog dialog2 = new OpenFileDialog
{
Filter = "Bitmap Image (*.jpeg)|*.jpeg"
};
using (OpenFileDialog dialog = dialog2)
{
if (dialog.ShowDialog() == DialogResult.OK)
{
try
{
using (StreamReader reader = new StreamReader(dialog.FileName))
{
this._OrginalBitmap = new Bitmap(dialog.FileName);
this.pb_fullimage.Image = this._OrginalBitmap;
}
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString());
}
}
}
}
public void pb_fullimage_MouseUp(object sender, MouseEventArgs e)
{
if (pb_fullimage.Image != null)
{
if (!checkBox1.Checked)
{
panning = false;
}
else
{
if (!IsSelecting) return;
IsSelecting = false;
pb_fullimage.Image = _NewBitmap;
int wid = Math.Abs(X0 - X1);
int hgt = Math.Abs(Y0 - Y1);
if ((wid < 1) || (hgt < 1)) return;
Bitmap area = new Bitmap(wid, hgt);
using (Graphics gr = Graphics.FromImage(area))
{
Rectangle source_rectangle = new Rectangle(Math.Min(X0, X1), Math.Min(Y0, Y1), wid, hgt);
Rectangle dest_rectangle = new Rectangle(0, 0, wid, hgt);
gr.DrawImage(_NewBitmap, dest_rectangle, source_rectangle, GraphicsUnit.Pixel);
}
pb_selectedportion.Image = area;
}
}
}
public void pb_fullimage_MouseDown(object sender, MouseEventArgs e)
{
if (pb_fullimage.Image != null)
{
if (!checkBox1.Checked)
{
panning = true;
startingPoint = new Point(e.Location.X - movingPoint.X, e.Location.Y - movingPoint.Y);
}
else
{
IsSelecting = true;
X0 = e.X;
Y0 = e.Y;
}
}
}
public void pb_fullimage_MouseMove(object sender, MouseEventArgs e)
{
if (pb_fullimage.Image != null)
{
if (!checkBox1.Checked)
{
if (panning)
{
movingPoint = new Point(e.Location.X - startingPoint.X, e.Location.Y - startingPoint.Y);
pb_fullimage.Invalidate();
using (Bitmap bitmap = new Bitmap(pb_fullimage.ClientSize.Width, pb_fullimage.ClientSize.Height))
{
pb_fullimage.DrawToBitmap(bitmap, pb_fullimage.ClientRectangle);
try { bitmap.Save(AppDomain.CurrentDomain.BaseDirectory + "draw.jpg"); }
catch (Exception ex) { Console.Write(ex.ToString()); }
}
}
}
else
{
if (!IsSelecting) return;
X1 = e.X;
Y1 = e.Y;
Bitmap bm = new Bitmap(Bitmap.FromStream(File.OpenRead(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "draw.jpg"))));
using (Graphics gr = Graphics.FromImage(bm))
{
gr.DrawRectangle(Pens.WhiteSmoke, Math.Min(X0, X1), Math.Min(Y0, Y1), Math.Abs(X0 - X1), Math.Abs(Y0 - Y1));
}
_NewBitmap = bm;
}
}
}
public void pb_fullimage_Paint(object sender, PaintEventArgs e)
{
if (pb_fullimage.Image != null && !checkBox1.Checked)
{
e.Graphics.Clear(Color.White);
e.Graphics.DrawImage(pb_fullimage.Image, movingPoint);
}
}
}
}
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();
}
}
}
I added a new form to my project the new form contain in the designer webBrowser control. What i'm doing is parsing from html some links then navigate to each link then taking a screenshot and save to the hard disk each image i navigated to in the webBrowser.
In the end when all the links navigated and i have the images on the hard disk i display them on Form1 pictureBox with a hScrollBar.
But now instead waiting for it to finish in the new form and then to show all the images i want to show each saved image on the hard disk in the pictureBox in form1.
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.Runtime.InteropServices;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.IO;
namespace WebBrowserScreenshots.cs
{
public partial class WebBrowserScreenshots : Form
{
private class MyComparer : IComparer<string>
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
private static extern int StrCmpLogicalW(string x, string y);
public int Compare(string x, string y)
{
return StrCmpLogicalW(x, y);
}
}
List<string> newHtmls = new List<string>();
string uri = "";
public bool htmlloaded = false;
int countlinks = 0;
public int numberoflinks = 0;
public int numberofimages = 0;
public List<string> imageList = new List<string>();
public WebBrowserScreenshots()
{
InitializeComponent();
webBrowser1.ScrollBarsEnabled = false;
webBrowser1.ScriptErrorsSuppressed = true;
NavigateToSites();
}
string test;
List<string> htmls;
private void GetLinks()
{
htmlloaded = true;
for (int i = 1; i < 304; i++)
{
if (newHtmls.Count == 1)
break;
backgroundWorker1.ReportProgress(i);
HtmlAgilityPack.HtmlWeb hw = new HtmlAgilityPack.HtmlWeb();
HtmlAgilityPack.HtmlDocument doc = hw.Load("http://test/page" + i);
htmls = new List<string>();
foreach (HtmlAgilityPack.HtmlNode link in doc.DocumentNode.SelectNodes("//a[#href]"))
{
string hrefValue = link.GetAttributeValue("href", string.Empty);
if (hrefValue.Contains("http") && hrefValue.Contains("attachment"))
htmls.Add(hrefValue);
}
if (htmls.Count > 0 && abovezero == false)
RealTimeHtmlList();
}
}
bool abovezero = false;
private void RealTimeHtmlList()
{
abovezero = true;
for (int x = 0; x < htmls.Count; x++)
{
test = htmls[x];
int index = test.IndexOf("amp");
string test1 = test.Substring(39, index - 25);
test = test.Remove(39, index - 35);
int index1 = test.IndexOf("amp");
if (index1 > 0)
test = test.Remove(index1, 4);
if (!newHtmls.Contains(test))
{
while (true)
{
if (htmlloaded == true)
{
newHtmls.Add(test);
RealTimeNavigate(test);
}
else
{
break;
}
}
}
}
}
private void RealTimeNavigate(string tests)
{
uri = test;
webBrowser1.Navigate(test);
htmlloaded = false;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
GetLinks();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
numberoflinks = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
numberofimages = newHtmls.Count;
htmlloaded = true;
}
private void NavigateToLinks()
{
if (countlinks != newHtmls.Count)
{
while (true)
{
if (htmlloaded == true)
{
uri = newHtmls[countlinks];
webBrowser1.Navigate(newHtmls[countlinks]);
countlinks++;
htmlloaded = false;
}
else
{
break;
}
}
}
}
int imagescount = 0;
public FileInfo[] filesinfo;
public bool savedall = false;
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url.ToString() == uri)
{
Bitmap bmp = new Bitmap(SaveImageFromWebBrowser(webBrowser1));
bmp = ImageTrim.ImagesTrim(bmp);
bmp.Save(#"e:\webbrowserimages\Image" + imagescount.ToString() + ".bmp",
System.Drawing.Imaging.ImageFormat.Bmp);
bmp.Dispose();
imagescount++;
htmlloaded = true;
RealTimeHtmlList();
}
}
private void NavigateToSites()
{
backgroundWorker1.RunWorkerAsync();
}
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);
private Bitmap SaveImageFromWebBrowser(Control ctl)
{
Bitmap bmp = new Bitmap(ctl.ClientRectangle.Width, ctl.ClientRectangle.Height);
using (Graphics graphics = Graphics.FromImage(bmp))
{
IntPtr hDC = graphics.GetHdc();
try { PrintWindow(ctl.Handle, hDC, (uint)0); }
finally { graphics.ReleaseHdc(hDC); }
}
return bmp;
}
}
}
And in form1 i did:
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.IO;
using System.Runtime.InteropServices;
namespace WebBrowserScreenshots.cs
{
public partial class Form1 : Form
{
private class MyComparer : IComparer<string>
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
private static extern int StrCmpLogicalW(string x, string y);
public int Compare(string x, string y)
{
return StrCmpLogicalW(x, y);
}
}
public List<string> imageList = new List<string>();
List<string> numbers = new List<string>();
WebBrowserScreenshots wbss;
public Form1()
{
InitializeComponent();
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
this.imageList = Directory.GetFiles(#"e:\webbrowserimages\", "*.bmp").ToList();
this.imageList.Sort(new MyComparer());
if (this.imageList.Count > 0)
{
hScrollBar1.Minimum = 0;
hScrollBar1.Value = 0;
hScrollBar1.Maximum = this.imageList.Count - 1;
hScrollBar1.SmallChange = 1;
hScrollBar1.LargeChange = 1;
pictureBox1.Image = Image.FromFile(this.imageList[0]);
}
else
{
timer1.Start();
wbss = new WebBrowserScreenshots();
wbss.Show();
}
}
FileInfo[] myFile;
private void timer1_Tick(object sender, EventArgs e)
{
if (wbss.savedall == true)
{
timer1.Stop();
hScrollBar1.Enabled = true;
hScrollBar1.Minimum = 0;
hScrollBar1.Value = 0;
hScrollBar1.Maximum = wbss.imageList.Count - 1;
hScrollBar1.SmallChange = 1;
hScrollBar1.LargeChange = 1;
pictureBox1.Image = Image.FromFile(wbss.imageList[0]);
}
else
{
if (wbss.htmlloaded == true)
{
var directory = new DirectoryInfo(#"e:\webbrowserimages\");
myFile = directory.GetFiles("*.bmp");
if (myFile.Length > 0)
{
var myFiles = (from f in directory.GetFiles("*.bmp")
orderby f.LastWriteTime descending
select f).First();
hScrollBar1.Enabled = true;
hScrollBar1.Minimum = 0;
hScrollBar1.Value = 0;
hScrollBar1.Maximum = 1;
hScrollBar1.SmallChange = 1;
hScrollBar1.LargeChange = 1;
pictureBox1.Image = Image.FromFile(myFiles.Name);
}
}
}
}
private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
{
int index = (int)hScrollBar1.Value;
if (pictureBox1.Image != null) pictureBox1.Image.Dispose();
if (this.imageList.Count > 0)
{
pictureBox1.Image = Image.FromFile(this.imageList[index]);
label1.Text = "Displaying image " + index + " of " + (this.imageList.Count - 1);
}
else
{
pictureBox1.Image = Image.FromFile(wbss.imageList[index]);
label1.Text = "Displaying image " + index + " of " + (wbss.imageList.Count - 1);
}
}
}
}
In form1 i have two options situations could be done.
Once if i'm using in the new form the way that i'm waiting for the backgroundworker to complete and then to wait untill it will navigate to all links in the List newHtmls and then after all images saved on hard disk for example 2453 images then i browse them in form1 pictureBox and hScrollBar.
Or the second option i'm using now that once an image saved to the hard disk in the new form then i will show the image in the form1 pictureBox1.
Then another image saved so now there are two images on hard disk so now show the last saved image. And so on once image saved display it on form1 pictureBox.
Just to show it. So i will see every X seconds images changing in form1 pictureBox.
The problem i'm facing now is in Form1 in this part:
if (wbss.htmlloaded == true)
{
var directory = new DirectoryInfo(#"e:\webbrowserimages\");
myFile = directory.GetFiles("*.bmp");
if (myFile.Length > 0)
{
var myFiles = (from f in directory.GetFiles("*.bmp")
orderby f.LastWriteTime descending
select f).First();
hScrollBar1.Enabled = true;
hScrollBar1.Minimum = 0;
hScrollBar1.Value = 0;
hScrollBar1.Maximum = 1;
hScrollBar1.SmallChange = 1;
hScrollBar1.LargeChange = 1;
pictureBox1.Image = Image.FromFile(myFiles.Name);
}
}
On the line:
pictureBox1.Image = Image.FromFile(myFiles.Name);
FileNotFoundException: Image3.bmp
But on my hard disk i see Image3.bmp
I will try to narrow cut some code but it's all connected the new form with form1.
You need to use myFiles.FullName. myFiles.Name only has the path relative to the directory the file is in, which is not enough to find the file. FullName includes the directory, so it's the full absolute path to the file.
And for gasake, name your controls. Form1 isn't a good name. pictureBox1 isn't a good name. Even the variable names are misleading - myFile for a collection of files, and then myFiles for a single file? And why are you calling GetFiles again when you already have a list in myFile? And why even check for file length? Why not just do directory.GetFiles("*.bmp").OrderByDescending(i => i.LastWriteTime).Select(i => i.FullName).FirstOrDefault()?