【发布时间】:2013-08-13 14:47:59
【问题描述】:
在 C# 中工作 我有一个项目需要将Control 或Form 捕获到位图。我有一个类,它在构造函数中采用Control 参数,然后执行以下代码(为本示例简化)以保存Control 的位图。
public MyItem(Control control)
{
if (control != null)
{
Control rootParent = control;
while (rootParent.Parent != null)
rootParent = rootParent.Parent;
rootParent.BringToFront();
_bounds = control.Bounds;
Rectangle controlBounds;
if (control.Parent == null)
{
_bounds = new Rectangle(new Point(0, 0), control.Bounds.Size);
controlBounds = _bounds;
}
else
{
_bounds.Intersect(control.Parent.ClientRectangle);
_bounds = new Rectangle(rootParent.PointToClient(control.Parent.PointToScreen(_bounds.Location)), _bounds.Size);
controlBounds = new Rectangle(rootParent.PointToClient(control.Parent.PointToScreen(control.Location)), control.Size);
}
if (_bounds.Height > 0 && _bounds.Width > 0)
{
IntPtr hDC = IntPtr.Zero;
if (control.Parent == null && !Clarity.ClientAreaOnly)
// Used for capturing a form including non-client area
hDC = Win32.GetWindowDC(control.Handle);
else
// Used for capturing a form excluding non-client area or a control
hDC = control.CreateGraphics().GetHdc();
try
{
_controlBitmap = new Bitmap(_bounds.Width, _bounds.Height);
using (Graphics bitmapGraphics = Graphics.FromImage(_controlBitmap))
{
IntPtr bitmapHandle = bitmapGraphics.GetHdc();
Win32.BitBlt(bitmapHandle, 0, 0, _bounds.Width, _bounds.Height, hDC, _bounds.X - controlBounds.X, _bounds.Y - controlBounds.Y, 13369376);
bitmapGraphics.ReleaseHdc(bitmapHandle);
}
}
finally
{
if (hDC != IntPtr.Zero)
Win32.ReleaseDC(control.Handle, hDC);
}
}
}
}
为我需要捕获的每个控件创建此类的一个实例,使用位图(在本例中将其绘制到屏幕上),并在不再需要时处理该对象。这很好用,给了我一个指定的Control 或Form 的位图,在后者的情况下包括非客户区,如下所示:
http://i.imgur.com/ZizXjNX.png
但是,如果我再次尝试捕获Form,我就会遇到问题。如果我在再次捕获之前调整了Form 的大小,则第二次捕获将显示非客户区不正确。
下面是一张图片来说明这一点 - 左边是表单在屏幕上的样子(正确),右边是上面的代码如何捕获它(不正确)。
http://i.imgur.com/y46kFDj.png
我没有从我自己的搜索中找到任何东西,所以想知道是否有人能指出我做错/没有做的事情?
【问题讨论】:
-
也许没有代码可以解决这个问题,所以你只需要绕过它。在捕获表单图像之前,使用计时器或类似的新线程来计算一小段时间。
-
这种情况会发生在调整大小期间,还是调整大小完成后的任何时候?
-
@DonBoitnott 对不起,我应该更清楚地说明这一点 - 它会在调整大小后随时发生。例如,我可以调整表单大小(调整大小已完成),等待 10 秒,然后捕获它,但它仍然显示不正确。令我困惑的是,客户区中的所有内容都是正确的,只有非客户区不正确。
-
在我看来,Control bounds 的大小没有根据表单进行调整。它是停靠或锚定以确保调整大小,还是以某种方式在代码中处理?因为如果你的 hDC 是 Control 的,而且它更大,你会像第二个例子一样获得捕获。
-
据我所知,边界是正确的——位图是根据控制边界创建的,并且始终是正确创建的。此外,客户区总是被正确捕获,非客户区似乎总是失败。
标签: c# .net screenshot bitblt nonclient-area