如何仅将图片框显示的内容捕获为位图,而不使用“从屏幕复制”?

Car*_*ang 2 c# image bitmap picturebox winforms

具体来说:我需要将图片框实际显示的特定区域捕获为位图。该区域的坐标由我覆盖在图片框顶部的控件的边界指定(但该控件属于图片框)。当我制作该区域的“快照”时,该控件被隐藏。

我尝试使用普通的屏幕捕获方法(CopyFromScreen),但您无法真正控制那里的时间。所以它正在捕捉“间隙”状态,就像我的图片框中照片之间的过渡。通常,它仅捕获纯黑色图像(图片框的背景颜色)。

所以我尝试将显示的图像(picturebox.image 属性)转换为位图。问题在于图片框很少能准确显示图像。它显示图像的某些部分,根据其大小模式(即缩放)进行缩放和裁剪。因此,我不能只获取控制坐标并将它们从整个图像中剪切出来。

因此,我尝试估计正在显示图像的哪一部分,并据此纠正我的矩形。事实证明,我基本上是重新创建图片框的“缩放”代码来执行此操作(使用图片框的纵横比、图像的纵横比、猜测图像当前发生的缩放级别(如果图像较大)或小于图片框等)。这并不漂亮。

所以:现在我需要一种仅捕获当前在图片框的客户区域中显示的位图的方法,包括照片和当前在其周围显示的任何黑色“信箱”。有人有吗?

请记住,我不能依赖使用 CopyFromScreen。对于我的目的而言,它不够可靠。我想我需要一种获取图片框的方法来告诉我它正在显示的位。

TaW*_*TaW 5

这将复制并保存 的当前显示的内容,PictureBox包括 a BackgroundImage(如果有一个并且它闪耀)以及Controls属于 的所有内容PictureBox,例如Labels等。还包括在Paint事件中绘制的元素。活动之外绘制的东西Paint是非持久性的,不会包含在内。

using (Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width,
                               pictureBox1.ClientSize.Height))
{
   pictureBox1.DrawToBitmap(bmp, pictureBox1.ClientRectangle);
   bmp.Save(yourfilename, ImageFormat.Png);
}
Run Code Online (Sandbox Code Playgroud)

注意:在我的测试表格中,它PicureBox位于AutoScroll Panel pan_PBscroll. PictureBox 以 1:1 的比例显示像素,因此,加载照片后,它比面板、表单甚至屏幕大得多。因此,为了剪辑到实际可见的部分,我无法使用该面板pictureBox1.ClientSizepictureBox1.ClientRectangle但使用了该面板的尺寸。这很可能也适用于你。

我不确定你的时间问题。但既然你CopyFromScreen在这里提到了一些差异:

  • CopyFromScreen对每个屏幕像素进行 1:1 复制
  • 这包括非持久性绘图,不包括任何被覆盖或隐藏的内容
  • Control.DrawToBitmap使控件将自身绘制到位图上,就像它在Paint
  • 这排除了不属于该控件但包含其控件集合的所有成员的任何内容
  • 这也排除了非持久性绘图,但包括控件的完整大小,无论它是否适合窗体或屏幕,以及是否隐藏或覆盖。
  • 对于具有活动滚动条的控件,仅复制可见部分。要复制所有内容,您需要暂时调整其大小。然后,即使列表框有一千个项目,您也可以获得完整的图像。