在多个显示器上捕获屏幕截图

本文关键字:屏幕截图 显示器 | 更新日期: 2023-09-27 18:25:27

作为应用程序的一部分,我希望能够在桌面上抓取所选区域的屏幕截图。不久前,我遇到了如何做到这一点的示例代码(如果我还记得我会引用哪里的话),这个示例运行得很好,但它有多个显示的问题。

它的工作原理是创建一个透明的全屏窗体,然后在其中绘制一条橡皮筋来指定区域。问题是它出现在主显示器上,只允许你在该显示器或其右侧的一个显示器上获取内容。如果你有3个显示器,而你的主显示器是中心,那么就无法获取左侧的内容。

我的问题是如何允许在所有3个显示器上进行捕获。

示例代码:

RubberBand.cs

public partial class RubberBand : Form
{
    public Point lastLoc;
    public Size lastSize;
    bool mouseDown = false;
    Point mouseDownPoint = Point.Empty;
    Point mousePoint = Point.Empty;
    Main mainform;
    Pen pen;
    Rectangle bounds = new Rectangle();
    public RubberBand(Main mainform)
    {
        this.mainform = mainform;
        InitializeComponent();
        this.TopMost = true;
        this.Opacity = .30;
        this.TransparencyKey = System.Drawing.Color.White;
        this.Location = new Point(0, 0);
        DoubleBuffered = true;
        pen = new Pen(System.Drawing.Color.DarkRed, 3);
        pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
        int maxX = 0;
        int maxY = 0;
        foreach (Screen screen in System.Windows.Forms.Screen.AllScreens)
        {
            int x = screen.Bounds.X + screen.Bounds.Width;
            if (x > maxX)
                maxX = x;
            int y = screen.Bounds.Y + screen.Bounds.Height;
            if (y > maxY)
                maxY = y;
        }
        bounds.X = 0;
        bounds.Y = 0;
        bounds.Width = maxX;
        bounds.Height = maxY;
        this.Size = new Size(bounds.Width, bounds.Height);
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        mouseDown = true;
        mousePoint = mouseDownPoint = e.Location;
    }
    protected override void OnMouseUp(MouseEventArgs e)
    {
        base.OnMouseUp(e);
        mouseDown = false;
        // corey
        this.lastLoc = new Point(Math.Min(mouseDownPoint.X, mousePoint.X), Math.Min(mouseDownPoint.Y, mousePoint.Y));
        this.lastSize = new Size(Math.Abs(mouseDownPoint.X - mousePoint.X), Math.Abs(mouseDownPoint.Y - mousePoint.Y));
        this.Close();
    }
    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        mousePoint = e.Location;
        Invalidate();
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        //base.OnPaint(e);
        Region region = new Region(bounds);
        if (mouseDown)
        {
            Rectangle selectionWindow = new Rectangle(
                Math.Min(mouseDownPoint.X, mousePoint.X),
                Math.Min(mouseDownPoint.Y, mousePoint.Y),
                Math.Abs(mouseDownPoint.X - mousePoint.X),
                Math.Abs(mouseDownPoint.Y - mousePoint.Y));
            // make a hole, where we can see thru this form
            region.Xor(selectionWindow);
            e.Graphics.FillRegion(Brushes.Black, region);
        }
        else
        {
            e.Graphics.FillRegion(Brushes.LightGray, region);
            e.Graphics.DrawLine(pen,
                mousePoint.X, 0,
                mousePoint.X, this.Size.Height);
            e.Graphics.DrawLine(pen,
                0, mousePoint.Y,
                this.Size.Width, mousePoint.Y);
        }
    }
}

RubberBand.Designer.cs

partial class RubberBand
{
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
    #region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.SuspendLayout();
        //
        // RubberBand
        //
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.BackColor = System.Drawing.Color.White;
        this.ClientSize = new System.Drawing.Size(284, 262);
        this.Cursor = System.Windows.Forms.Cursors.Cross;
        this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
        this.Name = "RubberBand";
        this.ShowInTaskbar = false;
        this.Text = "RubberBand";
        this.TransparencyKey = System.Drawing.Color.White;
        this.ResumeLayout(false);
    }
    #endregion
}

这就是调用它的代码:

    private void ShowRubberBand()
    {
        using (RubberBand rbf = new RubberBand(this))
        {
            rbf.ShowDialog();
            Size sLastSize = rbf.lastSize;
            if (sLastSize.Width > 0 && sLastSize.Height > 0)
            {
                Rectangle r = new Rectangle();
                r.Location = rbf.lastLoc;
                r.Size = sLastSize;
                CaptureBitmap(r);
            }
        }
        this.Show();
    }
    private void CaptureBitmap(Rectangle r)
    {
        bitmap = new Bitmap(r.Width, r.Height);
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            g.CopyFromScreen(r.Location, new Point(0, 0), r.Size);
        }
        PasteImage(bitmap);
    }

在多个显示器上捕获屏幕截图

this.Location = new Point(0, 0);与主屏幕左上角相关。主(主)屏幕左侧或上方的屏幕具有负位置坐标。在定位窗口和设置窗口大小时,必须将其考虑在内。

在RubberBand构造函数:

    int maxX = 0;
    int maxY = 0;
    int minX = 0;
    int minY = 0;
    foreach (Screen screen in System.Windows.Forms.Screen.AllScreens)
    {
        int x = screen.Bounds.X + screen.Bounds.Width;
        if (x > maxX)
            maxX = x;
        int y = screen.Bounds.Y + screen.Bounds.Height;
        if (y > maxY)
            maxY = y;
        if(screen.Bound.X < minX) minX = screen.Bound.X;
        if(screen.Bound.Y < minY) minY = screen.Bound.Y;
    }
    bounds.X = minX;
    bounds.Y = minY;
    bounds.Width = maxX - minX;
    bounds.Height = maxY - minY;
    this.Location = new Point(bounds.X, bounds.Y);
    this.Size = new Size(bounds.Width, bounds.Height);