1

在 C# 中工作我有一个项目需要捕获位图ControlForm位图。我有一个类,它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);
                }
            }
        }
    }

为我需要捕获的每个控件创建此类的一个实例,使用位图(在本例中将其绘制到屏幕上),并在不再需要时处理该对象。这很好用,并为我提供了指定Controlor的位图,Form在后者的情况下包括非客户区,如下所示:

http://i.imgur.com/ZizXjNX.png

但是,如果我尝试Form再次捕获 a,我会遇到问题。如果我Form在再次捕获之前调整了它的大小,第二次捕获将显示非客户区不正确。

下面是一张图片来说明这一点 - 左边是表单在屏幕上的样子(正确),右边是上面的代码如何捕获它(不正确)。

http://i.imgur.com/y46kFDj.png

我没有从我自己的搜索中找到任何东西,所以想知道是否有人能指出我做错了什么/没有做什么?

4

1 回答 1

0

我无法按需要解决这个问题(通过保留现有的捕获方法),而且由于这是一个原型应用程序,我目前没有时间进一步深入研究它。如果这个原型被选中或者我有另一个机会再次研究这个,我会相应地更新这个答案。

同时,我使用以下方法作为替代方法。尽管使用不同的机制来捕获内容,但这会产生所需的输出。我不太喜欢这个,因为它涉及到“弄乱”窗户和表格​​,而不是我想要的,但现在就足够了。

基本上,我现在只需将有问题的窗口/表单放在前面,将其设置为最顶部,然后仅在窗口的边界上执行屏幕捕获。正如我所说,比我想要的更混乱,但它在实践中效果很好!

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)
        {
            _controlBitmap = new Bitmap(_bounds.Width, _bounds.Height);
            using (Graphics bitmapGraphics = Graphics.FromImage(_controlBitmap))
            {
                if (control.Parent == null)
                {
                    Form form = control as Form;
                    Boolean currentTopMost = form.TopMost;
                    form.TopMost = true;
                    control.BringToFront();
                    bitmapGraphics.CopyFromScreen(control.Location, Point.Empty, _bounds.Size);
                    form.TopMost = currentTopMost;
                }
                else
                {
                    IntPtr hDC = IntPtr.Zero;
                    try
                    {
                        hDC = control.CreateGraphics().GetHdc();
                        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);
                    }
                }
            }
        }
    }
}
于 2013-08-27T11:36:05.773 回答