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()); } } }