ByteScout Screen Capturing SDK - C# - Capture From Separate Thread - ByteScout
Announcement
Our ByteScout SDK products are sunsetting as we focus on expanding new solutions.
Learn More Open modal
Close modal
Announcement Important Update
ByteScout SDK Sunsetting Notice
Our ByteScout SDK products are sunsetting as we focus on our new & improved solutions. Thank you for being part of our journey, and we look forward to supporting you in this next chapter!

ByteScout Screen Capturing SDK – C# – Capture From Separate Thread

  • Home
  • /
  • Articles
  • /
  • ByteScout Screen Capturing SDK – C# – Capture From Separate Thread

ByteScout Screen Capturing SDK – C# – Capture From Separate Thread

CapturingThread.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Drawing;
using BytescoutScreenCapturingLib;

// NOTE: if you are getting error like "invalid image" related to loading the SDK's dll then 
// try to do the following:
// 1) remove the reference to the SDK by View - Solution Explorer
// then click on References, select Bytescout... reference name and right-click it and select Remove
// 2) To re-add click on the menu: Project - Add Reference
// 3) In "Add Reference" dialog switch to "COM" tab and find Bytescout...
// 4) Select it and click "Add" 
// 5) Recompile the application 
// Note: if you need to run on both x64 and x86 then please make sure you have set "Embed Interop Types" to True for this reference


namespace CaptureFromSeparateThread
{
	public class CapturingThread
	{
		public static void ThreadProc(Object obj)
		{
		    CapturingThreadData data = (CapturingThreadData) obj;
		    data.Success = true;

		    // Prepare Capturer:

		    Capturer capturer = new Capturer(); // create new screen capturer object

		    capturer.RegistrationName = "demo";
		    capturer.RegistrationKey = "demo";

		    capturer.CaptureRectLeft = data.CaptureRectangle.Left;
		    capturer.CaptureRectTop = data.CaptureRectangle.Top;
		    capturer.CaptureRectWidth = data.CaptureRectangle.Width;
		    capturer.CaptureRectHeight = data.CaptureRectangle.Height;

		    capturer.OutputWidth = 640;
		    capturer.OutputHeight = 480;

		    // WMV and WEBM output use WMVVideoBitrate property to control output video bitrate
		    // so try to increase it by x2 or x3 times if you think the output video are you are getting is laggy
		    // capturer.WMVVideoBitrate = capturer.WMVVideoBitrate * 2;

		    capturer.CaptureRectWidth = 320;
		    capturer.CaptureRectHeight = 240;

		    data.TempFile = Path.GetTempFileName();
		    data.TempFile = Path.ChangeExtension(data.TempFile, ".wmv");

		    capturer.OutputFileName = data.TempFile;
		    capturer.CapturingType = data.CaptureType;

		    // set border around captured area if we are not capturing entire screen
		    if (capturer.CapturingType != CaptureAreaType.catScreen &&
		        capturer.CapturingType != CaptureAreaType.catWebcamFullScreen)
		    {
		        capturer.CaptureAreaBorderType = CaptureAreaBorderType.cabtDashed;
		        capturer.CaptureAreaBorderColor = (uint) ColorTranslator.ToOle(Color.Red);
		    }


		    // Wait for events:

		    WaitHandle[] events = new WaitHandle[] {data.StartOrResumeEvent, data.PauseEvent, data.StopEvent};
		    
            try
		    {
                while (true)
                {
                    int i = WaitHandle.WaitAny(events);

                    if (events[i] == data.StartOrResumeEvent)
                    {
                        if (!capturer.IsRunning)
                            capturer.Run();
                    }
                    else if (events[i] == data.PauseEvent)
                    {
                        if (capturer.IsRunning)
                            capturer.Pause();
                    }
                    else if (events[i] == data.StopEvent)
                    {
                        capturer.Stop();
                        break;
                    }
                }
		    }
		    catch (Exception ex)
		    {
		        data.ErrorText = ex.Message;
		        data.Success = false;
		    }
		    finally
		    {
		        // Release resources
		        Marshal.ReleaseComObject(capturer);
		    }
		}
	}
}

CapturingThreadData.cs

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Threading;
using BytescoutScreenCapturingLib;


// NOTE: if you are getting error like "invalid image" related to loading the SDK's dll then 
// try to do the following:
// 1) remove the reference to the SDK by View - Solution Explorer
// then click on References, select Bytescout... reference name and right-click it and select Remove
// 2) To re-add click on the menu: Project - Add Reference
// 3) In "Add Reference" dialog switch to "COM" tab and find Bytescout...
// 4) Select it and click "Add" 
// 5) Recompile the application 



