`

wpf - how to create and save any visual element into a file

    博客分类:
  • WPF
wpf 
阅读更多

Given a random Visual (type of System.Windows.Media.Visual) how to create a visual that represent the visual in memory and save that back to some file?

 

the key here are a few classes

 

System.Windows.Media.DrawingVisual

System.Windows.Media.DrawingImage

System.Windows.Media.Imaging.RenderTargetBitmap

System.Windows.Media.Imaging.BitmapFrame

 

 

 

and the flow of the classes as such

 

 

  1. you first create a DrawingVisual through the use of TreeHelper.GetDrawing(visual); while the return value of the call is DrawingGroup.
  2. you then can create an empty DrawingVisual, and open  it by DrawingVisual.RenderOpen to get a DrawingContent (System.Windows.Media.DrawingContext); so that you can draw the image to the drawing context.
  3. You can call the DrawingContext.DrawImage to draw the image onto the Drawing Context.
  4. After that, you can create a RenderTargetBitmap or any other type of Bitmap, initialize it withthe proper resultion settings and size (width and height)
  5. you then render the RenderTargetBitmap  with the Render(drawingVisual) call
  6. After all this, you can create a certain BitmapEncoder, in this case, you can use PngBitmapEncoder;
  7. Add a BitmapFrame to the BitmapEncoder, by add the bitmapFrame to the BitmapEncoder's Frames collection. To creat a BitmapFrame, you can use the static method of System.Windows.Media.Imaging.BitmapFrame.Create(RenderTargetBitmap bitmap);
  8. After all this, you can create a file stream , and call the BitmapEncoder.Save(stream) to save the image to file

 

Below is the code that demonstrate the whole process.

 

 

  private static void ExampleCreateImage(System.Windows.Media.Visual  visual, int width, int height) 
  {

    var drawingVisual = new DrawingVisual();
    var drawingImage = new DrawingImage(VisualTreeHelper.GetDrawing(visual));

    using (var dc = drawingVisual.RenderOpen())
    {
        var rectangle = new Rect
        {
          X = 0,
          Y = 0,
          Width = width,
          Height = height,
        };
        dc.DrawRectangle(Brushes.White, null, rectangle);
        dc.DrawImage(drawingImage, rectangle);
    }

    System.Windows.Media.Imaging.RenderTargetBitmap rtb = new System.Windows.Media.Imaging.RenderTargetBitmap(width,
      height, 96d, 96d, PixelFormats.Default);

    rtb.Render(drawingVisual);

    System.Windows.Media.Imaging.PngBitmapEncoder encoder = new System.Windows.Media.Imaging.PngBitmapEncoder();
    encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(rtb));
    using (System.IO.FileStream stream = new System.IO.FileStream(Environment.ExpandEnvironmentVariables(@"%temp%\print\MyDrawingImage.png"), System.IO.FileMode.OpenOrCreate))
    {
      encoder.Save(stream);
      stream.Close();
    }
    // to use you can call as follow
    //var frameworkElement = new FrameworkElement();
    //ExampleCreateImage(frameworkElement, (int)frameworkElement.ActualWidth, (int)frameworkElement.ActualWidth);
  }

 

NOTE: only when the Visual is Actually System.Windows.Interop.HwndHost, then you will use the above technique.

 

If the Visual is a general Visual, other than System.Windows.Interop.HwndHost, you can use the VisualBrush.

 

Below the code show how you descriminate between HwndHost and other FrameworkElement, you can come up the Bitmap and serialization code which is missing in the previous example.

 

 

    // @return a instance of IPrintImage
    public static IPrintImage CreatePrintImage(object container_)
    {

      if (Content != null)
      {
        var hwndHost = Content as System.Windows.Interop.HwndHost;
        if (hwndHost != null)
        {
          var drawingVisual = CreateDrawingImage(hwndHost, hwndHost.ActualWidth, hwndHost.ActualHeight);
          return new PrintImage(hwndHost) { DrawingVisual = drawingVisual };
        }
        var content = Content as FrameworkElement;
        if (content != null)
        {
          var drawingVisual = CreateDrawingVisual(content, content.ActualWidth, content.ActualHeight);
          return new PrintImage(content) { DrawingVisual = drawingVisual };
        }
      }
      return null;
    }

    public static DrawingVisual CreateDrawingVisual(FrameworkElement visual, double width, double height)
    {
      var drawingVisual = new DrawingVisual();
      // open the Render of the DrawingVisual
      using (var dc = drawingVisual.RenderOpen())
      {
        var vb = new VisualBrush(visual) { Stretch = Stretch.None };
        var rectangle = new Rect
        {
          X = 0,
          Y = 0,
          Width = width,
          Height = height,
        };

        // draw the white background
        dc.DrawRectangle(Brushes.White, null, rectangle);
        // draw the visual
        dc.DrawRectangle(vb, null, rectangle);
      }
      return drawingVisual;
    }

    public static DrawingVisual CreateDrawingImage(Visual visual, double width, double height)
    {
      return CreateDrawingImage(new DrawingImage(VisualTreeHelper.GetDrawing(visual)), width, height);
    }

    public static DrawingVisual CreateDrawingImage(System.Windows.Media.DrawingImage drawingImage, double width, double height)
    {
      //var image = new System.Windows.Controls.Image();
      //image.Height = height;
      //image.Width = width;
      //image.Source = drawingImage;

      var drawingVisual = new DrawingVisual();
      // open the Render of the DrawingVisual
      using (var dc = drawingVisual.RenderOpen())
      {
        var rectangle = new Rect
        {
          X = 0,
          Y = 0,
          Width = width,
          Height = height,
        };

        // draw the white background
        dc.DrawRectangle(Brushes.White, null, rectangle);
        //NOTE:
        // instead of Creating one VisualBrush, it create and use one DrawingImage
        // which works with WebBrowser and get the right image back, while 
        // with the VisualBrush, it seems empty content is returned
        // 
        dc.DrawImage(drawingImage, rectangle);
      }

      return drawingVisual;
    }
分享到:
评论

相关推荐

    gong-wpf-dragdrop, GongSolutions.WPF.DragDrop 库是WPF的拖动'n'拖放框架.zip

    gong-wpf-dragdrop, GongSolutions.WPF.DragDrop 库是WPF的拖动'n'拖放框架 简介GongSolutions.WPF.DragDrop 库是一个易于使用的拖拉'n'拖放框架。特性使用 MVVM: 拖放逻辑可以放在ViewModel中。 代码不需要放在in中...

    File-Manager-UI-Wpf-master.7z

    【标题】"File-Manager-UI-Wpf-master.7z" 涉及的是一个基于WPF(Windows Presentation Foundation)的文件管理器用户界面项目。这个压缩包包含了一个完整的开发环境,供开发者进行学习和使用。 【描述】"自用资源...

    基于WPF的图形化编程控件和环境WPF-Blockly-master

    【标题】"基于WPF的图形化编程控件和环境WPF-Blockly-master" 提供了一个创新的编程体验,它将传统的代码编写转变为图形化的流程图形式,使得编程变得更加直观和易于理解。WPF(Windows Presentation Foundation)是...

    Prism-Samples-Wpf-master06-10.zip

    **Prism-Samples-Wpf-master06-10.zip** 是一个包含多个示例项目的压缩包,主要用于展示如何在Visual Studio 2017中使用 **WPF (Windows Presentation Foundation)** 和 **Prism** 框架进行开发。Prism是微软支持的...

    wpf---StatusBar

    “wpf---StatusBar”这个标题表明我们将探讨的是WPF(Windows Presentation Foundation)框架中的StatusBar组件。WPF是.NET Framework的一部分,用于构建桌面应用程序,它提供了丰富的用户界面(UI)功能。StatusBar...

    WPF-Diagram-Designer:WPF图表设计器源代码

    通过深入研究WPF-Diagram-Designer的源代码(如WPF-Diagram-Designer-master文件夹中的内容),开发者不仅可以学习到如何在WPF中构建复杂的图形界面,还可以了解到图形编辑器的设计原理和实现细节,对于提升图形应用...

    WPF - Visual调试工具Snoop(只能调试wpf应用程序)

    WPF - Visual调试工具Snoop(只能调试wpf应用程序) 演示及教程地址: http://blog.csdn.net/homezzm/archive/2009/11/20/4843286.aspx

    Packt.MVVM.Survival.Guide.for.Enterprise.Architectures.in.Silverlight.And.WPF

    During your journey you will see how to satisfy all the demands of modern WPF and Silverlight enterprise applications including scalability, testability, extensibility, and blendability. Complete ...

    wpf-datagrid-access DB

    在这个“wpf-datagrid-access DB”主题中,我们将深入探讨如何利用WPF Datagrid与Microsoft Access数据库进行交互,实现数据的读取、更新和保存。 1. **WPF Datagrid简介** - Datagrid是WPF中的一个数据展示控件,...

    WPF-强大的图表.zip

    **WPF - 强大的图表技术** Windows Presentation Foundation (WPF) 是Microsoft开发的一个用于构建桌面应用程序的框架,它提供了丰富的图形系统,包括对2D和3D图形的强大支持。在WPF中,开发人员可以利用各种图表...

    WPF--Effect特效

    标题中的"WPF--Effect特效"指的是Windows Presentation Foundation(WPF)中的Effect特效。WPF是.NET Framework的一个重要组件,用于构建丰富的桌面应用程序。Effect特效在WPF中是用来改变UI元素外观的一...

    BluetoothSample.WPF-master.zip

    【标题】"BluetoothSample.WPF-master.zip"是一个包含WPF(Windows Presentation Foundation)应用程序的示例,该示例专门用于演示如何使用蓝牙技术。这个压缩包可能是开发人员为了分享其在构建蓝牙功能的WPF应用...

    WPF-WIFI.zip

    标题 "WPF-WIFI.zip" 暗示了这是一个与Windows Presentation Foundation (WPF) 相关的项目,特别关注于模拟手机信号和WIFI信号的显示。WPF是.NET Framework的一部分,它提供了一个用于构建桌面应用程序的强大而灵活...

    C# WPF-IP扫描工具WPF.zip

    C# WPF--IP扫描工具WPF.zip

    wpf-资源的使用-resource

    在Windows Presentation Foundation (WPF) 中,资源是可重用的UI元素集合,它们可以是样式、模板、颜色、字体、图像等。资源的使用极大地增强了应用程序的灵活性和可维护性,同时也使得UI设计更加一致和高效。本教程...

    Prism-Samples-Wpf-master21-25.zip

    这个压缩包“Prism-Samples-Wpf-master21-25.zip”包含了一系列基于Prism框架的示例项目,这些示例涵盖了从21到25的不同阶段,可能是按照教程或进阶顺序排列的。此资源对于想要学习或深入了解Prism框架的开发者来说...

    Navigation-Drawer-Sidebar-Menu-in-WPF-master.zip

    标题"Navigation-Drawer-Sidebar-Menu-in-WPF-master.zip"提示我们这是一个关于WPF应用的项目,它包含了一个可展开和收缩的左侧导航菜单。描述中的“WPF左侧展开收缩图标导航菜单”进一步确认了这一功能。通过分析...

    WPF Programmer's Reference: Windows Presentation Foundation with C# 2010 and .NET 4

    It covers the built-in themes provided by WPF and how to create custom themes using styles and templates. #### Printing (Chapter 17) Chapter 17 focuses on printing in WPF applications. It covers the...

    WPF-MVVM-简单示例

    **WPF-MVVM-简单示例** 在本文中,我们将深入探讨如何使用MVVM(Model-View-ViewModel)设计模式来构建一个基于WPF(Windows Presentation Foundation)的应用程序。这个示例着重于通过操作XML数据来实现基本的CRUD...

Global site tag (gtag.js) - Google Analytics