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