如何在不使用“从屏幕复制"的情况下仅将图片框显示的内容捕获为位图? [英] How can I capture as bitmap only what a picturebox is displaying, without using "copy from screen"?

查看:17
本文介绍了如何在不使用“从屏幕复制"的情况下仅将图片框显示的内容捕获为位图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Specifically: I need to capture as a bitmap a specific region of what a picturebox is actually displaying. The coordinates of the region are specified by the bounds of a control that I have overlayed on top of the picturebox (but that belongs to the picturebox). The control is hidden when I make the "snapshot" of the region.

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

I tried using normal screen capture methods (CopyFromScreen), but you can't really control the timing there. So it was capturing "interstitial" states, like transitions between photos in my picturebox. Frequently it was only capturing purely black images (the background color of the picture box).

所以我尝试将显示的图像(picturebox.image 属性)转换为位图.问题在于图片框很少准确显示图像.它显示了图像的一部分,根据它的大小模式(即缩放)进行缩放和裁剪.所以我不能只是把我的控制坐标从整个图像中剪下来.

So I tried just converting the image (picturebox.image property) being displayed to a bitmap. The problem there is that the picture box is rarely showing exactly the image. It's displaying some PORTION of the image, scaled and clipped as appropriate to it's sizemode (which is zoom). So the I can't just take my control coordinates and clip them from the image as a whole.

所以我试图估计图像的哪个部分被显示,并根据它修正我的矩形.事实证明,我基本上是在重新创建图片框的缩放"代码来执行此操作(使用图片框的纵横比,图像的纵横比,如果图像较大,则猜测图像当前发生的缩放级别或小于图片框等).不好看.

So I tried to estimate what portion of the image was being displayed, and correcting my rectangle based on that. Turns out that I was basically re-creating the "zoom" code of the picturebox to do this (using aspect ratio of the picturebox, the aspect ratio of the image, guessing at what level of scaling is currently happening to the image if it's larger or smaller than the picturebox, etc). It was not pretty.

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

So: now I need a method of just capturing only the bitmap currently being displayed in the client area of the picturebox, including the photo and any black "letterboxing" currently being displayed around it. Anybody got one?

请记住,我不能依赖使用 CopyFromScreen.就我的目的而言,它不够可靠.我想我需要一种让图片框告诉我它显示的位的方法.

Remember that I can't rely on using CopyFromScreen. It's not reliable enough for my purposes. I think I need a method of getting picturebox to TELL me the bits it is displaying.

推荐答案

这将复制并保存 PictureBox 当前显示的内容,包括一个 BackgroundImage(如果有一个,如果它发光)以及属于 PictureBox 的所有 Controls,如 Labels 等.还包括在Paint 事件.在Paint 事件之外绘制的东西非持久性,将包括在内.

This will copy and save the currently shown content of the PictureBox including a BackgroundImage (if there is one and if it shines through) and also all Controls that belong to the PictureBox, like Labels etc.. Also included are elements drawn in the Paint event. Things drawn outside the Paint event are non-persistent and will not be included.

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

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

Note: On my test Form the PicureBox is sitting inside an AutoScroll Panel pan_PBscroll. The PictureBox is displaying pixels 1:1 and is therefore, with a photograph loaded, much bigger than the Panel, the Form or even the Screen. So to clip to the actually visible parts I could not use the pictureBox1.ClientSize and pictureBox1.ClientRectangle but used the dimensions of that Panel. This may well apply to you, too.

我不确定您的时间问题.但既然你提到了 CopyFromScreen,这里有一些不同之处:

I'm not sure about your timing issues. But since you mentioned CopyFromScreen here are a few differences:

  • CopyFromScreen 制作每个屏幕像素的 1:1 副本
  • 这包括非永久性绘图,不包括任何覆盖或隐藏的内容
  • Control.DrawToBitmap 使控件将自己绘制到位图上,就像它在 Paint
  • 期间绘制自己一样
  • 这排除了不属于 Control 但包括其 Controls 集合的所有成员的任何内容
  • 这也不包括非持久性绘图,但包括控件的完整大小,无论它是否适合窗体或屏幕,以及是否隐藏或覆盖.
  • 对于带有活动滚动条的控件,仅复制可见部分.要复制所有你需要临时调整它的大小.然后,即使列表框有一千个项目,您也可以获得完整的图像.
  • CopyFromScreen makes a 1:1 copy of each screen pixel
  • This includes non-persistent drawings and excludes anything covered or hidden
  • Control.DrawToBitmap makes the Control draw itself onto a Bitmap, just as it draws itself during Paint
  • This excludes anything that doesn't belong to the Control but includes all members of its Controls collection
  • This also excludes non-persistent drawings but includes the full Size of the Control, whether it fits on the Form or Screen or not and whether it is hidden or covered or not.
  • For Controls with active Scrollbars only the visible parts are copied. To copy all you need to resize it temporarily. Then you can get a complete image of a listbox even if it has a thousand items..

这篇关于如何在不使用“从屏幕复制"的情况下仅将图片框显示的内容捕获为位图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