/// <summary> /// Free resources /// </summary> private void Cleanup() { if (hOldObject != IntPtr.Zero && hDCDest != IntPtr.Zero) { // restore selection (old handle) GDI32.SelectObject(hDCDest, hOldObject); GDI32.DeleteDC(hDCDest); } if (hDCDesktop != IntPtr.Zero) { User32.ReleaseDC(hWndDesktop, hDCDesktop); } if (hDIBSection != IntPtr.Zero) { // free up the Bitmap object GDI32.DeleteObject(hDIBSection); } if (disabledDWM) { DWM.EnableComposition(); } if (aviWriter != null) { aviWriter.Dispose(); aviWriter = null; string ffmpegexe = PluginUtils.GetExePath("ffmpeg.exe"); if (ffmpegexe != null) { try { string webMFile = filename.Replace(".avi", ".webm"); string arguments = "-i \"" + filename + "\" -codec:v libvpx -quality good -cpu-used 0 -b:v 1000k -qmin 10 -qmax 42 -maxrate 1000k -bufsize 4000k -threads 4 \"" + webMFile + "\""; LOG.DebugFormat("Starting {0} with arguments {1}", ffmpegexe, arguments); ProcessStartInfo processStartInfo = new ProcessStartInfo(ffmpegexe, arguments); processStartInfo.CreateNoWindow = false; processStartInfo.RedirectStandardOutput = false; processStartInfo.UseShellExecute = false; Process process = Process.Start(processStartInfo); process.WaitForExit(); if (process.ExitCode == 0) { MessageBox.Show("Recording written to " + webMFile); } } catch (Exception ex) { MessageBox.Show("Recording written to " + filename + " couldn't convert due to an error: " + ex.Message); } } else { MessageBox.Show("Recording written to " + filename); } } }
/// <summary> /// Free resources /// </summary> private void Cleanup() { if (hOldObject != IntPtr.Zero && hDCDest != IntPtr.Zero) { // restore selection (old handle) GDI32.SelectObject(hDCDest, hOldObject); GDI32.DeleteDC(hDCDest); } if (hDCDesktop != IntPtr.Zero) { User32.ReleaseDC(hWndDesktop, hDCDesktop); } if (hDIBSection != IntPtr.Zero) { // free up the Bitmap object GDI32.DeleteObject(hDIBSection); } if (aviWriter != null) { aviWriter.Dispose(); aviWriter = null; } }
public void Start(int framesPerSecond) { string filename; if (recordingWindow != null) { string windowTitle = Regex.Replace(recordingWindow.Text, @"[^\x20\d\w]", ""); if (string.IsNullOrEmpty(windowTitle)) { windowTitle = "greenshot-recording"; } filename = Path.Combine(conf.OutputFilePath, windowTitle + ".avi"); } else { filename = Path.Combine(conf.OutputFilePath, "greenshot-recording.avi"); } if (File.Exists(filename)) { try { File.Delete(filename); } catch {} } LOG.InfoFormat("Capturing to {0}", filename); if (recordingWindow != null) { LOG.InfoFormat("Starting recording Window '{0}', {1}", recordingWindow.Text, recordingWindow.ClientRectangle); recordingSize = recordingWindow.ClientRectangle.Size; } else { LOG.InfoFormat("Starting recording rectangle {0}", recordingRectangle); recordingSize = recordingRectangle.Size; } if (recordingSize.Width % 8 > 0) { LOG.InfoFormat("Correcting width to be factor 8, {0} => {1}", recordingSize.Width, recordingSize.Width + (8 - (recordingSize.Width % 8))); recordingSize = new Size(recordingSize.Width + (8 - (recordingSize.Width % 8)), recordingSize.Height); } if (recordingSize.Height % 8 > 0) { LOG.InfoFormat("Correcting Height to be factor 8, {0} => {1}", recordingSize.Height, recordingSize.Height + (8 - (recordingSize.Height % 8))); recordingSize = new Size(recordingSize.Width, recordingSize.Height + (8 - (recordingSize.Height % 8))); } this.framesPerSecond = framesPerSecond; // "P/Invoke" Solution for capturing the screen hWndDesktop = User32.GetDesktopWindow(); // get te hDC of the target window hDCDesktop = User32.GetWindowDC(hWndDesktop); // Make sure the last error is set to 0 Win32.SetLastError(0); // create a device context we can copy to hDCDest = GDI32.CreateCompatibleDC(hDCDesktop); // Check if the device context is there, if not throw an error with as much info as possible! if (hDCDest == IntPtr.Zero) { // Get Exception before the error is lost Exception exceptionToThrow = CreateCaptureException("CreateCompatibleDC", recordingSize); // Cleanup User32.ReleaseDC(hWndDesktop, hDCDesktop); // throw exception throw exceptionToThrow; } // Create BitmapInfoHeader for CreateDIBSection BitmapInfoHeader bitmapInfoHeader = new BitmapInfoHeader(recordingSize.Width, recordingSize.Height, 32); // Make sure the last error is set to 0 Win32.SetLastError(0); // create a bitmap we can copy it to, using GetDeviceCaps to get the width/height hDIBSection = GDI32.CreateDIBSection(hDCDesktop, ref bitmapInfoHeader, BitmapInfoHeader.DIB_RGB_COLORS, out bits0, IntPtr.Zero, 0); if (hDIBSection == IntPtr.Zero) { // Get Exception before the error is lost Exception exceptionToThrow = CreateCaptureException("CreateDIBSection", recordingSize); exceptionToThrow.Data.Add("hdcDest", hDCDest.ToInt32()); exceptionToThrow.Data.Add("hdcSrc", hDCDesktop.ToInt32()); // clean up GDI32.DeleteDC(hDCDest); User32.ReleaseDC(hWndDesktop, hDCDesktop); // Throw so people can report the problem throw exceptionToThrow; } // Create a GDI Bitmap so we can use GDI and GDI+ operations on the same memory GDIBitmap = new Bitmap(recordingSize.Width, recordingSize.Height, 32, PixelFormat.Format32bppArgb, bits0); // select the bitmap object and store the old handle hOldObject = GDI32.SelectObject(hDCDest, hDIBSection); stop = false; aviWriter = new AVIWriter(); // Comment the following 2 lines to make the user select it's own codec //aviWriter.Codec = "msvc"; //aviWriter.Quality = 99; aviWriter.FrameRate = framesPerSecond; aviWriter.Open(filename, recordingSize.Width, recordingSize.Height); // Start update check in the background backgroundTask = new Thread(new ThreadStart(CaptureFrame)); backgroundTask.IsBackground = true; backgroundTask.Start(); }