如何使用Mono C#截取屏幕截图?

我正在尝试使用代码在Mono C#中获取屏幕截图,但是当我调用CopyFromScreen时,我得到一个System.NotImplementedException。 我的代码适用于.NET,那么是否有另一种使用Mono获取屏幕截图的方法?

Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); Graphics graphics = Graphics.FromImage(bitmap as Image); graphics.CopyFromScreen(0, 0, 0, 0, bitmap.Size); System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(); bitmap.Save(memoryStream, imageFormat); bitmap.Save(@"\tmp\screenshot.png", ImageFormat.Png); 

我使用的是Mono JIT编译器版本2.4.2.3(Debian 2.4.2.3 + dfsg-2)

更新:Mono无法截屏。 伤心。 瘸。

我想另一种方法是使用gtk#来获取截图。 在执行以下代码之后,您需要创建一个带有GTK#支持的单声道项目:

 Gdk.Window window = Gdk.Global.DefaultRootWindow; if (window!=null) { Gdk.Pixbuf pixBuf = new Gdk.Pixbuf(Gdk.Colorspace.Rgb, false, 8, window.Screen.Width, window.Screen.Height); pixBuf.GetFromDrawable(window, Gdk.Colormap.System, 0, 0, 0, 0, window.Screen.Width, window.Screen.Height); pixBuf.ScaleSimple(400, 300, Gdk.InterpType.Bilinear); pixBuf.Save("screenshot0.jpeg", "jpeg"); } 

你也可以使用P \ Invoke直接调用GTK函数。

希望这会有所帮助,问候

当我们需要在同一软件中使用Linux和OS X上的Mono屏幕截图时,我们遇到了同样的问题。

实际上,您可以在Linux上的Mono上使用CopyFromScreen 。 但是,您需要安装mono-complete软件包,其中包括System.Drawing。

对于OS X ,最可靠的方法是Process.Start screencapture命令行工具。 它默认出现在那里。

对于Linux ,为了使其可靠,可以使用ImageMagic中的import命令行(在这种情况下您需要使其成为依赖项),或强制依赖包含System.Drawing的mono-complete包。 根据我们的测试,Gtk#方法是不可靠的,并且可能提供空白屏幕或exception失败(我们每天在各种机器上拍摄数千个屏幕截图)。

另一件事是,当您需要在一个屏幕截图中捕获多个显示时,您必须在通过CopyFromScreen单独拍摄之后正确对齐单独的屏幕截图。

所以到目前为止我们有这个解决方案

 using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Windows.Forms; namespace Pranas { ///  /// ScreenshotCapture ///  public static class ScreenshotCapture { #region Public static methods ///  /// Capture screenshot to Image object ///  /// Create screen only from primary screen ///  public static Image TakeScreenshot(bool onlyPrimaryScreen = false) { try { return WindowsCapture(onlyPrimaryScreen); } catch (Exception) { return OsXCapture(onlyPrimaryScreen); } } #endregion #region Private static methods //private static Image ImageMagicCapture(bool onlyPrimaryScreen) //{ // return ExecuteCaptureProcess("import", "-window root "); //} private static Image OsXCapture(bool onlyPrimaryScreen) { var data = ExecuteCaptureProcess( "screencapture", string.Format("{0} -T0 -tpng -S -x", onlyPrimaryScreen ? "-m" : "")); return data; } ///  /// Start execute process with parameters ///  /// Application name /// Command line parameters /// Bytes for destination image private static Image ExecuteCaptureProcess(string execModule, string parameters) { var imageFileName = Path.Combine(Path.GetTempPath(), string.Format("screenshot_{0}.jpg", Guid.NewGuid())); var process = Process.Start(execModule, string.Format("{0} {1}", parameters, imageFileName)); if (process == null) { throw new InvalidOperationException(string.Format("Executable of '{0}' was not found", execModule)); } process.WaitForExit(); if (!File.Exists(imageFileName)) { throw new InvalidOperationException(string.Format("Failed to capture screenshot using {0}", execModule)); } try { return Image.FromFile(imageFileName); } finally { File.Delete(imageFileName); } } ///  /// Capture screenshot with .NET standard implementation ///  ///  /// Return bytes of screenshot image private static Image WindowsCapture(bool onlyPrimaryScreen) { if (onlyPrimaryScreen) return ScreenCapture(Screen.PrimaryScreen); var bitmaps = (Screen.AllScreens.OrderBy(s => s.Bounds.Left).Select(ScreenCapture)).ToArray(); return CombineBitmap(bitmaps); } ///  /// Create screenshot of single display ///  ///  ///  private static Bitmap ScreenCapture(Screen screen) { var bitmap = new Bitmap(screen.Bounds.Width, screen.Bounds.Height, PixelFormat.Format32bppArgb); using (var graphics = Graphics.FromImage(bitmap)) { graphics.CopyFromScreen( screen.Bounds.X, screen.Bounds.Y, 0, 0, screen.Bounds.Size, CopyPixelOperation.SourceCopy); } return bitmap; } ///  /// Combine images into one bitmap ///  ///  /// Combined image private static Image CombineBitmap(ICollection images) { Image finalImage = null; try { var width = 0; var height = 0; foreach (var image in images) { width += image.Width; height = image.Height > height ? image.Height : height; } finalImage = new Bitmap(width, height); using (var g = Graphics.FromImage(finalImage)) { g.Clear(Color.Black); var offset = 0; foreach (var image in images) { g.DrawImage(image, new Rectangle(offset, 0, image.Width, image.Height)); offset += image.Width; } } } catch (Exception ex) { if (finalImage != null) finalImage.Dispose(); throw ex; } finally { //clean up memory foreach (var image in images) { image.Dispose(); } } return finalImage; } #endregion } } 

或者通过NuGet安装它( 免责声明:我是作者 ):

 PM> Install-Package Pranas.ScreenshotCapture 

我们在许多设置中大量使用它,因此我们会定期改进代码并将注释放入博客中 。

使用Mono 2.4.4,您可以在没有 GTK#的情况下获得整个屏幕:

public static class MonoScreenShooter { public static void TakeScreenshot(string filePath) { using (Bitmap bmpScreenCapture = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)) { using (Graphics g = Graphics.FromImage(bmpScreenCapture)) { g.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, bmpScreenCapture.Size, CopyPixelOperation.SourceCopy); } bmpScreenCapture.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg); } } } }