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

时间:2013-07-28 20:55:10

标签: c# winforms

作为我的应用程序的一部分,我希望能够在桌面上绘制所选区域的屏幕截图。我偶然发现了如何执行此操作的示例代码(如果我能记住我要引用的地方)并且该示例运行良好,但是它存在多个显示器的问题。

它的工作原理是创建一个透明的全屏形式,然后在其中绘制一个橡皮带来指定该区域。问题是它在主显示屏上产生,只允许您抓取该显示屏上的内容或其右侧的内容。如果您有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);
    }

1 个答案:

答案 0 :(得分:2)

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