将屏幕捕获为位图

问题描述 投票:0回答:6

我想在代码中捕获屏幕以获取图像 - 就像使用键盘上的“打印屏幕”按钮一样。

有人知道如何做到这一点吗?我没有起点。

c# .net screenshot
6个回答
122
投票

您可以使用

Graphics.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);

11
投票

我对接受的答案有两个问题。

  1. 它不会捕获多显示器设置中的所有屏幕。
  2. 当使用显示缩放并且您的应用程序未按显示器声明时,
    Screen
    类返回的宽度和高度不正确dpiAware

这是我更新的解决方案,使用

Screen.AllScreens
静态属性并使用 p/invoke 调用
EnumDisplaySettings
来获取真实的屏幕分辨率。

using System.Runtime.InteropServices;

const int ENUM_CURRENT_SETTINGS = -1;

foreach (Screen screen in Screen.AllScreens)
{
    var dm = new DEVMODE();
    dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));
    EnumDisplaySettings(screen.DeviceName, ENUM_CURRENT_SETTINGS, ref dm);

    using var bmp = new Bitmap(dm.dmPelsWidth, dm.dmPelsHeight);
    using var g = Graphics.FromImage(bmp);

    g.CopyFromScreen(dm.dmPositionX, dm.dmPositionY, 0, 0, bmp.Size);
    bmp.Save(screen.DeviceName.Split('\\').Last() + ".png");
}

[DllImport("user32.dll")]
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


8
投票
// Use this version to capture the full extended desktop (i.e. multiple screens)

Bitmap screenshot = new Bitmap(SystemInformation.VirtualScreen.Width, 
                               SystemInformation.VirtualScreen.Height, 
                               PixelFormat.Format32bppArgb);
Graphics screenGraph = Graphics.FromImage(screenshot);
screenGraph.CopyFromScreen(SystemInformation.VirtualScreen.X, 
                           SystemInformation.VirtualScreen.Y, 
                           0, 
                           0, 
                           SystemInformation.VirtualScreen.Size, 
                           CopyPixelOperation.SourceCopy);

screenshot.Save("Screenshot.png", System.Drawing.Imaging.ImageFormat.Png);

1
投票

尝试这个代码

Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics gr = Graphics.FromImage(bmp);
gr.CopyFromScreen(0, 0, 0, 0, bmp.Size);
pictureBox1.Image = bmp;
bmp.Save("img.png",System.Drawing.Imaging.ImageFormat.Png);

0
投票
Bitmap memoryImage;
//Set full width, height for image
memoryImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
                       Screen.PrimaryScreen.Bounds.Height,
                       PixelFormat.Format32bppArgb);
Size s = new Size(memoryImage.Width, memoryImage.Height);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
memoryGraphics.CopyFromScreen(0, 0, 0, 0, s);
string str = "";
try
{
    str = string.Format(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) +
          @"\Screenshot.png");//Set folder to save image
}
catch { };
memoryImage.save(str);

0
投票

我一直想知道如何在 FORTRAN 中做同样的事情,以节省我使用 PrintScreen、粘贴到 Paint 等的大量手动干预。 我刚刚弄清楚如何:我使用 GETPIXEL_RGB 读取我想要的屏幕任何部分的像素,并且准备好 .bmp 标头并将其写入 .bmp 文件,然后写入像素数据。然而,我不认为它会捕获 10 到 20 sctre

© www.soinside.com 2019 - 2024. All rights reserved.