咨询区
Omar Abid
我想通过代码获取当前的电脑屏幕并保存为一张图片,就好像键盘的 截屏
按钮功能,请问这该如何实现?我没有好思路。
回答区
Gary Willoughby:
如果你的程序是 framework >2.0
的话,完全可以使用 CopyFromScreen()
方法,参考如下代码:
//Create a new bitmap.
var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,Screen.PrimaryScreen.Bounds.Height,PixelFormat.Format32bppArgb);// Create a graphics object from the bitmap.
var gfxScreenshot = Graphics.FromImage(bmpScreenshot);// Take the screenshot from the upper left corner to the right bottom corner.
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,Screen.PrimaryScreen.Bounds.Y,0,0,Screen.PrimaryScreen.Bounds.Size,CopyPixelOperation.SourceCopy);// Save the screenshot to the specified path that the user has chosen.
bmpScreenshot.Save("Screenshot.png", ImageFormat.Png);
更详细的资料可参考:http://www.geekpedia.com/tutorial181_Capturing-screenshots-using-Csharp.html
colton7909:
要想完美的通过代码截屏,通常有两个坑需要解决。
默认情况下是不能截图到扩展屏的,也就是
多显示器
的情况。当显示屏设置了扩大或缩小展示,比如
125%,150%
,那么 Screen 返回的数值会是错误的。
解决这两个问题,最好的方式就是通过 p/invoke
调用底层的 win32 api 来实现,参考如下代码:
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;class Program
{const int ENUM_CURRENT_SETTINGS = -1;static void Main(){foreach (Screen screen in Screen.AllScreens){DEVMODE dm = new DEVMODE();dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));EnumDisplaySettings(screen.DeviceName, ENUM_CURRENT_SETTINGS, ref dm);using (Bitmap bmp = new Bitmap(dm.dmPelsWidth, dm.dmPelsHeight))using (Graphics g = Graphics.FromImage(bmp)){g.CopyFromScreen(dm.dmPositionX, dm.dmPositionY, 0, 0, bmp.Size);bmp.Save(screen.DeviceName.Split('\\').Last() + ".png");}}}[DllImport("user32.dll")]public static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);[StructLayout(LayoutKind.Sequential)]public struct DEVMODE{private const int CCHDEVICENAME = 0x20;private const int CCHFORMNAME = 0x20;[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]public string dmDeviceName;public short dmSpecVersion;public short dmDriverVersion;public short dmSize;public short dmDriverExtra;public int dmFields;public int dmPositionX;public int dmPositionY;public ScreenOrientation dmDisplayOrientation;public int dmDisplayFixedOutput;public short dmColor;public short dmDuplex;public short dmYResolution;public short dmTTOption;public short dmCollate;[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]public string dmFormName;public short dmLogPixels;public int dmBitsPerPel;public int dmPelsWidth;public int dmPelsHeight;public int dmDisplayFlags;public int dmDisplayFrequency;public int dmICMMethod;public int dmICMIntent;public int dmMediaType;public int dmDitherType;public int dmReserved1;public int dmReserved2;public int dmPanningWidth;public int dmPanningHeight;}
}
更多资料请参考:https://stackoverflow.com/a/36864741/987968 http://pinvoke.net/default.aspx/user32/EnumDisplaySettings.html?diff=y
点评区
没想到截个屏还有这么多坑需要解决,不过用了 win32 api,那就限定了 windows 平台,不知道大家可有什么好的跨平台解决方案呢?