namespace CaptureFromSeparateThread
{
	public class CapturingThreadData
	{
		public CaptureAreaType CaptureType;
		public String TempFile;
        public Rectangle CaptureRectangle = new Rectangle(0, 0, 320, 240);

		public bool Success;
		public string ErrorText;

	    public AutoResetEvent StartOrResumeEvent = new AutoResetEvent(false); // event signalling to start or resume the recodring
	    public AutoResetEvent PauseEvent = new AutoResetEvent(false); // event signalling to pause the recodring
	    public AutoResetEvent StopEvent = new AutoResetEvent(false); // event signalling to stop the recording 
	}
}

Form1.cs

using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using BytescoutScreenCapturingLib;

// NOTE: if you are getting error like "invalid image" related to loading the SDK's dll then 
// try to do the following:
// 1) remove the reference to the SDK by View - Solution Explorer
// then click on References, select Bytescout... reference name and right-click it and select Remove
// 2) To re-add click on the menu: Project - Add Reference
// 3) In "Add Reference" dialog switch to "COM" tab and find Bytescout...
// 4) Select it and click "Add" 
// 5) Recompile the application 
// Note: if you need to run on both x64 and x86 then please make sure you have set "Embed Interop Types" to True for this reference


namespace CaptureFromSeparateThread
{
	public partial class Form1 : Form
	{
		private Thread _capturingThread;
		private CapturingThreadData _capturingThreadData; // data to exchange between form and capturing thread
	    
        public Form1()
		{
			InitializeComponent();

            _capturingThreadData = new CapturingThreadData();
            
            cmbCapturingType.SelectedIndex = 0;
		}

		private void btnStart_Click(object sender, EventArgs e)
		{
			CaptureAreaType captureType = CaptureAreaType.catMouse;
			
			if (cmbCapturingType.SelectedIndex == 1)
				captureType = CaptureAreaType.catScreen;

			StartRecording(captureType);
		}

	    private void btnPauseResume_Click(object sender, EventArgs e)
	    {
            PauseOrResumeRecording();
	    }

	    private void btnStop_Click(object sender, EventArgs e)
		{
			StopRecording();
		}

		private void StartRecording(CaptureAreaType captureType)
		{
			btnStart.Enabled = false;
			btnPauseResume.Enabled = true;
			btnStop.Enabled = true;

			_capturingThreadData.CaptureType = captureType;

            // Start thread
			_capturingThread = new Thread(CapturingThread.ThreadProc);
			_capturingThread.Start(_capturingThreadData);

            // Signal to start the recording
		    _capturingThreadData.StartOrResumeEvent.Set();
		}

	    private void PauseOrResumeRecording()
	    {
            btnStart.Enabled = false;
            btnPauseResume.Enabled = true;
            btnStop.Enabled = true;

	        if (btnPauseResume.Text == "Pause")
	        {
                // Signal to pause
                _capturingThreadData.PauseEvent.Set();
	            btnPauseResume.Text = "Resume";
	        }
	        else
	        {
                // Signal to resume
                _capturingThreadData.StartOrResumeEvent.Set();
                btnPauseResume.Text = "Pause";
	        }
	    }

	    private void StopRecording()
		{
            Cursor = Cursors.WaitCursor;

            // Signal to stop
            _capturingThreadData.StopEvent.Set();

			try
			{
				_capturingThread.Join();
			}
			finally
			{
				Cursor = Cursors.Default;
			}

			if (!_capturingThreadData.Success)
			{
				MessageBox.Show("Capturing failed. Error: " + _capturingThreadData.ErrorText);
			}
			else
			{
				SaveFileDialog dlg = new SaveFileDialog();
				dlg.DefaultExt = "*.wmv";
				dlg.Filter = "WMV files (*.wmv)|*.wmv|All files (*.*)|*.*";

				dlg.FileName = "Screencast";
				dlg.Title = "Save captured video as";
				
				if (dlg.ShowDialog() == DialogResult.OK)
				{
					File.Copy(_capturingThreadData.TempFile, dlg.FileName, true);
					
					Process.Start(dlg.FileName); // start the video in default associated application
				}
				
				File.Delete(_capturingThreadData.TempFile);
			}

            btnStart.Enabled = true;
            btnPauseResume.Enabled = false;
            btnStop.Enabled = false;
            btnPauseResume.Text = "Pause";
		}

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _capturingThreadData.StopEvent.Set();
        }
	}
}

Program.cs

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace CaptureFromSeparateThread
{
	static class Program
	{
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main()
		{
			Application.EnableVisualStyles();
			Application.SetCompatibleTextRenderingDefault(false);
			Application.Run(new Form1());
		}
	}
}

Tutorials:

prev
next