【发布时间】:2016-01-13 02:56:15
【问题描述】:
简介:
我已将SVG 导出为XAML,它变成了具有大量路径的画布。
在制作简单的自动生成窗口的 Canvas 主要内容后,图像被裁剪,因为它大于主窗口的客户矩形。
我已经通过实现平移解决了这个问题。
由于我计划稍后调整缩放,我在 Canvas 的 XAML 中添加了虚拟 ScaleTransform,并将其 RenderTransformOrigin 更改为 0.5 , 0.5(以便我可以围绕其中心缩放图像)。
我希望在加载窗口时图像居中,所以我将 Canvas 放在 Viewbox 中,在调整了一些属性后,它似乎工作得很好。
问题:
由于我更改了画布的 RenderTransformOrigin,我无法计算出可以限制平移量的数学运算。
即使 Viewbox 是主窗口的内容,我也无法获得主窗口客户区的尺寸(Viewbox 调整大小以适应其内容)。这让我的任务更加困难。
我为解决这个问题所做的努力:
除了使用P/Invoke 和GetClientRect WinAPI 调用外,似乎没有其他方法可以获取主窗口的客户矩形。
还有另一个 hack 用于查询 SystemParametersInfo 以获取边框和标题栏等非客户端指标,但这是一个估计,可能会因应用主题和类似情况而失败。
我没有尝试使用P/Invoke,因为我现在只是拒绝这样做。必须有比这更好的解决方案!那条路应该是我最后的选择,也是我会在绝望中走的路。
我曾尝试自行寻找替代方法,但失败了。
我曾尝试使用TransformToAncestor(...).Transformtobounds(..) 进行计算,但也失败了。
问题:
当用户拖动太多时,如何限制平移以使图像不会从主窗口中消失?
我会接受替代解决方案。提交的代码是一个没有经验、自学成才的初学者的尝试,所以我接受建设性的批评和建议。
相关信息:
为了使这篇文章尽可能简短,我在下面只给出相关的 XAML 和“代码隐藏”sn-ps。
完整的代码粘贴在 Pastebin 上,可以在这篇文章的最底部找到。
相关XAML sn-ps:
<Window x:Class="TestZaMapu.MainWindow"
Name="GlavniProzor"
WindowStartupLocation="CenterScreen"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525"
MouseLeftButtonDown="GlavniProzor_MouseLeftButtonDown"
MouseLeftButtonUp="GlavniProzor_MouseLeftButtonUp"
MouseMove="GlavniProzor_MouseMove"
LostMouseCapture="GlavniProzor_LostMouseCapture">
<Viewbox
Name="surface"
Stretch="UniformToFill"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Background="Blue"
x:Name="svg4306"
Width="494.44705"
Height="510.55356"
<!-- needed in the future, for zooming around center-->
RenderTransformOrigin="0.5, 0.5">
<!--Unknown tag: metadata-->
<Canvas.RenderTransform>
<TransformGroup>
<!-- I intend to experiment with scaling in the future, so I added the below part -->
<ScaleTransform ScaleX="1" ScaleY="1"/>
<!-- I have used dependency properties for translation -->
<TranslateTransform X="{Binding TranslationFactorX, ElementName=GlavniProzor, Mode=TwoWay}" Y="{Binding TranslationFactorY, ElementName=GlavniProzor, Mode=TwoWay}"/>
</TransformGroup>
</Canvas.RenderTransform>
<!-- Bunch of Path objects, omitted for brevity-->
</Canvas>
</Viewbox>
</Window>
sn-ps 背后的相关代码:
namespace TestZaMapu
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TranslationFactorX = 0;
TranslationFactorY = 0;
isPanning = false;
}
// panning variables
private Point ptOldPosition;
private bool isPanning ;
// dependency properties for translation along X and Y axes
public static readonly DependencyProperty TranslateX =
DependencyProperty.Register("TranslationFactorX", typeof(double), typeof(MainWindow));
public static readonly DependencyProperty TranslateY =
DependencyProperty.Register("TranslationFactorY", typeof(double), typeof(MainWindow));
public double TranslationFactorX
{
get { return (double)GetValue(TranslateX); }
set { SetValue(TranslateX, value); }
}
public double TranslationFactorY
{
get { return (double)GetValue(TranslateY); }
set { SetValue(TranslateY, value); }
}
// mouse event handlers for panning
private void GlavniProzor_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (isPanning )
return;
isPanning = this.CaptureMouse();
ptOldPosition = e.GetPosition(this);
}
private void GlavniProzor_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
if (this.IsMouseCaptured)
{
this.ReleaseMouseCapture();
isPanning = false;
}
}
private void GlavniProzor_MouseMove(object sender, MouseEventArgs e)
{
base.OnMouseMove(e);
if (isPanning )
{
Point ptNewPosition = e.GetPosition(this);
if (ptNewPosition != ptOldPosition)
{
Vector direction = ptOldPosition - ptNewPosition;
direction.X = TranslationFactorX - direction.X;
direction.Y = TranslationFactorY - direction.Y;
TranslationFactorX = direction.X;
TranslationFactorY = direction.Y;
ptOldPosition = ptNewPosition;
}
}
}
private void GlavniProzor_LostMouseCapture(object sender, MouseEventArgs e)
{
isPanning = false;
this.OnLostMouseCapture(e);
}
}
}
【问题讨论】:
-
“为了让这篇文章尽可能简短”——太晚了。 :) 说真的,一个好的 Stack Overflow 问题将包括清楚地说明问题的a good, minimal, complete code example,以及对当前特定问题的简明描述。为了解决您需要帮助的特定问题,您的叙述以及几乎可以肯定不需要阅读的代码有很多。
-
您可能需要做的就是将您的内容放在
Grid中,而后者又包含在ScrollViewer中。但对于如此广泛的问题,我们无法确定。 -
@PeterDuniho:我不明白我的帖子有什么不清楚/广泛的地方。我将图像从 SVG 导出到 XAML(它是 一个巨大的 Canvas)。我想在简单的窗口中显示该图像。它不适合,所以我决定实施平移。由于稍后我将添加缩放围绕中心,因此我已将 Canvas 的 RenderTransformOrigin 编辑为
0.5 , 0.5。然后将 Canvas 放置在 Viewbox 内,该 viewbox 就是主窗口的内容。我想限制平移,因此图像不会移出窗口,将其留空。完整的 XAML 和背后的代码链接在帖子的最底部。