WPF不弹出控件的情况下,将控件内容生成截图

1 篇文章 0 订阅

参考 wpf 对控件进行截图,获取快照 - 大海的泡沫 - 博客园

但该文中的情况是针对已经显示的控件,有另一种情况是,我控件或者弹窗是不显示的,只存在于内存中,这种情况下如果也需要生成该控件的截图可以使用如下方式:

/// <summary>
        /// 不弹出控件的情况下,将控件内容生成截图
        /// </summary>
        /// <param name="width">图片宽度</param>
        /// <param name="height">图片高度</param>
        /// <param name="visualToRender">目标控件</param>
        /// <param name="undoTransformation">是否需要重新渲染:true(是),false(否)</param>
        /// <returns></returns>
        public static System.Drawing.Bitmap ToBitmap(this FrameworkElement visualToRender,
            Double width, Double height, Boolean undoTransformation)
        {
            try
            {
                #region 将目标控件放到 Viewbox中渲染
                visualToRender.Width = width;
                visualToRender.Height = height;
                visualToRender.RenderSize = new System.Windows.Size(width, height);
                var viewbox = new Viewbox();
                viewbox.Width = width;
                viewbox.Height = height;
                viewbox.Child = visualToRender;
                viewbox.Measure(visualToRender.RenderSize);
                viewbox.Arrange(new Rect(new System.Windows.Point(0, 0), visualToRender.RenderSize));
                viewbox.UpdateLayout();
                #endregion

                var bitSrc = CreateBitmapFromVisual(width, height, visualToRender, undoTransformation);
                var bit = bitSrc.BitmapSourceToBitmap();
                return bit;
            }
            catch { }

            return null;
        }

        private static BitmapSource CreateBitmapFromVisual(Double width,
            Double height,
            Visual visualToRender,
            Boolean undoTransformation)
        {
            if (visualToRender == null)
            {
                return null;
            }

            // The PixelsPerInch() helper method is used to read the screen DPI setting.
            // If you need to create a bitmap with a specified resolution, you could directly
            // pass the specified dpiX and dpiY values to RenderTargetBitmap constructor.
            RenderTargetBitmap bmp = new RenderTargetBitmap((Int32)Math.Ceiling(width),
                                                            (Int32)Math.Ceiling(height),
                                                            (Double)DeviceHelper.PixelsPerInch(Orientation.Horizontal),
                                                            (Double)DeviceHelper.PixelsPerInch(Orientation.Vertical),
                                                            PixelFormats.Pbgra32);

            // If we want to undo the transform, we could use VisualBrush trick.
            if (undoTransformation)
            {
                DrawingVisual dv = new DrawingVisual();
                using (DrawingContext dc = dv.RenderOpen())
                {
                    VisualBrush vb = new VisualBrush(visualToRender);
                    dc.DrawRectangle(vb, null, new Rect(new System.Windows.Point(), new System.Windows.Size(width, height)));
                }
                bmp.Render(dv);
            }
            else
            {
                bmp.Render(visualToRender);
            }

            return bmp;
        }

        /// <summary>
        /// BitmapSource转Bitmap
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static System.Drawing.Bitmap BitmapSourceToBitmap(this BitmapSource source)
        {
            return BitmapSourceToBitmap(source, source.PixelWidth, source.PixelHeight);
        }

        /// <summary>
        /// Convert BitmapSource to Bitmap
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static System.Drawing.Bitmap BitmapSourceToBitmap(this BitmapSource source, int width, int height)
        {
            System.Drawing.Bitmap bmp = null;
            try
            {
                System.Drawing.Imaging.PixelFormat format = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
                /*set the translate type according to the in param(source)*/
                switch (source.Format.ToString())
                {
                    case "Rgb24":
                    case "Bgr24": format = System.Drawing.Imaging.PixelFormat.Format24bppRgb; break;
                    case "Bgra32": format = System.Drawing.Imaging.PixelFormat.Format32bppPArgb; break;
                    case "Bgr32": format = System.Drawing.Imaging.PixelFormat.Format32bppRgb; break;
                    case "Pbgra32": format = System.Drawing.Imaging.PixelFormat.Format32bppArgb; break;
                }
                bmp = new Bitmap(width, height, format);
                BitmapData data = bmp.LockBits(new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size),
                    ImageLockMode.WriteOnly,
                    format);
                source.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
                bmp.UnlockBits(data);
            }
            catch
            {
                if (bmp != null)
                {
                    bmp.Dispose();
                    bmp = null;
                }
            }

            return bmp;
        }
    }

    internal class DeviceHelper
    {
        public static Int32 PixelsPerInch(Orientation orientation)
        {
            Int32 capIndex = (orientation == Orientation.Horizontal) ? 0x58 : 90;
            using (DCSafeHandle handle = UnsafeNativeMethods.CreateDC("DISPLAY"))
            {
                return (handle.IsInvalid ? 0x60 : UnsafeNativeMethods.GetDeviceCaps(handle, capIndex));
            }
        }
    }

    internal sealed class DCSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private DCSafeHandle() : base(true) { }

        protected override Boolean ReleaseHandle()
        {
            return UnsafeNativeMethods.DeleteDC(base.handle);
        }
    }

    [SuppressUnmanagedCodeSecurity]
    internal static class UnsafeNativeMethods
    {
        [DllImport("gdi32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern Boolean DeleteDC(IntPtr hDC);

        [DllImport("gdi32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern Int32 GetDeviceCaps(DCSafeHandle hDC, Int32 nIndex);

        [DllImport("gdi32.dll", EntryPoint = "CreateDC", CharSet = CharSet.Auto)]
        public static extern DCSafeHandle IntCreateDC(String lpszDriver,
            String lpszDeviceName, String lpszOutput, IntPtr devMode);

        public static DCSafeHandle CreateDC(String lpszDriver)
        {
            return UnsafeNativeMethods.IntCreateDC(lpszDriver, null, null, IntPtr.Zero);
        }
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值