2013-07-28 61 views
1

作为我的应用程序的一部分,我希望能够在桌面上抓取选定区域的屏幕截图。前段时间我遇到了如何做这个示例代码(如果我能记得我会引用它的地方),并且该示例很好地工作,但它在多个显示器上有问题。跨多个显示屏捕捉屏幕截图

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

回答

2

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

在橡皮筋的构造函数:

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