1

作为我的应用程序的一部分,我希望能够在我的桌面上截取所选区域的屏幕截图。不久前,我遇到了如何执行此操作的示例代码(如果我记得我会引用的地方)并且该示例运行良好,但是它在多个显示器上存在问题。

它的工作原理是创建一个透明的全屏表单,然后在其中画一个橡皮筋来指定区域。问题是它会在主显示屏上生成,并且只允许您在该显示屏或右侧的一个显示屏上抓取内容。如果您有 3 个显示器并且您的主人是中心,则无法抓住左侧。

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

示例代码:

橡皮筋.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);
    }
4

1 回答 1

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);
于 2013-07-28T21:07:40.837 回答