I want to show how many times I open and close the valve in the text box in the application I control, but I can only see the result when the process is finished, I cannot see it in real time.
private void button6_Click(object sender, EventArgs e)
{
sayacValue = 0;
int LoopCount = Convert.ToInt32(textBox_send.Text);
for (int s = 0; s < LoopCount; s++)
{
OpenValf();
IncreaseValfValue();
System.Threading.Thread.Sleep(400);
CloseValf();
System.Threading.Thread.Sleep(400);
}
}
public int IncreaseValfValue() //Counter Control Function
{
sayacValue++;
sayac.Text = sayacValue.ToString();
return sayacValue;
}
How can I do it using Thread or any other method?
You should use Microsoft's Reactive Framework (aka Rx) - NuGet System.Reactive.Windows.Forms - then you can do this:
using System;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reactive.Linq;
using System.Reactive.Disposables;
namespace WindowsFormsApp
{
public partial class ExampleForm : Form
{
public ExampleForm()
{
InitializeComponent();
}
private SerialDisposable _subscription = new SerialDisposable();
private void button6_Click(object sender, EventArgs e)
{
if (int.TryParse(textBox_send.Text, out int LoopCount))
{
if (LoopCount > 0)
{
_subscription.Disposable =
Observable
.Interval(TimeSpan.FromMilliseconds(400.0))
.Take(LoopCount + 1)
.ObserveOn(this)
.Subscribe(
x => sayac.Text = $"{x}",
() => sayac.Text = "Done.");
}
}
}
}
}
Related
How to work with richtextbox asynchronously? For example, I have a class and an event that logs some kind of calculation
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ExampleProject
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//I subscribe to an event that often sends messages
//and I want to display
var c = new Core();
c.Notify += DisplayMessage;
c.ExampleMethod();
}
private void DisplayMessage(object sender, LogEventArgs e)
{ //When a event arrives, transfer to richTextBox1
richTextBox1.AppendText("\r\n" + e.Date.ToString("dd/MM/yyyy HH:mm:ss "), Color.SlateGray);
richTextBox1.AppendText(e.Message, Color.Blue);
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.ScrollToCaret();
}
}
class Core
{
public delegate void LogHandler(object sender, LogEventArgs e);
public event LogHandler Notify;
//
public void ExampleMethod()
{
//generate messages with a pause in a random value
var rand = new Random();
for (int i = 1; i < 10000; i++)
{ var pause = rand.Next(50, 2000);
Thread.Sleep(pause);
Notify?.Invoke(this, new LogEventArgs($"logged {i} pause in miliseconds {pause}", DateTime.Now, MessageType.Notice));
}
}
} //The class in which log messages are placed
class LogEventArgs
{
public string Message { get; }
public DateTime Date { get; }
public MessageType MessageType { get; }
public LogEventArgs(string mes, DateTime date, MessageType messageType)
{
Message = mes;
Date = date;
MessageType = messageType;
}
}
enum MessageType
{
Notice,
Warning,
Error,
}
//Extension method to set line colors in RichTextBox
public static class RichTextBoxExtensions
{
public static void AppendText(this RichTextBox box, string text, Color color)
{
box.SelectionStart = box.TextLength;
box.SelectionLength = 0;
box.SelectionColor = color;
box.AppendText(text);
box.SelectionColor = box.ForeColor;
}
}
}
Tried options with backgroundworker, task , synchronization... and got no result. I'm surprised that WinForms have been around for many years and Microsoft hasn't added asynchronous actions to them, for example AppendTextAsync(). How can I force text to be added asynchronously to a richtextbox?
Put another textbox on your form
Paste this code over ther top of everything in your Form1.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ExampleProject
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
var c = new Core();
c.Notify += DisplayMessage;
await c.ExampleMethod();
}
private void DisplayMessage(object sender, LogEventArgs e)
{
richTextBox1.AppendText("\r\n" + e.Date.ToString("dd/MM/yyyy HH:mm:ss "), Color.SlateGray);
richTextBox1.AppendText(e.Message, Color.Blue);
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.ScrollToCaret();
}
}
class Core
{
public delegate void LogHandler(object sender, LogEventArgs e);
public event LogHandler Notify;
public async Task ExampleMethod()
{
var rand = new Random();
for (int i = 1; i < 10000; i++)
{ var pause = rand.Next(50, 200);
await Task.Delay(pause);
Notify?.Invoke(this, new LogEventArgs($"logged {i} pause in miliseconds {pause}", DateTime.Now, MessageType.Notice));
}
}
}
class LogEventArgs
{
public string Message { get; }
public DateTime Date { get; }
public MessageType MessageType { get; }
public LogEventArgs(string mes, DateTime date, MessageType messageType)
{
Message = mes;
Date = date;
MessageType = messageType;
}
}
enum MessageType
{
Notice,
Warning,
Error,
}
public static class RichTextBoxExtensions
{
public static void AppendText(this RichTextBox box, string text, Color color)
{
box.SelectionStart = box.TextLength;
box.SelectionLength = 0;
box.SelectionColor = color;
box.AppendText(text);
box.SelectionColor = box.ForeColor;
}
}
}
Run it, click the button, then carry on typing in the other textbox - it stays responsive etc.. I don't know how long you'll have to wait to see major slowdowns as the text in the RTB gets huge.. but really you should look at periodically clipping your log so you arent building up megabytes of text in the RTB
Async in winforms is not about getting the controls to update using some async fashion; control must only be accessed by the thread that created them so any interaction with a control we generally ask that thread to do it (but I suppose it's a matter of perspective: if a background thread is asking the UI thread to update a control then it's being done asyncronous to whatever work the background thread is doing) - make sure the access you do with them is quick, do your heavy lifting (API calls?) using async way and then Invoke to get your UI thread to update the controls.
Hello this is my first time when i program in C# and first time when i use xamarin,and i maked this code on xamarin as a first project.
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Counter
{
public partial class MainPage : ContentPage
{
private int count = 0;
private int squared = 0;
private double sqroot = 0;
private int milliseconds = 500;
private bool direction = true;
public MainPage()
{
InitializeComponent();
}
private void IncrementCounterClicked(object sender, EventArgs e)
{
direction = true;
}
private void Button_Clicked(object sender, EventArgs e)
{
direction = false;
}
private void Auto_increment()
{
if (direction == true)
count++;
else
count--;
squared = count * count;
sqroot = Math.Sqrt(count);
CounterLabel.Text = count.ToString();
Squared.Text = squared.ToString();
Sqroot.Text = sqroot.ToString();
Task.Delay(1000);
}
}
}
How can i run the function Auto_Increment every time the code executes?
I would use it on an android device, if it matters.
And also how i can display only first 2 digits of the double variable?
As far as I know If you want to use it for an android app which is build using xamarin you could actually use the lifecycle function given below:
protected override void OnResume()
{
#CALL_YOUR_FUNCTION_HERE
}
and to round the double values you could use the round method which is given below:
Math.Round(#Value_to_be_rounded, #number_of_decimal_places)
For instance: Math.Round(3.56, 1) will give you 3.5
Hope this helps.
Try doing this. Note that this solution isn't a good one. You have to control this infite loop in Auto_increment() or find another way to run it continiously in a cleaner way. Add a new button and replace the while(true) with while(yourBoolean) that you control by clicking the new button (like you already do for the increment.
public partial class MainPage : ContentPage
{
private int count = 0;
private int squared = 0;
private double sqroot = 0;
private int milliseconds = 500;
private bool direction = true;
public MainPage()
{
InitializeComponent();
Auto_increment();
}
private void IncrementCounterClicked(object sender, EventArgs e)
{
direction = true;
}
private void Button_Clicked(object sender, EventArgs e)
{
direction = false;
}
private void Auto_increment()
{
while (true) {
if (direction == true)
count++;
else
count--;
squared = count * count;
sqroot = Math.Sqrt(count);
CounterLabel.Text = count.ToString();
Squared.Text = squared.ToString();
Sqroot.Text = sqroot.ToString();
Task.Delay(1000);
}
}
}
PS : Also note that you should follow the Naming Guidelines in your code. In your case rename your private method AutoIncrement().
Hope this will help you.
I'm creating an add in for Microsoft Excel that includes a ribbon tab. On this tab is a button with the following code:
public void setAccounts()
{
foreach (Excel.Worksheet displayWorksheet in Globals.ThisAddIn.Application.Worksheets)
{
displayWorksheet.Range[budget_cell].Value2 = "$" + Convert.ToString(budget);
displayWorksheet.Range[account_cell].Value2 = "$0.00";
displayWorksheet.Range[transaction_cell].Value2 = "Amount";
}
}
The button opens up a separate form where the user specifies budget_cell, account_cell, and transaction_cell. I then pass that data to the above code in SolutionName.ThisAddIn.cs (where SolutionName is the namespace of the solution). Strictly speaking, the code works. However, the data doesn't show up in the cells until the button is pressed a second time. Why is that? Is it because I'm retrieving the data from a different object in the solution?
Also, I've been trying to get this code and the aforementioned form to activate when the add in first starts up.
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
frmStartup startup = new frmStartup();
startup.Show();
setAccounts();
}
I've been at this for a good twelve hours now, and I can't get it to work. What am I missing?
ThisAddIn.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Excel;
namespace AccountingAddIn
{
public partial class ThisAddIn
{
public static string budget_cell = "";
public static string account_cell = "";
public static string transaction_cell = "";
public static string date_cell = "";
public static string time_cell = "";
public static string description_cell = "";
public static bool date = false;
public static bool time = false;
public static bool description = false;
public static decimal budget = 0;
List<Account> accounts = new List<Account>();
public void budgetStartUp()
{
frmStartup startup = new frmStartup();
startup.Show();
setAccounts();
}
public void setAccounts()
{
foreach (Excel.Worksheet displayWorksheet in Globals.ThisAddIn.Application.Worksheets)
{
displayWorksheet.Range[budget_cell].Value2 = "$" + Convert.ToString(budget);
displayWorksheet.Range[account_cell].Value2 = "$0.00";
displayWorksheet.Range[transaction_cell].Value2 = "Amount";
if (date == true)
{
displayWorksheet.Range[date_cell].Value2 = "Date";
}
if (time == true)
{
displayWorksheet.Range[time_cell].Value2 = "Time";
}
if (description == true)
{
displayWorksheet.Range[description_cell].Value2 = "Description";
}
Account na = new Account(0, displayWorksheet);
accounts.Add(na);
}
}
protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
return Globals.Factory.GetRibbonFactory().CreateRibbonManager(
new Microsoft.Office.Tools.Ribbon.IRibbonExtension[] { new MyRibbon() });
}
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
CreateRibbonExtensibilityObject();
budgetStartUp();
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
}
}
frmStartup.cs:
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 AccountingAddIn
{
public partial class frmStartup : Form
{
public frmStartup()
{
InitializeComponent();
}
private void btnHelp_Click(object sender, EventArgs e)
{
MessageBox.Show("Please enter a starting amount for your budget and " +
"which cells will display the running total for your " +
"accounts." +
"\n\nNote: Leaving the budget blank will" +
" result in a starting budget of $0.00.");
}
private void btnOkay_Click(object sender, EventArgs e)
{
AccountingSeminar.ThisAddIn.budget += Convert.ToDecimal(txtStartingAmount.Text);
AccountingSeminar.ThisAddIn.budget_cell = txtBudget.Text;
AccountingSeminar.ThisAddIn.account_cell = txtAccount.Text;
AccountingSeminar.ThisAddIn.transaction_cell = txtTransaction.Text;
if (chkDate.Checked)
{
AccountingSeminar.ThisAddIn.date_cell = txtDate.Text;
AccountingSeminar.ThisAddIn.date = true;
}
if (chkTime.Checked)
{
AccountingSeminar.ThisAddIn.time_cell = txtTime.Text;
AccountingSeminar.ThisAddIn.time = true;
}
if (chkDescription.Checked)
{
AccountingSeminar.ThisAddIn.description_cell = txtDescription.Text;
AccountingSeminar.ThisAddIn.description = true;
}
Close();
}
}
}
I have a main form with a progress bar on it, and I would like to update the progress bar from an external class called "Logic"... however, Logic is already being referenced to on the main form. If I try to reference the main form in the Logic to update the progress bar, I just get stack overflows.
While searching around, I came across a lot of topics about a BackgroundWorker... but that's not what I'm trying to use. I have specific places in my Logic class where I want to update the progress bar on the main form by using progressbar.PerformStep(). I've tried creating a method on the main form to update the progress bar and calling that from the Logic class, but once again it's lacking a reference... and I can't just use MainForm frm1 = new MainForm() without causing errors everywhere else. I'm feeling pretty stumped here.
[edit]
Here is the code with the solution (thanks to you guys)----
Main Form:
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 Natural_Language_Processor
{
public partial class frm_Main : Form
{
Logic logic = new Logic();
public frm_Main()
{
InitializeComponent();
}
private void frm_Main_Load(object sender, EventArgs e)
{
Timer.Start();
}
private void btn_Enter_Click(object sender, EventArgs e)
{
logic.Progress += new Logic.ProgressDelegate(DisplayProgess);
logic.RaiseProgress(0);
logic.str_Input = txt_Input.Text;
logic.Prep_Input();
txt_Input.Text = "";
logic.RaiseProgress(100);
System.Threading.Thread.Sleep(100);
logic.RaiseProgress(0);
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void eraseToolStripMenuItem_Click(object sender, EventArgs e)
{
logic.EraseMemory();
}
public void DisplayProgess(int percent)
{
if (this.InvokeRequired)
{
this.Invoke(new Logic.ProgressDelegate(DisplayProgess), new Object[] { percent });
}
else
{
this.progbar.Value = percent;
}
}
}
Logic:
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace Natural_Language_Processor
{
class Logic
{
Data oData = new Data();
public List<string> Words = new List<string>();
private System.Threading.Thread T = null;
public delegate void ProgressDelegate(int percent);
public event ProgressDelegate Progress;
#region Variables
public string str_Input;
public string[] WordArray;
#endregion
public void RaiseProgress(int percent)
{
if (Progress != null)
{
Progress(percent);
}
}
public void Prep_Input()
{
//Check for Input
if (String.IsNullOrEmpty(str_Input))
{
}
else
{
//Set everything to lower-case
str_Input = str_Input.ToLower();
RaiseProgress(10);
//Remove all punctuation
if (str_Input.Contains(","))
{
while (str_Input.Contains(","))
{
int int_index = str_Input.IndexOf(",");
str_Input = str_Input.Remove(int_index, 1);
}
}
if (str_Input.EndsWith("."))
{
str_Input = str_Input.Trim('.');
}
else if (str_Input.EndsWith("?"))
{
str_Input = str_Input.Trim('?');
}
RaiseProgress(20);
//Split the sentence into an array of individual words
WordArray = str_Input.Split(' ');
RaiseProgress(30);
//Get current words (and max ID) from the database
int max_index = 0;
oData.GetWords();
Words.Clear();
if (oData.WordDataSet.Count > 0)
{
for (int i = 0; i < oData.WordDataSet.Count; i++)
{
max_index = oData.WordDataSet[i].ID;
Words.Add(oData.WordDataSet[i].Word);
}
}
RaiseProgress(40);
//Check each word in the sentence
for (int i = 0; i < WordArray.Length; i++)
{
//Update the frequency of an existing word in the database
if (Words.Contains(WordArray[i].ToString()))
{
oData.UpdateWords(WordArray[i].ToString());
}
else
{
//Or add the word
max_index = max_index + 1;
oData.InsertWordsTable(max_index, WordArray[i].ToString(), 1);
//And create its pre/pro word tables
oData.NewPreWordTable(WordArray[i].ToString());
oData.NewProWordTable(WordArray[i].ToString());
}
}
RaiseProgress(50);
//Check each word in the sentence after we have possibly created new pre/pro word tables in the previous code
for (int i = 1; i < WordArray.Length; i++)
{
oData.GetPreWords(WordArray[i].ToString());
Words.Clear();
//Get current pre_words from the database
for (int a = 0; a < oData.WordDataSet.Count; a++)
{
Words.Add(oData.WordDataSet[a].Word);
}
//Update the frequency of an existing word in the database
if (Words.Contains(WordArray[i - 1].ToString()))
{
oData.UpdatePreWords(WordArray[i].ToString(), WordArray[i - 1].ToString());
}
else
{
//Or add the word
oData.InsertPreWord(WordArray[i].ToString(), oData.GetPreWordIndex(WordArray[i].ToString()), WordArray[i - 1].ToString(), 1);
}
if (i == WordArray.Length - 1)
{
}
else
{
oData.GetProWords(WordArray[i].ToString());
Words.Clear();
//Get current pro_words from the database
for (int b = 0; b < oData.WordDataSet.Count; b++)
{
Words.Add(oData.WordDataSet[b].Word);
}
//Update the frequency of an existing word in the database
if (Words.Contains(WordArray[i + 1].ToString()))
{
oData.UpdateProWords(WordArray[i].ToString(), WordArray[i + 1].ToString());
}
else
{
//Or add the word
oData.InsertProWord(WordArray[i].ToString(), oData.GetProWordIndex(WordArray[i].ToString()), WordArray[i + 1].ToString(), 1);
}
}
}
RaiseProgress(60);
}
}
public void Respond()
{
RaiseProgress(70);
}
public void EraseMemory()
{
oData.GetWords();
Words.Clear();
for (int i = 0; i < oData.WordDataSet.Count; i++)
{
oData.DeletePreTable(oData.WordDataSet[i].Word);
oData.DeleteProTable(oData.WordDataSet[i].Word);
}
oData.DeleteWordsTable();
MessageBox.Show("Memory has been erased.");
}
}
}
Here's a loosely coupled approach, with the Logic() class raising a custom event instead of directly referencing the Form:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Logic logic = new Logic();
logic.Progress += new Logic.ProgressDelegate(DisplayProgess);
logic.Start();
}
public void DisplayProgess(string message, int percent)
{
if (this.InvokeRequired)
{
this.Invoke(new Logic.ProgressDelegate(DisplayProgess), new Object[] { message, percent });
}
else
{
this.label1.Text = message;
this.progressBar1.Value = percent;
}
}
}
public class Logic
{
private System.Threading.Thread T = null;
public delegate void ProgressDelegate(string message, int percent);
public event ProgressDelegate Progress;
public void Start()
{
if (T == null)
{
T = new System.Threading.Thread(new System.Threading.ThreadStart(Worker));
T.Start();
}
}
private void Worker()
{
RaiseProgress("Initializing...", 0);
System.Threading.Thread.Sleep(1000); // simulated work
RaiseProgress("Loading Map...", 25);
System.Threading.Thread.Sleep(1500); // simulated work
RaiseProgress("Loading Sprites...", 50);
System.Threading.Thread.Sleep(1200); // simulated work
RaiseProgress("Loading Sound Effects...", 75);
System.Threading.Thread.Sleep(1700);
RaiseProgress("Loading Music...", 85);
System.Threading.Thread.Sleep(1100); // simulated work
RaiseProgress("Done!", 100);
}
private void RaiseProgress(string message, int percent)
{
if (Progress != null)
{
Progress(message, percent);
}
}
}
i am currently learning on QR code webcam decoder. i have taken an example from https://zxingnet.svn.codeplex.com/svn/trunk/Clients/AForgeDemo/ and have succesfully build it without error. however when i run it with my webcam connected, no input or it wont switch on the webcam. based on my understanding, the webcam would be switch on when user select it at combobox. well, since there is no error at build, i cant pinpoint what went wrong. i have also taken a look at a project which switch on the webcam when user press a button and i plan to implement it to the current project. i have already insert the button but i do not know what should i program at the button to switch on the webcam instead on having to choose at combobox
would someone kindly advise or guide me through it.
below is the main program, and 2 class
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 AForge.Video;
using ZXing;
using System.Threading;
namespace AForgeDemo
{
public partial class AForgeDemoForm : Form
{
private struct Device
{
public int Index;
public string Name;
public override string ToString()
{
return Name;
}
}
private readonly CameraDevices camDevices;
private Bitmap currentBitmapForDecoding;
private readonly Thread decodingThread;
private Result currentResult;
private readonly Pen resultRectPen;
public AForgeDemoForm()
{
InitializeComponent();
camDevices = new CameraDevices();
decodingThread = new Thread(DecodeBarcode);
decodingThread.Start();
pictureBox1.Paint += pictureBox1_Paint;
resultRectPen = new Pen(Color.Green, 10);
}
void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (currentResult == null)
return;
if (currentResult.ResultPoints != null && currentResult.ResultPoints.Length > 0)
{
var resultPoints = currentResult.ResultPoints;
var rect = new Rectangle((int)resultPoints[0].X, (int)resultPoints[0].Y, 1, 1);
foreach (var point in resultPoints)
{
if (point.X < rect.Left)
rect = new Rectangle((int)point.X, rect.Y, rect.Width + rect.X - (int)point.X, rect.Height);
if (point.X > rect.Right)
rect = new Rectangle(rect.X, rect.Y, rect.Width + (int)point.X - rect.X, rect.Height);
if (point.Y < rect.Top)
rect = new Rectangle(rect.X, (int)point.Y, rect.Width, rect.Height + rect.Y - (int)point.Y);
if (point.Y > rect.Bottom)
rect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height + (int)point.Y - rect.Y);
}
using (var g = pictureBox1.CreateGraphics())
{
g.DrawRectangle(resultRectPen, rect);
}
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
LoadDevicesToCombobox();
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (!e.Cancel)
{
decodingThread.Abort();
if (camDevices.Current != null)
{
camDevices.Current.NewFrame -= Current_NewFrame;
if (camDevices.Current.IsRunning)
{
camDevices.Current.SignalToStop();
}
}
}
}
private void LoadDevicesToCombobox()
{
cmbDevice.Items.Clear();
for (var index = 0; index < camDevices.Devices.Count; index++)
{
cmbDevice.Items.Add(new Device { Index = index, Name = camDevices.Devices[index].Name });
}
}
private void cmbDevice_SelectedIndexChanged(object sender, EventArgs e)
{
if (camDevices.Current != null)
{
camDevices.Current.NewFrame -= Current_NewFrame;
if (camDevices.Current.IsRunning)
{
camDevices.Current.SignalToStop();
}
}
camDevices.SelectCamera(((Device)(cmbDevice.SelectedItem)).Index);
camDevices.Current.NewFrame += Current_NewFrame;
camDevices.Current.Start();
}
private void Current_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
if (IsDisposed)
{
return;
}
try
{
if (currentBitmapForDecoding == null)
{
currentBitmapForDecoding = (Bitmap)eventArgs.Frame.Clone();
}
Invoke(new Action<Bitmap>(ShowFrame), eventArgs.Frame.Clone());
}
catch (ObjectDisposedException)
{
// not sure, why....
}
}
private void ShowFrame(Bitmap frame)
{
if (pictureBox1.Width < frame.Width)
{
pictureBox1.Width = frame.Width;
}
if (pictureBox1.Height < frame.Height)
{
pictureBox1.Height = frame.Height;
}
pictureBox1.Image = frame;
}
private void DecodeBarcode()
{
var reader = new BarcodeReader();
while (true)
{
if (currentBitmapForDecoding != null)
{
var result = reader.Decode(currentBitmapForDecoding);
if (result != null)
{
Invoke(new Action<Result>(ShowResult), result);
}
currentBitmapForDecoding.Dispose();
currentBitmapForDecoding = null;
}
Thread.Sleep(200);
}
}
private void ShowResult(Result result)
{
currentResult = result;
txtBarcodeFormat.Text = result.BarcodeFormat.ToString();
txtContent.Text = result.Text;
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}
the class for cameradevice
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AForge.Video.DirectShow;
namespace AForgeDemo
{
internal class CameraDevices
{
public FilterInfoCollection Devices { get; private set; }
public VideoCaptureDevice Current { get; private set; }
public CameraDevices()
{
Devices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
}
public void SelectCamera(int index)
{
if (index >= Devices.Count)
{
throw new ArgumentOutOfRangeException("index");
}
Current = new VideoCaptureDevice(Devices[index].MonikerString);
}
}
}
again, i kindly ask for anybody help on what i shall put at the button command to activate the webcam directly instead of choosing from combobox
thanks a million
The code which you need for your event handler behind the button is similar to the code within the method cmbDevice_SelectedIndexChanged.
I think it should look like the following
// select the first available camera and start capturing
camDevices.SelectCamera(0);
camDevices.Current.NewFrame += Current_NewFrame;
camDevices.Current.Start();
But I think the main challenge is to find out why the original example doesn't work as expected. It makes no difference if the same code is called in the handler of the combobox or in the handler of the button.