Alw*_*uff 8 c# wpf xaml panning
我已导出SVG为XAML,并且它变成了带有大量路径的Canvas.
在制作简单的自动生成窗口的Canvas主要内容之后,图像被剪裁,因为它比主窗口的客户端矩形更大.
我通过实现平移解决了这个问题.
由于我打算稍后进行缩放,我在Canvas中添加了虚拟ScaleTransform,XAML并将其RenderTransformOrigin更改为0.5 , 0.5(因此我可以围绕其中心缩放图像).
我想在加载窗口时将图像置于中心位置,所以我将Canvas放在Viewbox中,在调整了几个属性之后,它似乎工作得很好.
由于我已经更改了Canvas的RenderTransformOrigin,我无法弄清楚能够限制平移量的数学.
即使Viewbox是主窗口的内容,我也无法获得主窗口客户区的尺寸(Viewbox调整大小以适应其内容).这使我的任务更加困难.
除了使用P/Invoke和GetClientRectWinAPI调用之外,似乎没有其他方法可以获取主窗口的客户端矩形.
有另一个黑客查询SystemParametersInfo用于非客户指标,如边框和标题栏,但这是一个估计可能因应用主题和类似原因而失败.
我没试过用 P/Invoke因为我现在只是拒绝这样做.必须有比这更好的解决方案!那条道路应该是我的最后选择,也是我绝望的选择.
我试图找到自己的替代方法,但失败了.
我试图TransformToAncestor(...).Transformtobounds(..)用于我的计算,但也失败了.
如何限制平移,这样当用户拖得太多时,图像不会从主窗口消失?
我会接受替代解决方案.提交的代码是一个没有经验,自学成才的初学者的尝试,所以我接受建设性的批评和建议.
为了使这篇文章尽可能短,我只给出了相关的XAML和"代码隐藏"代码片段.
完整代码粘贴在Pastebin上,可以在本文的最底部找到.
相关的XAML片段:
<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>
Run Code Online (Sandbox Code Playgroud)
片段背后的相关代码:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我真的没有阅读完整的问题(我认为没有人会),但这是我在图表库中使用的用于限制平移的代码。这就是数学。现在将其适应您的情况。提示:下次仅输入相关代码,以便我们提供更好的答案。
我在平移结束时调用此方法(在我的例子中是鼠标松开事件)
如果有帮助的话,这是库(https://github.com/beto-rodriguez/Live-Charts),也许它也可以帮助您查看源代码。放松点,我认为你让事情变得比实际情况要困难得多。
private void PreventGraphToBeVisible()
{
var tt = Canvas.RenderTransform as TranslateTransform;
if (tt == null) return;
var eX = tt.X;
var eY = tt.Y;
var xOverflow = -tt.X + ActualWidth - Canvas.Width;
var yOverflow = -tt.Y + ActualHeight - Canvas.Height;
if (eX > 0)
{
tt.X = 0;
}
if (eY > 0)
{
tt.Y = 0;
}
if (xOverflow > 0)
{
tt.X = tt.X + xOverflow;
}
if (yOverflow > 0)
{
tt.Y = tt.Y + yOverflow;
}
}
Run Code Online (Sandbox Code Playgroud)