Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
WPF在使用RenderTargetBitmap进行渲染时包含工具提示_Wpf_Tooltip_Infragistics_Rendertargetbitmap_Xamdatachart - Fatal编程技术网

WPF在使用RenderTargetBitmap进行渲染时包含工具提示

WPF在使用RenderTargetBitmap进行渲染时包含工具提示,wpf,tooltip,infragistics,rendertargetbitmap,xamdatachart,Wpf,Tooltip,Infragistics,Rendertargetbitmap,Xamdatachart,我找了又找,但是没有找到任何和我有同样问题的东西。我正在尝试呈现WPF应用程序的一些高分辨率/dpi屏幕截图。唯一的问题是我需要在渲染中包含来自图表工具提示的信息,而不是我可以很好地保存屏幕截图 我目前正在使用Infragistics XamDataChart,我用代码而不是xaml生成工具提示 有人知道如何在可视化树中获取工具提示以使其呈现吗?或者能够渲染整个窗口和其中的所有内容,包括工具提示覆盖 渲染的代码: public static void RenderVisualToFile(thi

我找了又找,但是没有找到任何和我有同样问题的东西。我正在尝试呈现WPF应用程序的一些高分辨率/dpi屏幕截图。唯一的问题是我需要在渲染中包含来自图表工具提示的信息,而不是我可以很好地保存屏幕截图

我目前正在使用Infragistics XamDataChart,我用代码而不是xaml生成工具提示

有人知道如何在可视化树中获取工具提示以使其呈现吗?或者能够渲染整个窗口和其中的所有内容,包括工具提示覆盖

渲染的代码:

public static void RenderVisualToFile(this FrameworkElement visual)
    {
        var width = (int)visual.RenderSize.Width;
        var height = (int)visual.RenderSize.Height;

        RenderTargetBitmap renderTarget = new RenderTargetBitmap(width * 4, height * 4, 384, 384, PixelFormats.Pbgra32);
        renderTarget.Render(visual);

        // Encode and save to PNG file
        var enc = new PngBitmapEncoder();
        enc.Frames.Add(BitmapFrame.Create(renderTarget));

        if (Directory.Exists("Screenshots"))
        {
            using (var stm = File.Create(@"Screenshots\Render_" + DateTime.Now.ToString("yyMMMdd_HHmmss") + ".png"))
                enc.Save(stm);
        }
        else
        {
            Directory.CreateDirectory("Screenshots");
            using (var stm = File.Create(@"Screenshots\Render_" + DateTime.Now.ToString("yyMMMdd_HHmmss") + ".png"))
                enc.Save(stm);
        }
    }    
我在主窗口中称之为代码隐藏

    if (e.Key == Key.PrintScreen)
    {
        this.RenderVisualToFile();
    }

虽然有点晚了,但也许有人可以使用我的解决方案

我的屏幕截图课程基于以下解决方案:

  • 截图的创建基于QMINO技术博客上的一篇文章
  • 要获取当前打开的工具提示,我使用此处发布的代码片段:
  • 我花了一段时间才找到一个解决方案,如何将截图的UIElement与弹出窗口合并,但的一条评论给出了最终的线索
我使用元组返回多个参数

这是我的课:

 using System.Collections.Generic;
 using System.IO;
 using System.Linq; 
 using System.Windows;
 using System.Windows.Controls.Primitives;
 using System.Windows.Interop;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;

 public class Screenshot
 {
      //UIElement to create screenshot 
      private UIElement _element;
      //Bounds for the screenshot
      private Rect _screenshotBounds;
      //Path for Screenshot
      private string _path;


      private const int DPI = 384;
      private const double BASEDPI = 96;
      private const double DPISCALE = DPI / BASISDPI;

      public Screenshot(UIElement element, string path)
      {
          this._element = element; 
          this._screenshotBounds = this.createBounds(this._element);
          this._path = path;
      }

      //public interface to create the screenshot
      public void createScreenshot()
      {
         if (this._element == null)
         {
             return;
         }
         //Create a list of tuples with the elements to render in the screenshot
         List<(UIElement, Rect, Point)> listElements = new List<(UIElement, Rect, Point)>
         {
              //Fist element in the list should be the actual UIElement
              this.createElementBoundPosition(this._element); 
         };

         RenderTargetBitmap renderBitMap = this.createBitMap(this._screenshotBounds);

         //Get the opened Popups, create a list of tuples for the Popups and add them to the list of elements to render
         listElements.AddRange(this.createListPopUpBoundsPosition( this.getOpenPopups()));

         DrawingVisual drawingVisual = this.createDrawingVisual(listElements);
         renderBitMap.Render(drawingVisual);

         this.saveRTBAsPNG(renderBitMap);
      }

      //Create DrawingVisual based on List of Tuples
      private DrawingVisual createDrawingVisual(List<(UIElement, Rect, Point)> listElements)
      {
           DrawingVisual drawingVisual = new DrawingVisual();

           using (DrawingContext context = drawingVisual.RenderOpen())
           {
                foreach((UIElement element, Rect bounds, Point position) in listElements)
                {
                      VisualBrush visualBrush = new VisualBrush(element);
                      context.DrawRectangle(visualBrush, null, new Rect(position, bounds.Size));
                }
           }

           return drawingVisual;
      }

      //Save RenderTargetBitmap to file
      private void saveRTBAsPNG(RenderTargetBitmap bitmap)
      {
          PngBitmapEncoder pngBitmapEncoder = new PngBitmapEncoder()
          {
              Interlace = PngInterlaceOption.On
          }

          pngBitmapEncoder.Frames.Add(BitmapFrame.Create(bitmap));

          using (FileStream fileStream = File.Create(this._path))
          {
              pngBitmapEncoder.Save(fileStream);
          }
      }

      //Create Bounds for Element
      private Rect createBounds(UIElement element)
      {
          new Rect(new Size((int)element.RenderSize.Width, (int)element.RenderSize.Height)); 
      } 

      //Create a Tuple with the Element, its bounds and its position
      private (UIElement element, Rect bounds, Point position) createElementBoundPosition(UIElement element)
      {
          return (element, this.createBounds(element), element.PointToScreen(new Point(0,0)));
      } 

      //create the RenderTargetBitmap
      private RenderTargetBitmap createBitMap(Rect bounds)
      {
          (int width, int height) calculatedBounds = this.calculateBounds(bounds);
           return new RenderTargetBitmap(calculatedBounds.width, calculatedBounds.height, DPI, DPI, PixelFormats.Pbgra32);
      }

      //recalculate bounds according to the scale
      private (int width, int heigth) calculateBounds(Rect bounds)
      {
          int width = (int)(bounds.Width * DPISCALE);
          int height = (int)(bounds.Height * DPISCALE);
          return (width, height);
      }

      //Convert the list of Popups into a List of Tuples
      private List<(UIElement element, Rect bounds, Point position)> createListPopUpBoundsPosition(List<Popup> listPopup)
      {
           List<(UIElement, Rect, Point)> list = new List<(UIElement, Rect, Point)>();

           foreach (Popup p in listPopup)
           {
               //The Child-Element contains the UIElement to render
               UIElement uiElement = p.Child;
               list.Add(this.createElementBoundPosition(uiElement));
           }
           return list;
      }

      //get the open Popups
      private List<Popup> getOpenPopups()
      {
           return PresentationSource.CurrentSources.OfType<HwndSource>()
               .Select(h => h.RootVisual)
               .OfType<FrameworkElement>()
               .Select(f => f.Parent)
               .OfType<Popup>()
               .Where(p => p.IsOpen).ToList();
      }

 }
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用System.Windows;
使用System.Windows.Controls.Primitives;
使用System.Windows.Interop;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
公共课截图
{
//UIElement创建屏幕截图
私有元素_元素;
//截图的边界
私有矩形屏幕快照边界;
//截图路径
私有字符串路径;
私有常数int DPI=384;
专用常量双基DPI=96;
private const double DPISCALE=DPI/BASISDPI;
公共屏幕截图(UIElement、字符串路径)
{
本._元素=元素;
this.\u screenshotBounds=this.createBounds(this.\u元素);
这是路径;
}
//创建屏幕截图的公共界面
公共屏幕截图()
{
if(this.\u元素==null)
{
返回;
}
//创建包含要在屏幕截图中渲染的元素的元组列表
列表元素=新列表
{
//列表中的第一个元素应该是实际的UIElement
this.createElementBoundPosition(this.u元素);
};
RenderTargetBitmap renderBitMap=this.createBitMap(this.\u屏幕快照边界);
//获取打开的弹出窗口,为弹出窗口创建元组列表,并将它们添加到要渲染的元素列表中
AddRange(this.createListPopubOutboundsPosition(this.getOpenPopups());
DrawingVisual DrawingVisual=this.createDrawingVisual(列表元素);
renderBitMap.Render(drawingVisual);
这个.saveRTBAsPNG(renderBitMap);
}
//基于元组列表创建DrawingVisual
私有DrawingVisual createDrawingVisual(列表元素)
{
DrawingVisual DrawingVisual=新建DrawingVisual();
使用(DrawingContext=drawingVisual.Renderropen())
{
列表元素中的foreach((UIElement元素、Rect边界、点位置)
{
VisualBrush VisualBrush=新的VisualBrush(元素);
DrawRectangle(visualBrush,null,new Rect(position,bounds.Size));
}
}
返回绘图可视化;
}
//将RenderTargetBitmap保存到文件
私有void saveRTBAsPNG(RenderTargetBitmap位图)
{
PngBitmapEncoder PngBitmapEncoder=新的PngBitmapEncoder()
{
交错=PngInterlaceOption.On
}
pngBitmapEncoder.Frames.Add(BitmapFrame.Create(bitmap));
使用(FileStream FileStream=File.Create(此._路径))
{
保存(文件流);
}
}
//为元素创建边界
私有Rect createBounds(UIElement)
{
新的Rect(新的大小((int)element.renderize.Width,(int)element.renderize.Height));
} 
//创建一个包含元素、其边界和位置的元组
私有(UIElement元素、矩形边界、点位置)createElementBoundPosition(UIElement元素)
{
返回(元素,this.createBounds(元素),元素.PointToScreen(新点(0,0));
} 
//创建渲染目标位图
私有RenderTargetBitmap createBitMap(矩形边界)
{
(整数宽度,整数高度)calculatedBounds=此。calculateBounds(边界);
返回新的RenderTargetBitmap(calculatedBounds.width、calculatedBounds.height、DPI、DPI、PixelFormats.Pbgra32);
}
//根据比例重新计算边界
专用(整数宽度、整数高度)计算器边界(矩形边界)
{
int width=(int)(bounds.width*DPISCALE);
int height=(int)(bounds.height*DPISCALE);
返回(宽度、高度);
}
//将弹出窗口列表转换为元组列表
私有列表CreateListPopubOutboundsPosition(列表列表Popup)
{
列表=新列表();
foreach(在listPopup中弹出p)
{
//子元素包含要渲染的UIElement
UIElement UIElement=p.子元素;
添加(this.createElementBoundPosition(uiElement));
}
退货清单;
}
//打开弹出窗口
私有列表getOpenPopups()
{
返回PresentationSource.CurrentSources.OfType()
.选择(h=>h.RootVisual)
第()类
.选择(f=>f.Parent)
第()类
其中(p=>p.IsOpen).ToList();
}
}

有没有找到这个问题的答案?谢谢