`

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-Samples-master_WPF基本sample_

    WPF的基本空间历程,使用.net core3.0.1版本

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

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

    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的一部分,它提供了一个用于构建桌面应用程序的强大而灵活...

    wpf-资源的使用-resource

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

    c#-的WPF---MVVM例子

    在“c#-的WPF---MVVM例子”中,我们可能会看到以下关键概念: 1. **数据绑定**:WPF的强项之一就是其强大的数据绑定功能。通过数据绑定,View中的UI元素可以直接与ViewModel中的属性关联,当ViewModel中的数据改变...

    Prism-Samples-Wpf-master21-25.zip

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

    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...

    深入浅出WPF-刘铁猛-MVVM视频源代码,MVVM入门与提高视频对应的源代码

    刘铁猛的"深入浅出WPF-刘铁猛-MVVM视频"深入讲解了这一模式,配合源代码学习,能够帮助开发者更好地理解和应用MVVM。 **MVVM模式详解** 1. **模型(Model)**:模型层是应用程序的核心,包含业务逻辑和数据。它不...

Global site tag (gtag.js) - Google Analytics