This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I'm new to C#, just beginning to write some codes.
I have something in mind but before proceeding to it, need some help on this matter.
How to exit a running process by detecting a mouse click?
I wrote some lines but when compiled and running, the mouse click has no effect at all.
Can someone please take a look and help me?
Here's my lines...
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;
namespace Graphic_test_1
{
public partial class Form1 : Form
{
public static Single lim_x, lim_y; // limits in X & Y
public static int dly = 45;
System.Drawing.Pen myPen = new System.Drawing.Pen(System.Drawing.Color.Blue); // color of the pen
System.Drawing.Graphics Canvas;
public Boolean clik = false; // initialize
public string mystring;
public Form1()
{
InitializeComponent();
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
clik = true;
lim_x = e.X;
lim_y = e.Y;
}
private void btgo_Click(object sender, EventArgs e) // Start drawing [GO]
{
Canvas = this.CreateGraphics();
btgo.Enabled = false;
MessageBox.Show("Checking the limits of the canvas.\r\n" +
"Click anywhere to stop and find out X position",
"Watching Coordinates",
MessageBoxButtons.OK, MessageBoxIcon.Information);
btgo.Visible = false;
btend.Enabled = false;
myPen.Color=System.Drawing.Color.Red; // color of the pen
myPen.Width = 2; // pen width
System.Drawing.Font drawfont = new System.Drawing.Font("Arial", 10); // Graphics font
System.Drawing.SolidBrush mybrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black); // color for the font
System.Drawing.Color background;
background = this.BackColor;
lim_x = 0; // initialize
do
{
Canvas.DrawLine(myPen, 0, 200, lim_x, 200);
mystring = "Current X = " + lim_x.ToString();
mybrush.Color = System.Drawing.Color.Black;
Canvas.DrawString(mystring, drawfont, mybrush, 351, 334);
System.Threading.Thread.Sleep(dly);
mybrush.Color = background; // use the background color
Canvas.FillRectangle(mybrush, new Rectangle(350, 333, 500, 353));
if (clik)
{
mybrush.Color = background; // use the background color
Canvas.FillRectangle(mybrush, new Rectangle(350, 333, 500, 353));
mystring = "Current X = " + lim_x.ToString();
mybrush.Color = System.Drawing.Color.Black;
Canvas.DrawString(mystring, drawfont, mybrush, 351, 334);
MessageBox.Show("Final position in X = " + lim_x.ToString(),
"Mouse click detected",
MessageBoxButtons.OK, MessageBoxIcon.Stop);
break;
}
else
lim_x++;
} while (lim_x < 611);
myPen.Dispose(); // release the pen
mybrush.Dispose(); // release the brush
Canvas.Dispose(); // release the canvas
btend.Enabled = true;
btend.Focus();
}
private void btend_Click(object sender, EventArgs e) // quit program [END]
{
Dispose(); // program ends.
}
}
}
If you want to close your form, use this.Close(). if you want to exit your application, you can use Application.Exit().
If I understand well, you are trying to stop the process it are running. (e.g. The btgo click event).
To do this, you should use an individual Thread to execute the process.
Why Thread ?
Your application will run two different process :
The main Thread
The second Thread
So, it will be possible to recognize the "Mouse Click" while you are running the second Thread.
E.g. I have one Button and one Label. I want, on the Button1 click,create and start a Thread. This Thread will loop 10000 time and modify the Label1 text. But when I click on the label, the loop will stop :
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
public partial class Test : Form
{
Thread thread;
public Test()
{
InitializeComponent();
}
void Button1_Click(object sender, EventArgs e)
{
thread = new Thread(new ThreadStart(StartThread));
thread.Start();
}
private void StartThread()
{
for(int i =0;i<1000000;i++)
{
Thread.Sleep(1000);
Label1.Invoke((MethodInvoker)(() => Label1.Text = i.ToString()));
//See the more information section, I will post a link about this.
}
}
void Label1_Click(object sender, EventArgs e)
{
thread.Abort();
}
}
More information :
You should read about how to properly close a thread here.
Invoke method here.
Related
I am having an windows application where I am fetching data from db and binding that to a label. I am using timer and scrolling the label, this works fine when the string is around 150 characters but when I have string of around 30000 characters it just hangs out the application.
lblMsg1.AutoEllipsis = true;
private void timer1_Tick(object sender, EventArgs e)
{
try
{
if (lblMsg1.Right <= 0)
{
lblMsg1.Left = this.Width;
}
else
lblMsg1.Left = lblMsg1.Left - 5;
this.Refresh();
}
catch (Exception ex)
{
}
}
public void bindData()
{
lblMsg.Text = "Some Large text";
}
public void Start()
{
try
{
timer1.Interval = 150;
timer1.Start();
}
catch (Exception ex)
{
Log.WriteException(ex);
}
}
Why is this related to string length and causing application to hang? Thanks in advance.
I guess you are trying to create a news ticker?
I am not sure that labels are designed to hold such big strings.
Use a picturebox instead and update your code.
Define two variables in your form class. One to hold text offset and the other to hold the graphics object for the picture box. Like this:
private float textoffset = 0;
System.Drawing.Graphics graphics = null;
In the form onload do this:
private void Form1_Load(object sender, EventArgs e)
{
textoffset = (float)pictureBox1.Width; // Text starts off the right edge of the window
pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
graphics = Graphics.FromImage(pictureBox1.Image);
}
Your timer should then look like this:
private void timer1_Tick(object sender, EventArgs e)
{
graphics.Clear(BackColor);
graphics.DrawString(newstickertext, new Font(FontFamily.GenericMonospace, 10, FontStyle.Regular), new SolidBrush(Color.Black), new PointF(textoffset, 0));
pictureBox1.Refresh();
textoffset = textoffset-5;
}
Instead of a Label, use a TextBox and set the ScrollBars, MultiLine and WordWrap properties according to your needs. To disable editing of the TextBox (and, thus, make it behave similar to a label), use the ReadOnly property.
I want to display text on a ProgressBar, (without all the nonsense of a custom progress bar). This is not hard to do, and does not involve the OnPaint method -- as demonstrated with button1 of the following code. However, this method blocks the UI thread, which is evil.
Unfortunately, my best stab at an asynchronous approach causes the text to flicker, which is very annoying.
Can somebody show me how to update the text asynchronously without the flicker?
(To run the following code, just paste it into a new project
containing a Form with 3 Buttons and 3 ProgressBars).
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.Threading;
namespace ProgBarTest //change namespace in Program.cs accordingly
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//This method will block the main UI thread
// (thus freezing the other buttons)
StartUpdate(this.progressBar1);
}
private void button2_Click(object sender, EventArgs e)
{
//this method (and the next) don't block the UI, and can be used concurrently,
// but the text flickers
Task t = new Task(() => StartUpdate(this.progressBar2));
t.Start();
}
private void button3_Click(object sender, EventArgs e)
{
Task t = new Task(() => StartUpdate(this.progressBar3));
t.Start();
}
private void StartUpdate( ProgressBar progBar)
{
for (int i = 1; i <= 100; i++)
{
UpdateProgressBar(i, progBar);
Thread.Sleep(100);
}
}
private void UpdateProgressBar(int i, ProgressBar progBar)
{
if (progBar.InvokeRequired) //for use with background Task
{
progBar.Invoke(new Action<int, ProgressBar>(UpdateProgressBar),
new Object[] { i, progBar });
}
else
{
//set progress bar:
progBar.Value = i;
progBar.Refresh();
//set status label:
string percentStr = i.ToString() + "%";
PointF location = new PointF(progBar.Width / 2 - 10, progBar.Height / 2 - 7);
using (Graphics gr = progBar.CreateGraphics())
{
gr.DrawString(percentStr, new Font("Arial",10), Brushes.Red, location );
}
}
}
}
}
A custom ProgressBar would be your best bet.. if you set it up correctly. I know I'm not answering your question, just offering a different solution. I haven't tested this yet, but it would in theory draw the percentage every time the progress bar had to repaint, which would happen every time the value was changed.
Your current problem is that the bar is repainting itself every time you change the value, thus the flickering of the text. If it didn't repaint, you would see percentage you draw starting to overlay on top of each other which is not good either.
This would be better to encapsulate everything within one control from a design standpoint as well.
class CustomProgressBar : ProgressBar {
public CustomProgressBar() : base() {}
protected override void OnPaint(PaintEventArgs e) {
// Call the OnPaint method of the base class.
base.OnPaint(e);
string percentStr = this.Value.ToString() + "%";
PointF location = new PointF(this.Width / 2 - 10, this.Height / 2 - 7);
// Call methods of the System.Drawing.Graphics object.
e.Graphics.DrawString(percentStr, new Font("Arial",10), Brushes.Red, location );
}
}
It's probably because you're drawing the string from another thread. If you can use a Control based text element instead you can use BeginInvoke in the same way as the ProgressBar:
// Label progressLbl
private void UpdateProgressFromAnotherThread(int completed, int total, string progressText)
{
this.progBar.BeginInvoke(new Action(() =>
{
this.progBar.Maximum = total;
this.progBar.Value = completed;
}));
this.progressLbl.BeginInvoke(new Action(() =>
{
this.progressLbl.Text = progressText;
}));
}
This question already has answers here:
How to move and resize a form without a border?
(7 answers)
Closed 7 years ago.
I have created a border-less form using c# but could make the custom title bar movable so I search the internet and found this code:
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_NCHITTEST)
m.Result = (IntPtr)(HT_CAPTION);
}
private const int WM_NCHITTEST = 0x84;
private const int HT_CLIENT = 0x1;
private const int HT_CAPTION = 0x2;
After applying this code can click and drag my form in every inch of the form except for the title bar .
This is a good example of the movable title bar.
This is a full example
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Custom_Title_Bar
{
public partial class MainForm : Form
{
private PictureBox title = new PictureBox(); // create a PictureBox
private Label minimise = new Label(); // this doesn't even have to be a label!
private Label maximise = new Label(); // this will simulate our this.maximise box
private Label close = new Label(); // simulates the this.close box
private bool drag = false; // determine if we should be moving the form
private Point startPoint = new Point(0, 0); // also for the moving
public MainForm()
{
this.FormBorderStyle = FormBorderStyle.None;// get rid of the standard title bar
this.title.Location = this.Location; // assign the location to the form location
this.title.Width = this.Width; // make it the same width as the form
this.title.Height = 50; // give it a default height (you may want it taller/shorter)
this.title.BackColor = Color.Black; // give it a default colour (or load an image)
this.Controls.Add(this.title); // add it to the form's controls, so it gets displayed
// if you have an image to display, you can load it, instead of assigning a bg colour
// this.title.Image = new Bitmap(System.Environment.CurrentDirectory + "\\title.jpg");
// if you displayed an image, alter the SizeMode to get it to display as you want it to
// examples:
// this.title.SizeMode = PictureBoxSizeMode.StretchImage;
// this.title.SizeMode = PictureBoxSizeMode.CenterImage;
// this.title.SizeMode = PictureBoxSizeMode.Zoom;
// etc
// you may want to use PictureBoxes and display images
// or use buttons, there are many alternatives. This is a mere example.
this.minimise.Text = "Minimise"; // Doesn't have to be
this.minimise.Location = new Point(this.Location.X + 5, this.Location.Y + 5); // give it a default location
this.minimise.ForeColor = Color.Red; // Give it a colour that will make it stand out
// this is why I didn't use an image, just to keep things simple:
this.minimise.BackColor = Color.Black; // make it the same as the PictureBox
this.Controls.Add(this.minimise); // add it to the form's controls
this.minimise.BringToFront(); // bring it to the front, to display it above the picture box
this.maximise.Text = "Maximise";
// remember to make sure it's far enough away so as not to overlap our minimise option
this.maximise.Location = new Point(this.Location.X + 60, this.Location.Y + 5);
this.maximise.ForeColor = Color.Red;
this.maximise.BackColor = Color.Black; // remember, we want it to match the background
this.maximise.Width = 50;
this.Controls.Add(this.maximise); // add it to the form
this.maximise.BringToFront();
this.close.Text = "Close";
this.close.Location = new Point(this.Location.X + 120, this.Location.Y + 5);
this.close.ForeColor = Color.Red;
this.close.BackColor = Color.Black;
this.close.Width = 37; // this is just to make it fit nicely
this.Controls.Add(this.close);
this.close.BringToFront();
// now we need to add some functionality. First off, let's give those labels
// MouseHover and MouseLeave events, so they change colour
// Since they're all going to change to the same colour, we can give them the same
// event handler, which saves time of writing out all those extra functions
this.minimise.MouseEnter += new EventHandler(Control_MouseEnter);
this.maximise.MouseEnter += new EventHandler(Control_MouseEnter);
this.close.MouseEnter += new EventHandler(Control_MouseEnter);
// and we need to do the same for MouseLeave events, to change it back
this.minimise.MouseLeave += new EventHandler(Control_MouseLeave);
this.maximise.MouseLeave += new EventHandler(Control_MouseLeave);
this.close.MouseLeave += new EventHandler(Control_MouseLeave);
// and lastly, for these controls, we need to add some functionality
this.minimise.MouseClick += new MouseEventHandler(Control_MouseClick);
this.maximise.MouseClick += new MouseEventHandler(Control_MouseClick);
this.close.MouseClick += new MouseEventHandler(Control_MouseClick);
// finally, wouldn't it be nice to get some moveability on this control?
this.title.MouseDown += new MouseEventHandler(Title_MouseDown);
this.title.MouseUp += new MouseEventHandler(Title_MouseUp);
this.title.MouseMove += new MouseEventHandler(Title_MouseMove);
}
private void Control_MouseEnter(object sender, EventArgs e)
{
if (sender.Equals(this.close))
this.close.ForeColor = Color.White;
else if (sender.Equals(this.maximise))
this.maximise.ForeColor = Color.White;
else // it's the minimize label
this.minimise.ForeColor = Color.White;
}
private void Control_MouseLeave(object sender, EventArgs e)
{
// return them to their default colors
if (sender.Equals(this.close))
this.close.ForeColor = Color.Red;
else if (sender.Equals(this.maximise))
this.maximise.ForeColor = Color.Red;
else // it's the minimise label
this.minimise.ForeColor = Color.Red;
}
private void Control_MouseClick(object sender, MouseEventArgs e)
{
if (sender.Equals(this.close))
this.Close(); // close the form
else if (sender.Equals(this.maximise))
{
// maximise is more interesting. We need to give it different functionality,
// depending on the window state (Maximise/Restore)
if (this.maximise.Text == "Maximise")
{
this.WindowState = FormWindowState.Maximized; // maximise the form
this.maximise.Text = "Restore"; // change the text
this.title.Width = this.Width; // stretch the title bar
}
else // we need to restore
{
this.WindowState = FormWindowState.Normal;
this.maximise.Text = "Maximise";
}
}
else // it's the minimise label
this.WindowState = FormWindowState.Minimized; // minimise the form
}
void Title_MouseUp(object sender, MouseEventArgs e)
{
this.drag = false;
}
void Title_MouseDown(object sender, MouseEventArgs e)
{
this.startPoint = e.Location;
this.drag = true;
}
void Title_MouseMove(object sender, MouseEventArgs e)
{
if (this.drag)
{
// if we should be dragging it, we need to figure out some movement
Point p1 = new Point(e.X, e.Y);
Point p2 = this.PointToScreen(p1);
Point p3 = new Point(p2.X - this.startPoint.X,
p2.Y - this.startPoint.Y);
this.Location = p3;
}
}
} // end of the class
} // end of the namespace
If you want you can extract just the moving code and integrate it with your code, the movable Title code is just in the following Event Handlers
Title_MouseUp
Title_MouseDown
Title_MouseMove
Here is the original article for this code, you can read it for more explanation about the code
http://www.dreamincode.net/forums/topic/64981-designing-a-custom-title-bar/
The link to original article is broken
I am trying do image slide show with picturebox Control and a trackbar. The trackbar gets minimum and maximum value corresponds to the number of images to show. I use a timer to get interval period for the slide along with trackbar valuechange.
Now, here is the main thing for each image in the picturebox I'm drawing a rectangle box over the image.
I am not able to draw on the first image when the form get load with first image. But I could do if I scroll the mouse wheel.
I need help to trigger the mouse wheel scroll event once after the first image get loaded.
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 test
{
public partial class Form1 : Form
{
public event MouseEventHandler MouseWheel;
//MouseEventArgs k = new MouseEventArgs(MouseButtons.Middle,0,0,-1);
string[] pics = { "C:\\Downloads\\folder_picture_green.png", "C:\\Downloads\\Aetherpal.ico", "C:\\Downloads\\folder_picture_green.png" };
public Form1()
{
InitializeComponent();
this.trackBar1.Minimum = 0;
this.trackBar1.Maximum = (pics.Count() - 1);
//this.trackBar1.Maximum = 0;
imageupdate(0);
timer1.Start();
timer1.Interval = 3000;
this.MouseWheel += test;
this.MouseWheel(null, null);
}
private void test(object sender, System.Windows.Forms.MouseEventArgs e)
{
MessageBox.Show("Scrolled");
}
private void check(object sender, System.EventArgs e)
{
//if (Initializing == false) { return; }
if(this.trackBar1.Value < this.trackBar1.Maximum )
this.trackBar1.Value += 1;
else
timer1.Stop();
}
private void Valuechange(object sender, System.EventArgs e)
{
imageupdate(this.trackBar1.Value);
if(this.trackBar1.Value < this.trackBar1.Maximum)
timer1.Start();
}
private void imageupdate(int k)
{
this.pictureBox1.Refresh();
this.pictureBox1.Image = new Bitmap(pics[k]);
Pen blackPen = new Pen(Color.Blue, 5);
this.pictureBox1.Refresh();
using (Graphics g = this.pictureBox1.CreateGraphics())
{
g.DrawRectangle(blackPen, 10, 10, 100, 50);
}
}
}
}
You can add this code to your form to scroll your form (of course with MouseWheel):
private void Wheel(int ticks, bool down){
//WM_MOUSEWHEEL = 0x20a
Message msg = Message.Create(Handle, 0x20a, new IntPtr((down ? -1 : 1)<<16), new IntPtr(MousePosition.X + MousePosition.Y << 16));
for(int i = 0; i < ticks; i++)
WndProc(ref msg);
}
//Use it
Wheel(120,true);//Wheel down
Wheel(120,false);//Wheel up
NOTE: I can see you define a MouseWheel event in your own form. This will hide the base MouseWheel event, I don't think you have any reason to do this, your own MouseWheel can't work as the base one, you have to catch the win32 message and raise it yourself, we should use the base MouseWheel event instead. (Maybe you thought there isn't any MouseWheel event in your form class?)
I am studying C# Programming and Kinect sensors programming (I am quite a
newbie in both C# language and Kinect). I am trying to use Microsoft Visual C# 2010 Express to write applications using sensors of Xtion Pro Live to control robots. In my main form, there are 2 picturebox objects, 2 button object, 3 label and 3 textbox objects. One of the two picturebox objects (pictureBox1) is to display the RGB camera. The other one pictureBox2) is to simulate the hand positions in 2D (x and y coordinates) graphics. One of the two buttons (button1) is to initialize Xtion Pro Live and to show RGB camera on picturebox1, and to simulate hand positions on picturebox2. The other one (button2) is to exit the program. The three labels, label1, label2, label3, and the three textboxes, textbox1, textbox2, textbox3 are used to show 3 coordinates of the hand.
This is my code in Form1.cs:
using OpenNI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace HandTracking
{
public partial class Form1 : Form
{
public const string path = #"C:/Vu/Kinect/Data/SamplesConfig.xml";
public bool run;
public Thread thread;
public Bitmap bitmap;
public Context context;
public ScriptNode node;
public ImageGenerator image;
public DepthGenerator depth;
public GestureGenerator gesture;
public HandsGenerator hand;
public Queue<Point3D> handpoint = new Queue<Point3D>();
public const int maxpoint = 30;
enum GestureStatus
{
Unrecognized, Progress, Recognized
}
private GestureStatus gesstatus = GestureStatus.Unrecognized;
enum HandsStatus
{
Untracked, Create, Update
}
private HandsStatus handstatus = HandsStatus.Untracked;
public Pen pen = new Pen(Color.Red, 5);
public Brush brush = new SolidBrush(Color.Magenta);
public Font font = new Font("Times New Roman", 20);
public PointF point = new PointF(0, 0);
public Form1()
{
InitializeComponent();
this.pictureBox1.BackColor = Color.Black;
this.pictureBox2.BackColor = Color.White;
this.button1.Enabled = true;
}
public void button1_Click(object sender, EventArgs e)
{
this.button1.Enabled = false;
try
{
context = Context.CreateFromXmlFile(path, out node);
image = context.FindExistingNode(NodeType.Image) as ImageGenerator;
if (image == null)
throw new Exception(context.GlobalErrorState);
depth = context.FindExistingNode(NodeType.Depth) as DepthGenerator;
if (depth == null)
throw new Exception(context.GlobalErrorState);
depth.AlternativeViewpointCapability.SetViewpoint(image);
gesture = context.FindExistingNode(NodeType.Gesture) as GestureGenerator;
if (gesture == null)
throw new Exception(context.GlobalErrorState);
gesture.AddGesture("RaiseHand");
gesture.GestureRecognized += new EventHandler<GestureRecognizedEventArgs>(GestureRecognized);
gesture.GestureProgress += new EventHandler<GestureProgressEventArgs> (GestureProgress);
hand = context.FindExistingNode(NodeType.Hands) as HandsGenerator;
if (hand == null)
throw new Exception(context.GlobalErrorState);
hand.HandCreate += new EventHandler<HandCreateEventArgs>(HandCreate);
hand.HandUpdate += new EventHandler<HandUpdateEventArgs>(HandUpdate);
context.StartGeneratingAll();
MapOutputMode map = image.MapOutputMode;
bitmap = new Bitmap((int)map.XRes, (int)map.YRes, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
run = true;
thread = new Thread(CallThread);
thread.Start();
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
}
public void GestureRecognized(object sender, GestureRecognizedEventArgs e)
{
gesstatus = GestureStatus.Recognized;
hand.StartTracking(e.EndPosition);
}
public void GestureProgress(object sender, GestureProgressEventArgs e)
{
gesstatus = GestureStatus.Progress;
}
public void HandCreate(object sender, HandCreateEventArgs e)
{
handstatus = HandsStatus.Create;
}
public void HandUpdate(object sender, HandUpdateEventArgs e)
{
handstatus = HandsStatus.Update;
handpoint.Enqueue(e.Position);
}
public void button2_Click(object sender, EventArgs e)
{
DialogResult result = MessageBox.Show("Do you want to quit?", "Confirm", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
if (result == DialogResult.OK)
{
try
{
run = false;
if (thread != null)
thread.Join();
this.Close();
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
}
}
public void CallThread()
{
try
{
while (run)
{
Data();
pictureBox1.Invalidate();
pictureBox2.Invalidate();
}
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
}
public unsafe void Data()
{
context.WaitAndUpdateAll();
ImageMetaData imd = image.GetMetaData();
lock (this)
{
Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
BitmapData data = bitmap.LockBits(rect, ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
byte* dstp = (byte*)data.Scan0.ToPointer();
byte* imstp = (byte*)image.ImageMapPtr.ToPointer();
for (int i = 0; i < imd.DataSize; i += 3, dstp += 3, imstp += 3)
{
dstp[0] = imstp[2];
dstp[1] = imstp[1];
dstp[2] = imstp[0];
}
bitmap.UnlockBits(data);
if (handpoint.Count != 0)
{
Point3D start = depth.ConvertRealWorldToProjective(handpoint.Peek());
foreach (Point3D hpoint in handpoint)
{
Point3D pt = depth.ConvertRealWorldToProjective(hpoint);
HandPosition(start);
start = pt;
}
}
string mess = "Gesture: RaiseHand" + " ,Status:" + gesstatus.ToString() + "\n" + "Hand: " + handstatus.ToString();
PicDraw(bitmap, mess);
}
}
public void HandPosition(Point3D pt)
{
try
{
float a,b,c;
string handx, handy, handz;
a=pt.X;
b=pt.Y;
c=pt.Z;
handx = a.ToString();
handy = b.ToString();
handz = c.ToString();
Graphics g = pictureBox2.CreateGraphics();
g.FillEllipse(brush, a - 5, b - 5, 20, 20);
textBox1.Text = handx;
textBox2.Text = handy;
textBox3.Text = handz;
g.Dispose();
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
}
public void PicDraw(Bitmap bmap, string me)
{
try
{
Graphics g;
pictureBox1.Image = bmap;
g = Graphics.FromImage(pictureBox1.Image);
g.DrawString(me, font, brush, point);
g.Dispose();
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
}
}
}
And this is my code in Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace HandTracking
{
static class Program
{
........
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 f1 = new Form1();
f1.Text = "Hand Tracking";
f1.StartPosition = FormStartPosition.CenterScreen;
Application.Run(f1);
}
}
}
When I compile the program many times, each time different errors are thrown: InvalidOperationException not handled; Cross-thread operation not valid: Control 'textBox1' accessed from a thread other than the thread it was created on; Object is currently in use elsewhere.
I don't know whether the way I pass parameters at: HandPosition(start) and PicDraw(bitmap, mess) were correct. Any problem will come out if I use HandPosition(start) to control a robot? Can anybody show me my mistakes and help me correct the progam?
The problem is that you are trying to access a WinForms control on a thread other than the UI thread. It is being done from the thread you are creating with Thread.Start.
A much better technique for Windows Forms is to use the BackgroundWorker approach (if you are using .NET 4, Task Parallel Library is very nice). With BackgroundWorker, you send the thread off to do some work, and it gives the UI thread updates, sending back any objects of your choice. Since you are newer to C#, BackgroundWorker is the right choice because it is simple to use, and there is tons of documentation on it if you get stuck.
On the UI thread, you just take those updates, and then update your WinForms controls from the UI thread. Problem fixed.
To learn more about BackgroundWorker, Google it, or you can start here:
http://www.codeproject.com/Articles/99143/BackgroundWorker-Class-Sample-for-Beginners