我正在将WPF Visual(UserControl)渲染到位图,但问题是渲染的图像在缩放/转换之前是UserControl的大小。所以我们假设UserControl的设计是200x200像素。当我渲染到BMP时,我正在使用UserControl的ActualWidth和ActualHeightt,它们分别报告200和200。问题是UserControl在Canvas中并且是自动调整大小(设置为按窗口大小缩放/填充)到更接近1200 x 1200(它更改)的内容
我已经完成了一些阅读和搜索,到目前为止还无法弄清楚如何确定有效大小,即控件在屏幕上绘制的大小。
我遇到了这个问题听起来很有希望,但返回的Transform不包含缩放数据。它确实如此,但它们都是1。 Get element position after transform
关于在哪里寻找渲染缩放的任何建议都会很棒!
[更新]根据建议,我包含相关代码:
public static Bitmap PngBitmap(this Visual visual)
{
// Get height and width
int width = (int)(double)visual.GetValue(
FrameworkElement.ActualWidthProperty);
int height = (int)(double)visual.GetValue(
FrameworkElement.ActualHeightProperty);
// Render
RenderTargetBitmap rtb =
new RenderTargetBitmap(
width,
height,
96,
96,
PixelFormats.Default);
rtb.Render(visual);
// Encode
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
System.IO.MemoryStream stream = new System.IO.MemoryStream();
encoder.Save(stream);
// Create Bitmap
Bitmap bmp = new Bitmap(stream);
stream.Close();
return bmp;
}
public static BitmapSource BitmapSource(this Visual visual)
{
Bitmap bmp = visual.PngBitmap();
IntPtr hBitmap = bmp.GetHbitmap();
BitmapSizeOptions sizeOptions = BitmapSizeOptions.FromEmptyOptions();
return Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
sizeOptions);
}
[更新#2] 添加了XAML - Grid元素已被删除,因为它是巨大的,从我对XAML的读取中,包含键盘UserControl的Canvas不是Grid元素的一部分。< / p>
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PMD.HECAT.DashboardModule"
xmlns:PMD_HECAT_DashboardModule_VirtualKeyboard="clr-namespace:PMD.HECAT.DashboardModule.VirtualKeyboard"
xmlns:System_Windows_Controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"
xmlns:PMD_HECAT_DashboardModule_Input="clr-namespace:PMD.HECAT.DashboardModule.Input"
xmlns:control="clr-namespace:PMD.HECAT.DashboardModule.Controls"
x:Class="PMD.HECAT.DashboardModule.CandidateElectrodeView"
x:Name="UserControl"
mc:Ignorable="d"
d:DesignWidth="1024" d:DesignHeight="768" Width="640" Height="360">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Themes/DashboardStyles.xaml" />
<ResourceDictionary Source="../Themes/ImageButtons.xaml" />
<ResourceDictionary Source="CandidateViewResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="PMD_HECAT_DashboardModule_VirtualKeyboard:VirtualKeyboardView.KeyboardClose" SourceName="virtualKeyboardView">
<BeginStoryboard Storyboard="{StaticResource OnKeyboardClose1}"/>
</EventTrigger>
</UserControl.Triggers>
<Canvas Width="100" HorizontalAlignment="Left">
<PMD_HECAT_DashboardModule_VirtualKeyboard:VirtualKeyboardView x:Name="virtualKeyboardView" Height="222" Width="550" RenderTransformOrigin="0.5,0.5" Opacity="0" Active="False">
<PMD_HECAT_DashboardModule_VirtualKeyboard:VirtualKeyboardView.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform X="40" Y="400"/>
</TransformGroup>
</PMD_HECAT_DashboardModule_VirtualKeyboard:VirtualKeyboardView.RenderTransform>
</PMD_HECAT_DashboardModule_VirtualKeyboard:VirtualKeyboardView>
<Rectangle Stroke="White" Opacity="0.7" Fill="White" Height="370" Width="654.851" Canvas.Left="687" Canvas.Top="0" />
</Canvas>
</UserControl>
答案 0 :(得分:6)
我知道问题被提出后已经过了很多时间,但发布更多信息并没有坏处:)
我使用此代码通过应用渲染变换查找视觉效果的大小(比例)。
GeneralTransform t = transformedVisual.TransformToVisual(parentVisual);
Vector topLeft = (Vector) t.Transform(new Point(0,0));
Vector topRight = (Vector) t.Transform(new Point(originalWidthOfTransformedVisual, 0));
double renderedWidth = (topRight-topLeft).Length;
double widthScale = renderedWidth / originalWidthOfTransformedVisual;
答案 1 :(得分:1)
在大多数其他情况下,您可以使用ActualHeight和ActualWidth属性来获取FrameworkElement的大小。尽管如此,这些属性将为您提供边界框的大小,这对于您描述的场景来说已经足够了。
答案 2 :(得分:1)
如果在强制执行此渲染之前未显示视觉效果,我有类似的问题
uiElement.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
uiElement.Arrange(new Rect(new Point(0, 0), uiElement.DesiredSize));
Size _size = uiElement.DesiredSize;
这至少在我的情况下适用于UIElement
渲染它的大小
答案 3 :(得分:0)
你说你使用Visual的宽度和高度。 首先,有两个问题。 视觉上,http://msdn.microsoft.com/en-us/library/system.windows.media.visual.aspx没有任何高度和宽度属性。
现在,假设您有一个FrameworkElement,它具有Height和Width属性,您使用的是Height和Width属性,还是ActualHeight和ActualWidth属性? 如果您不是,那么这些是您正在寻找的属性。
如果您正在使用它们,或者您没有使用FrameworkElement,那么您应该发布一些代码。
答案 4 :(得分:0)
如果您可以使用动画来执行Transform
,那么动画会提供Completed
事件。这应该是提取新变换大小的好地方。
答案 5 :(得分:0)
public static Rect GetRelativePlacement(this UIElement element, UIElement relativeTo)
{
var absolutePos = element.PointToScreen(new Point(0, 0));
var posRelativeTo = relativeTo.PointToScreen(new Point(0, 0));
var topLeft = new Point(absolutePos.X - posRelativeTo.X, absolutePos.Y - posRelativeTo.Y);
var bottomRight = element.PointToScreen(new Point(element.RenderSize.Width, element.RenderSize.Height));
var bounds = Rect.Empty;
bounds.Union(topLeft);
bounds.Union(bottomRight);
return bounds;
}
答案 6 :(得分:0)
基于@bor的答案,我简化了代码以允许更常见的使用:
private static Rect GetTransformedVisualBounds(Visual source, Visual target, Rect bounds)
{
return source.TransformToVisual(target).TransformBounds(bounds);
}
source
是一个可视化对象,可以应用转换; target
是将坐标转换为的外观; bounds
是源Visual的未变换范围; 以下是使用上述方法的示例:
private void ExampleOfUse()
{
Border border = new Border()
{
Width = 100,
Height = 100
};
ContainerVisual container = new ContainerVisual();
container.Children.Add(border);
container.Transform = new ScaleTransform(2d, 2d);
Rect transformedBounds = GetTransformedVisualBounds(container, this, VisualTreeHelper.GetDescendantBounds(container));
// This should print a rectangle with a size of 200x200;
Debug.Print($"Transformed bounds: {transformedBounds}");
}
这是一个非常老的问题,但这对我很有用,我希望它对其他人也有用。