Windows 8.1 中的 WPF 操作
WPF Manipulation in Windows 8.1
任何人都可以提供一些链接,指向如何在 Windows 8.1 中进行操作的示例吗?
我在网上看到很多关于如何为 Windows 7 执行此操作的示例,但它在我的 Windows 8.1 机器(带触摸屏)上对我不起作用。我正在使用 VS Studio Community v15。这是我一直在尝试的示例:
https://www.tutorialspoint.com/wpf/wpf_multi_touch.htm
使用鼠标或手指根本不会发生任何事情 - 没有移动、没有缩放、没有旋转等。
P.S.,我正在 VB,而不是 C# 中做我的项目。
例如,
<Window x:Class = "WpfManipulation1.MainWindow"
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:WpfManipulation1"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
<Window.Resources>
<MatrixTransform x:Key = "InitialMatrixTransform">
<MatrixTransform.Matrix>
<Matrix OffsetX = "200" OffsetY = "200"/>
</MatrixTransform.Matrix>
</MatrixTransform>
</Window.Resources>
<Canvas>
<Rectangle Name = "manRect" Width = "321" Height = "241"
RenderTransform = "{StaticResource InitialMatrixTransform}"
IsManipulationEnabled = "true" Canvas.Left = "-70" Canvas.Top = "-170">
<Rectangle.Fill>
<ImageBrush ImageSource = "ManipImage.JPG"/>
</Rectangle.Fill>
</Rectangle>
<Image Source="ManipImage.jpg" ManipulationMode="All" ManipulationDelta="UIElement_OnManipulationDelta" />
</Canvas>
</Window>
部分成功...
XAML:
<Window x:Class="MainWindow"
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:WpfManipulation2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image Source="ManipImage.jpg" IsManipulationEnabled="True" ManipulationDelta="OnManipulationDelta" />
</Grid>
</Window>
VB 代码隐藏:
Imports System.Windows.UIElement
Class MainWindow
Private Sub OnManipulationDelta(ByVal sender As Object, ByVal e As ManipulationDeltaEventArgs)
Dim transformGroup = GetTransformGroup(sender)
Dim translateTransform = transformGroup.Children.OfType(Of TranslateTransform).First
Dim rotateTransform = transformGroup.Children.OfType(Of RotateTransform).First
Dim scaleTransform = transformGroup.Children.OfType(Of ScaleTransform).First
translateTransform.X = (translateTransform.X + e.DeltaManipulation.Translation.X)
translateTransform.Y = (translateTransform.Y + e.DeltaManipulation.Translation.Y)
rotateTransform.Angle = (rotateTransform.Angle + e.DeltaManipulation.Rotation)
scaleTransform.ScaleY = (scaleTransform.ScaleY * e.DeltaManipulation.Scale.Y)
scaleTransform.ScaleX = (scaleTransform.ScaleX * e.DeltaManipulation.Scale.X)
End Sub
Private Function GetTransformGroup(ByVal sender As Object) As TransformGroup
Dim element = CType(sender, UIElement)
element.RenderTransformOrigin = New Point(0.5, 0.5)
Dim transformGroup = CType(element.RenderTransform, TransformGroup)
If (transformGroup Is Nothing) Then
transformGroup = New TransformGroup
transformGroup.Children.Add(New TranslateTransform)
transformGroup.Children.Add(New ScaleTransform)
transformGroup.Children.Add(New RotateTransform)
element.RenderTransform = transformGroup
End If
Return transformGroup
End Function
End Class
行 "Dim transformGroup = CType(element.RenderTransform, TransformGroup)" 上的错误:System.InvalidCastException:“无法将类型 'System.Windows.Media.MatrixTransform' 的对象转换为类型 'System.Windows.Media.TransformGroup'。”
这是实施所提供建议的结果。
XAML:
<Window x:Class="WpfTutorialSamples.Common_interface_controls.ToolbarSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ToolbarSample"
Top="50" Left="50" Height="500" Width="700">
<Window.CommandBindings>
<CommandBinding Command="New" CanExecute="CommonCommandBinding_CanExecute" />
<CommandBinding Command="Open" CanExecute="CommonCommandBinding_CanExecute" />
<CommandBinding Command="Save" CanExecute="CommonCommandBinding_CanExecute" />
</Window.CommandBindings>
<Window.Resources>
<MatrixTransform x:Key = "InitialMatrixTransform">
<MatrixTransform.Matrix>
<Matrix OffsetX = "0" OffsetY = "0"/>
</MatrixTransform.Matrix>
</MatrixTransform>
</Window.Resources>
<Grid x:Name="grid_MainWindow" Margin="0,0,0,0">
<DockPanel>
<ToolBarTray x:Name="myToolBarTray" DockPanel.Dock="Top" Panel.ZIndex="1">
<!--
<ToolBar>
<Button Command="New" Content="New" />
<Button Command="Open" Content="Open" />
<Button Command="Save" Content="Save" />
</ToolBar>
<ToolBar>
<Button Command="Cut" Content="Cut" />
<Button Command="Copy" Content="Copy" />
<Button Command="Paste" Content="Paste" />
</ToolBar>
-->
<ToolBar x:Name="myToolBar" Height="30">
<Button Name="button_HideWindows" Content="Un/Hide" />
<Button Name="button_ClearWindows" Content="Clear" />
<Button Name="button_ResetMatrix" Content="Reset" />
</ToolBar>
</ToolBarTray>
<!-- <TextBox AcceptsReturn="True" /> -->
<!-- <Canvas x:Name="canvas_Main"/> -->
<Canvas x:Name="canvas_Main" Background="LightPink" >
<!--
<Rectangle Name = "manRect" Width = "300" Height = "300"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="0,0,0,0"
IsManipulationEnabled="True" ManipulationDelta="Window_ManipulationDelta"
RenderTransform = "{StaticResource InitialMatrixTransform}"
>
<Rectangle.Fill>
<SolidColorBrush Color="LightBlue" />
</Rectangle.Fill>
</Rectangle>
-->
<Canvas Name = "manRect" Width = "300" Height = "300"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="0,0,0,0"
IsManipulationEnabled="True" ManipulationDelta="Window_ManipulationDelta"
RenderTransform = "{StaticResource InitialMatrixTransform}"
Background="LightBlue"
>
</Canvas>
<Label x:Name="label_ZoomIn" Content="ZIn" Canvas.Left="330" Canvas.Top="370" Background="LightSkyBlue"/>
<Label x:Name="label_ZoomOut" Content="ZOut" Canvas.Left="330" Canvas.Top="400" Background="LightSkyBlue"/>
</Canvas>
</DockPanel>
<StackPanel x:Name="stackpanel_NW" Background="LightYellow" HorizontalAlignment="Left" Margin="0,30,0,0" VerticalAlignment="Top" Height="100" Width="300">
<Grid x:Name="grid_NW">
<TextBox x:Name="textbox_NW" Background="LightYellow" BorderThickness="0" AcceptsReturn="True" Height="90" Width="290" Margin="5,5,5,5" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>
</StackPanel>
<StackPanel x:Name="stackpanel_NE" Background="LightYellow" HorizontalAlignment="Right" Margin="0,30,0,0" VerticalAlignment="Top" Height="300" Width="300">
<Grid x:Name="grid_NE">
<TextBox x:Name="textbox_NE" Background="LightYellow" BorderThickness="0" AcceptsReturn="True" Height="290" Width="290" Margin="5,5,5,5" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>
</StackPanel>
<StackPanel x:Name="stackpanel_SW" Background="LightYellow" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Bottom" Height="100" Width="300">
<Grid x:Name="grid_SW">
<TextBox x:Name="textbox_SW" Background="LightYellow" BorderThickness="0" AcceptsReturn="True" Height="90" Width="290" Margin="5,5,5,5" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>
</StackPanel>
<StackPanel x:Name="stackpanel_SE" Background="LightYellow" HorizontalAlignment="Right" Margin="0,0,0,0" VerticalAlignment="Bottom" Height="100" Width="300">
<Grid x:Name="grid_SE">
<TextBox x:Name="textbox_SE" Background="LightYellow" BorderThickness="0" AcceptsReturn="True" Height="90" Width="290" Margin="5,5,5,5" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>
</StackPanel>
</Grid>
</Window>
代码隐藏(VB):
'Reference: http://www.wpf-tutorial.com/common-interface-controls/toolbar-control/
Imports System
Imports System.Windows
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Shapes
Namespace WpfTutorialSamples.Common_interface_controls
Public Class ToolbarSample
Inherits Window
Dim CausedByCode As Boolean
Dim ZoomFactor As Double = 0.1
Dim ZoomMax As Double = 4.95
Dim ZoomMin As Double = 0.05
Dim NumberOfLevels As Integer = 6
Dim NumberOfCellsPerLevel As Integer = 2
Dim LvlBuffer As Double = 0.02
Dim CellBuffer As Double = 0.05
Dim LvlContainerColor As Brush = Brushes.LightGreen
Dim CellContainerColor As Brush = Brushes.LightYellow
Dim LvlDividerColor As Brush = Brushes.Red
Public Sub New()
MyBase.New
InitializeComponent()
End Sub
Private Sub MainWindow_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
'HideWindows(False, New StackPanel() {stackpanel_NW, stackpanel_SE, stackpanel_SW})
HideWindows(True, New StackPanel() {}) 'all
End Sub
Private Sub MainWindow_Loaded(sender As Object, e As EventArgs) Handles Me.Loaded
'add dividers
For a = 1 To (NumberOfLevels - 1)
Dim top As Double = a * (manRect.Height / NumberOfLevels)
Dim LvlDivider As New Canvas
LvlDivider.Background = LvlDividerColor
LvlDivider.Width = manRect.Width
LvlDivider.Height = 0.25
manRect.Children.Add(LvlDivider)
Canvas.SetLeft(LvlDivider, 0)
Canvas.SetTop(LvlDivider, top)
Next
'add levels
For a = 0 To (NumberOfLevels - 1)
Dim LvlWidth As Double = manRect.Width
Dim LvlHeight As Double = manRect.Height / NumberOfLevels
Dim LvlTop As Double = (a * LvlHeight) + (LvlBuffer * LvlHeight)
Dim LvlBottom As Double = LvlHeight - (2 * LvlBuffer * LvlHeight)
Dim LvlContainer As New Canvas
LvlContainer.Background = LvlContainerColor
LvlContainer.Width = LvlWidth
LvlContainer.Height = LvlBottom
manRect.Children.Add(LvlContainer)
Canvas.SetLeft(LvlContainer, 0)
Canvas.SetTop(LvlContainer, LvlTop)
'add cells
For b = 0 To (NumberOfCellsPerLevel - 1)
Dim CellWidth As Double = LvlWidth / NumberOfCellsPerLevel
Dim CellWidthBuffered As Double = CellWidth - (2 * CellBuffer * CellWidth)
Dim CellHeight As Double = LvlBottom
Dim CellTop As Double = (CellBuffer * CellHeight)
Dim CellBottom As Double = CellHeight - (2 * CellBuffer * CellHeight)
Dim CellLeft As Double = (b * CellWidth) + (CellBuffer * CellWidth)
Dim CellContainer As New Canvas
CellContainer.Background = CellContainerColor
CellContainer.Width = CellWidthBuffered
CellContainer.Height = CellBottom
LvlContainer.Children.Add(CellContainer)
Canvas.SetLeft(CellContainer, CellLeft)
Canvas.SetTop(CellContainer, CellTop)
Next
Next
'
ResetMatrix_Click(button_ResetMatrix, Nothing)
End Sub
Private Sub CommonCommandBinding_CanExecute(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
e.CanExecute = True
End Sub
Private Sub HideWindows_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles button_HideWindows.Click
HideWindows(False, New StackPanel() {stackpanel_NE, stackpanel_NW, stackpanel_SE, stackpanel_SW})
End Sub
Private Sub ClearWindows_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles button_ClearWindows.Click
ClearWindows(New StackPanel() {stackpanel_NE, stackpanel_NW, stackpanel_SE, stackpanel_SW})
End Sub
Private Sub HideWindows(ByVal Hide As Boolean, StackPanels() As StackPanel)
If StackPanels.Length = 0 Then
HideWindows(False, New StackPanel() {stackpanel_NE, stackpanel_NW, stackpanel_SE, stackpanel_SW})
Else
For Each s In StackPanels
If StackPanels.Length = 4 Then
s.Visibility = IIf((s.Visibility = Visibility.Hidden), Visibility.Visible, Visibility.Hidden)
Else
s.Visibility = IIf(Hide, Visibility.Visible, Visibility.Hidden)
End If
Next
End If
End Sub
Private Sub ClearWindows(StackPanels() As StackPanel)
For Each s In StackPanels
Dim g As Grid = (From a In s.Children Where a.GetType = GetType(Grid)
Select TryCast(a, Grid)).FirstOrDefault
Dim t As TextBox = (From a In g.Children Where a.GetType = GetType(TextBox)
Select TryCast(a, TextBox)).FirstOrDefault
If s.Visibility = Visibility.Visible Then t.Clear()
Next
End Sub
Private Sub ResetMatrix_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles button_ResetMatrix.Click
'CenterAboutPoint(New Point(150, 150), e) 'top-left
CenterAboutPoint(New Point(Me.Width / 2, (Me.Height / 2) - myToolBar.Height), False, False, False, e) 'middle of window
End Sub
Private Sub label_ZoomIn_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles label_ZoomIn.MouseDown
CenterAboutPoint(New Point(Me.Width / 2, (Me.Height / 2) - myToolBar.Height), True, True, False, e)
End Sub
Private Sub label_ZoomOut_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles label_ZoomOut.MouseDown
CenterAboutPoint(New Point(Me.Width / 2, (Me.Height / 2) - myToolBar.Height), True, False, False, e)
End Sub
Private Sub CenterAboutPoint(ByVal p As Point, ByVal JustZoom As Boolean, ByVal ZoomDir As Boolean, ByVal JustTranslate As Boolean, ByVal e As RoutedEventArgs)
'Dim rectToMove As Rectangle = CType(manRect, Rectangle)
Dim rectToMove As Canvas = CType(manRect, Canvas)
Dim rectsMatrix As Matrix = CType(rectToMove.RenderTransform, MatrixTransform).Matrix
Dim ZoomLevel As Double = rectsMatrix.M11
Dim transform = TransformToVisual(manRect)
'textbox_NE.Text = "zoom: " & ZoomLevel & ", width: " & manRect.Width & ", height: " & manRect.Height
Dim elemPosTopLeft = manRect.TranslatePoint(New Point(0, 0), canvas_Main)
'textbox_NE.AppendText(vbCrLf & "elemPosTopLeft: " & elemPosTopLeft.ToString)
Dim elemPosBottomRight = manRect.TranslatePoint(New Point(manRect.ActualWidth, manRect.ActualHeight), canvas_Main)
'textbox_NE.AppendText(vbCrLf & "elemPosBottomRight: " & elemPosBottomRight.ToString)
Dim elemPosWidth = (elemPosBottomRight.X - elemPosTopLeft.X) '* -ZoomLevel
'textbox_NE.AppendText(vbCrLf & "elemPosWidth: " & elemPosWidth.ToString)
Dim elemPosHeight = (elemPosBottomRight.Y - elemPosTopLeft.Y) '* -ZoomLevel
'textbox_NE.AppendText(vbCrLf & "elemPosHeight: " & elemPosHeight.ToString)
Dim elemPosLeft = elemPosTopLeft.X
'textbox_NE.AppendText(vbCrLf & "elemPosLeft: " & elemPosLeft.ToString)
Dim elemPosTop = elemPosTopLeft.Y
'textbox_NE.AppendText(vbCrLf & "elemPosTop: " & elemPosTop.ToString)
Dim elemPosBottom = elemPosBottomRight.Y
'textbox_NE.AppendText(vbCrLf & "elemPosBottom: " & elemPosBottom.ToString)
Dim elemPosRight = elemPosBottomRight.X
'textbox_NE.AppendText(vbCrLf & "elemPosRight: " & elemPosRight.ToString)
Dim elemPosCenterX = elemPosLeft + (elemPosWidth / 2)
'textbox_NE.AppendText(vbCrLf & "elemPosCenterX: " & elemPosCenterX.ToString)
Dim elemPosCenterY = elemPosTop + (elemPosHeight / 2)
'textbox_NE.AppendText(vbCrLf & "elemPosCenterY: " & elemPosCenterY.ToString)
'offsets from point
Dim elemPosLeftOffset = p.X - elemPosCenterX
'textbox_NE.AppendText(vbCrLf & "elemPosLeftOffset: " & elemPosLeftOffset.ToString)
Dim elemPosTopOffset = p.Y - elemPosCenterY
'textbox_NE.AppendText(vbCrLf & "elemPosTopOffset: " & elemPosTopOffset.ToString)
'scale
If JustTranslate = False Then
If JustZoom = False Then
If ZoomLevel <> 1 Then
rectsMatrix.ScaleAt((1 / ZoomLevel), (1 / ZoomLevel), elemPosCenterX, elemPosCenterY)
End If
Else
Dim NewZoomLevel = IIf(ZoomDir = True, (1 + ZoomFactor), (1 - ZoomFactor))
'textbox_NE.AppendText(vbCrLf & "NewZoomLevel: " & NewZoomLevel.ToString)
If ((ZoomLevel * NewZoomLevel) >= ZoomMin) And ((ZoomLevel * NewZoomLevel) <= ZoomMax) Then
rectsMatrix.ScaleAt(NewZoomLevel, NewZoomLevel, elemPosCenterX, elemPosCenterY)
End If
End If
End If
'translate
If JustZoom = False Then
rectsMatrix.Translate(elemPosLeftOffset, elemPosTopOffset)
End If
'transform
rectToMove.RenderTransform = New MatrixTransform(rectsMatrix)
If Not IsNothing(e) Then e.Handled = True
End Sub
Private Sub Window_ManipulationStarting(ByVal sender As Object, ByVal e As ManipulationStartingEventArgs)
e.ManipulationContainer = Me
e.Handled = True
End Sub
Private Sub Window_ManipulationDelta(ByVal sender As Object, ByVal e As ManipulationDeltaEventArgs)
'Reference: https://www.tutorialspoint.com/wpf/wpf_multi_touch.htm
'Dim rectToMove As Rectangle = CType(e.OriginalSource, Rectangle)
Dim rectToMove As Canvas = CType(e.OriginalSource, Canvas)
Dim rectsMatrix As Matrix = CType(rectToMove.RenderTransform, MatrixTransform).Matrix
Dim ZoomLevel As Double = rectsMatrix.M11
'scale
Dim scale As Double = (e.DeltaManipulation.Scale.X + e.DeltaManipulation.Scale.Y) / 2
rectsMatrix.ScaleAtPrepend(scale, scale, e.ManipulationOrigin.X, e.ManipulationOrigin.Y)
'translate
If CausedByCode = False AndAlso (Math.Abs(e.DeltaManipulation.Translation.X) > 1 Or Math.Abs(e.DeltaManipulation.Translation.Y) > 1) Then
rectsMatrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y)
CausedByCode = True
Else
CausedByCode = False
End If
'apply transformation
If (rectsMatrix.M11 >= ZoomMin) And (rectsMatrix.M11 <= ZoomMax) Then
rectToMove.RenderTransform = New MatrixTransform(rectsMatrix)
End If
Dim containingRect As Rect = New Rect(CType(e.ManipulationContainer, FrameworkElement).RenderSize)
Dim shapeBounds As Rect = rectToMove.RenderTransform.TransformBounds(New Rect(rectToMove.RenderSize))
If (e.IsInertial AndAlso Not containingRect.Contains(shapeBounds)) Then
e.Complete()
End If
e.Handled = True
End Sub
Private Sub Window_InertiaStarting(ByVal sender As Object, ByVal e As ManipulationInertiaStartingEventArgs)
e.TranslationBehavior.DesiredDeceleration = (10 * (96 / (1000 * 1000))) 'inches per second squared
e.ExpansionBehavior.DesiredDeceleration = (0.1 * (96 / (1000 * 1000))) 'inches per second squared
e.RotationBehavior.DesiredDeceleration = (720 / (1000 * 1000)) 'degrees per second squared
e.Handled = True
End Sub
End Class
End Namespace
该程序运行良好,尽管在按比例缩小后长时间拖动矩阵时会出现问题...这可能是由于惯性造成的。
以下允许对指定图像进行基本操作:
XAML
<Image Source="https://placehold.it/200x200" IsManipulationEnabled="True" ManipulationDelta="OnManipulationDelta" />
代码隐藏 (C#)
private void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
var transformGroup = GetTransformGroup(sender);
var translateTransform = transformGroup.Children.OfType<TranslateTransform>().First();
var rotateTransform = transformGroup.Children.OfType<RotateTransform>().First();
var scaleTransform = transformGroup.Children.OfType<ScaleTransform>().First();
translateTransform.X += e.DeltaManipulation.Translation.X;
translateTransform.Y += e.DeltaManipulation.Translation.Y;
rotateTransform.Angle += e.DeltaManipulation.Rotation;
scaleTransform.ScaleY *= e.DeltaManipulation.Scale.Y;
scaleTransform.ScaleX *= e.DeltaManipulation.Scale.X;
}
private TransformGroup GetTransformGroup(object sender)
{
var element = sender as UIElement;
element.RenderTransformOrigin = new Point(.5, .5);
var transformGroup = element.RenderTransform as TransformGroup;
if (transformGroup == null)
{
transformGroup = new TransformGroup();
transformGroup.Children.Add(new TranslateTransform());
transformGroup.Children.Add(new ScaleTransform());
transformGroup.Children.Add(new RotateTransform());
element.RenderTransform = transformGroup;
}
return transformGroup;
}
任何人都可以提供一些链接,指向如何在 Windows 8.1 中进行操作的示例吗?
我在网上看到很多关于如何为 Windows 7 执行此操作的示例,但它在我的 Windows 8.1 机器(带触摸屏)上对我不起作用。我正在使用 VS Studio Community v15。这是我一直在尝试的示例:
https://www.tutorialspoint.com/wpf/wpf_multi_touch.htm
使用鼠标或手指根本不会发生任何事情 - 没有移动、没有缩放、没有旋转等。
P.S.,我正在 VB,而不是 C# 中做我的项目。
例如,
<Window x:Class = "WpfManipulation1.MainWindow"
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:WpfManipulation1"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
<Window.Resources>
<MatrixTransform x:Key = "InitialMatrixTransform">
<MatrixTransform.Matrix>
<Matrix OffsetX = "200" OffsetY = "200"/>
</MatrixTransform.Matrix>
</MatrixTransform>
</Window.Resources>
<Canvas>
<Rectangle Name = "manRect" Width = "321" Height = "241"
RenderTransform = "{StaticResource InitialMatrixTransform}"
IsManipulationEnabled = "true" Canvas.Left = "-70" Canvas.Top = "-170">
<Rectangle.Fill>
<ImageBrush ImageSource = "ManipImage.JPG"/>
</Rectangle.Fill>
</Rectangle>
<Image Source="ManipImage.jpg" ManipulationMode="All" ManipulationDelta="UIElement_OnManipulationDelta" />
</Canvas>
</Window>
部分成功... XAML:
<Window x:Class="MainWindow"
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:WpfManipulation2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image Source="ManipImage.jpg" IsManipulationEnabled="True" ManipulationDelta="OnManipulationDelta" />
</Grid>
</Window>
VB 代码隐藏:
Imports System.Windows.UIElement
Class MainWindow
Private Sub OnManipulationDelta(ByVal sender As Object, ByVal e As ManipulationDeltaEventArgs)
Dim transformGroup = GetTransformGroup(sender)
Dim translateTransform = transformGroup.Children.OfType(Of TranslateTransform).First
Dim rotateTransform = transformGroup.Children.OfType(Of RotateTransform).First
Dim scaleTransform = transformGroup.Children.OfType(Of ScaleTransform).First
translateTransform.X = (translateTransform.X + e.DeltaManipulation.Translation.X)
translateTransform.Y = (translateTransform.Y + e.DeltaManipulation.Translation.Y)
rotateTransform.Angle = (rotateTransform.Angle + e.DeltaManipulation.Rotation)
scaleTransform.ScaleY = (scaleTransform.ScaleY * e.DeltaManipulation.Scale.Y)
scaleTransform.ScaleX = (scaleTransform.ScaleX * e.DeltaManipulation.Scale.X)
End Sub
Private Function GetTransformGroup(ByVal sender As Object) As TransformGroup
Dim element = CType(sender, UIElement)
element.RenderTransformOrigin = New Point(0.5, 0.5)
Dim transformGroup = CType(element.RenderTransform, TransformGroup)
If (transformGroup Is Nothing) Then
transformGroup = New TransformGroup
transformGroup.Children.Add(New TranslateTransform)
transformGroup.Children.Add(New ScaleTransform)
transformGroup.Children.Add(New RotateTransform)
element.RenderTransform = transformGroup
End If
Return transformGroup
End Function
End Class
行 "Dim transformGroup = CType(element.RenderTransform, TransformGroup)" 上的错误:System.InvalidCastException:“无法将类型 'System.Windows.Media.MatrixTransform' 的对象转换为类型 'System.Windows.Media.TransformGroup'。”
这是实施所提供建议的结果。
XAML:
<Window x:Class="WpfTutorialSamples.Common_interface_controls.ToolbarSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ToolbarSample"
Top="50" Left="50" Height="500" Width="700">
<Window.CommandBindings>
<CommandBinding Command="New" CanExecute="CommonCommandBinding_CanExecute" />
<CommandBinding Command="Open" CanExecute="CommonCommandBinding_CanExecute" />
<CommandBinding Command="Save" CanExecute="CommonCommandBinding_CanExecute" />
</Window.CommandBindings>
<Window.Resources>
<MatrixTransform x:Key = "InitialMatrixTransform">
<MatrixTransform.Matrix>
<Matrix OffsetX = "0" OffsetY = "0"/>
</MatrixTransform.Matrix>
</MatrixTransform>
</Window.Resources>
<Grid x:Name="grid_MainWindow" Margin="0,0,0,0">
<DockPanel>
<ToolBarTray x:Name="myToolBarTray" DockPanel.Dock="Top" Panel.ZIndex="1">
<!--
<ToolBar>
<Button Command="New" Content="New" />
<Button Command="Open" Content="Open" />
<Button Command="Save" Content="Save" />
</ToolBar>
<ToolBar>
<Button Command="Cut" Content="Cut" />
<Button Command="Copy" Content="Copy" />
<Button Command="Paste" Content="Paste" />
</ToolBar>
-->
<ToolBar x:Name="myToolBar" Height="30">
<Button Name="button_HideWindows" Content="Un/Hide" />
<Button Name="button_ClearWindows" Content="Clear" />
<Button Name="button_ResetMatrix" Content="Reset" />
</ToolBar>
</ToolBarTray>
<!-- <TextBox AcceptsReturn="True" /> -->
<!-- <Canvas x:Name="canvas_Main"/> -->
<Canvas x:Name="canvas_Main" Background="LightPink" >
<!--
<Rectangle Name = "manRect" Width = "300" Height = "300"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="0,0,0,0"
IsManipulationEnabled="True" ManipulationDelta="Window_ManipulationDelta"
RenderTransform = "{StaticResource InitialMatrixTransform}"
>
<Rectangle.Fill>
<SolidColorBrush Color="LightBlue" />
</Rectangle.Fill>
</Rectangle>
-->
<Canvas Name = "manRect" Width = "300" Height = "300"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="0,0,0,0"
IsManipulationEnabled="True" ManipulationDelta="Window_ManipulationDelta"
RenderTransform = "{StaticResource InitialMatrixTransform}"
Background="LightBlue"
>
</Canvas>
<Label x:Name="label_ZoomIn" Content="ZIn" Canvas.Left="330" Canvas.Top="370" Background="LightSkyBlue"/>
<Label x:Name="label_ZoomOut" Content="ZOut" Canvas.Left="330" Canvas.Top="400" Background="LightSkyBlue"/>
</Canvas>
</DockPanel>
<StackPanel x:Name="stackpanel_NW" Background="LightYellow" HorizontalAlignment="Left" Margin="0,30,0,0" VerticalAlignment="Top" Height="100" Width="300">
<Grid x:Name="grid_NW">
<TextBox x:Name="textbox_NW" Background="LightYellow" BorderThickness="0" AcceptsReturn="True" Height="90" Width="290" Margin="5,5,5,5" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>
</StackPanel>
<StackPanel x:Name="stackpanel_NE" Background="LightYellow" HorizontalAlignment="Right" Margin="0,30,0,0" VerticalAlignment="Top" Height="300" Width="300">
<Grid x:Name="grid_NE">
<TextBox x:Name="textbox_NE" Background="LightYellow" BorderThickness="0" AcceptsReturn="True" Height="290" Width="290" Margin="5,5,5,5" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>
</StackPanel>
<StackPanel x:Name="stackpanel_SW" Background="LightYellow" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Bottom" Height="100" Width="300">
<Grid x:Name="grid_SW">
<TextBox x:Name="textbox_SW" Background="LightYellow" BorderThickness="0" AcceptsReturn="True" Height="90" Width="290" Margin="5,5,5,5" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>
</StackPanel>
<StackPanel x:Name="stackpanel_SE" Background="LightYellow" HorizontalAlignment="Right" Margin="0,0,0,0" VerticalAlignment="Bottom" Height="100" Width="300">
<Grid x:Name="grid_SE">
<TextBox x:Name="textbox_SE" Background="LightYellow" BorderThickness="0" AcceptsReturn="True" Height="90" Width="290" Margin="5,5,5,5" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>
</StackPanel>
</Grid>
</Window>
代码隐藏(VB):
'Reference: http://www.wpf-tutorial.com/common-interface-controls/toolbar-control/
Imports System
Imports System.Windows
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Shapes
Namespace WpfTutorialSamples.Common_interface_controls
Public Class ToolbarSample
Inherits Window
Dim CausedByCode As Boolean
Dim ZoomFactor As Double = 0.1
Dim ZoomMax As Double = 4.95
Dim ZoomMin As Double = 0.05
Dim NumberOfLevels As Integer = 6
Dim NumberOfCellsPerLevel As Integer = 2
Dim LvlBuffer As Double = 0.02
Dim CellBuffer As Double = 0.05
Dim LvlContainerColor As Brush = Brushes.LightGreen
Dim CellContainerColor As Brush = Brushes.LightYellow
Dim LvlDividerColor As Brush = Brushes.Red
Public Sub New()
MyBase.New
InitializeComponent()
End Sub
Private Sub MainWindow_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
'HideWindows(False, New StackPanel() {stackpanel_NW, stackpanel_SE, stackpanel_SW})
HideWindows(True, New StackPanel() {}) 'all
End Sub
Private Sub MainWindow_Loaded(sender As Object, e As EventArgs) Handles Me.Loaded
'add dividers
For a = 1 To (NumberOfLevels - 1)
Dim top As Double = a * (manRect.Height / NumberOfLevels)
Dim LvlDivider As New Canvas
LvlDivider.Background = LvlDividerColor
LvlDivider.Width = manRect.Width
LvlDivider.Height = 0.25
manRect.Children.Add(LvlDivider)
Canvas.SetLeft(LvlDivider, 0)
Canvas.SetTop(LvlDivider, top)
Next
'add levels
For a = 0 To (NumberOfLevels - 1)
Dim LvlWidth As Double = manRect.Width
Dim LvlHeight As Double = manRect.Height / NumberOfLevels
Dim LvlTop As Double = (a * LvlHeight) + (LvlBuffer * LvlHeight)
Dim LvlBottom As Double = LvlHeight - (2 * LvlBuffer * LvlHeight)
Dim LvlContainer As New Canvas
LvlContainer.Background = LvlContainerColor
LvlContainer.Width = LvlWidth
LvlContainer.Height = LvlBottom
manRect.Children.Add(LvlContainer)
Canvas.SetLeft(LvlContainer, 0)
Canvas.SetTop(LvlContainer, LvlTop)
'add cells
For b = 0 To (NumberOfCellsPerLevel - 1)
Dim CellWidth As Double = LvlWidth / NumberOfCellsPerLevel
Dim CellWidthBuffered As Double = CellWidth - (2 * CellBuffer * CellWidth)
Dim CellHeight As Double = LvlBottom
Dim CellTop As Double = (CellBuffer * CellHeight)
Dim CellBottom As Double = CellHeight - (2 * CellBuffer * CellHeight)
Dim CellLeft As Double = (b * CellWidth) + (CellBuffer * CellWidth)
Dim CellContainer As New Canvas
CellContainer.Background = CellContainerColor
CellContainer.Width = CellWidthBuffered
CellContainer.Height = CellBottom
LvlContainer.Children.Add(CellContainer)
Canvas.SetLeft(CellContainer, CellLeft)
Canvas.SetTop(CellContainer, CellTop)
Next
Next
'
ResetMatrix_Click(button_ResetMatrix, Nothing)
End Sub
Private Sub CommonCommandBinding_CanExecute(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
e.CanExecute = True
End Sub
Private Sub HideWindows_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles button_HideWindows.Click
HideWindows(False, New StackPanel() {stackpanel_NE, stackpanel_NW, stackpanel_SE, stackpanel_SW})
End Sub
Private Sub ClearWindows_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles button_ClearWindows.Click
ClearWindows(New StackPanel() {stackpanel_NE, stackpanel_NW, stackpanel_SE, stackpanel_SW})
End Sub
Private Sub HideWindows(ByVal Hide As Boolean, StackPanels() As StackPanel)
If StackPanels.Length = 0 Then
HideWindows(False, New StackPanel() {stackpanel_NE, stackpanel_NW, stackpanel_SE, stackpanel_SW})
Else
For Each s In StackPanels
If StackPanels.Length = 4 Then
s.Visibility = IIf((s.Visibility = Visibility.Hidden), Visibility.Visible, Visibility.Hidden)
Else
s.Visibility = IIf(Hide, Visibility.Visible, Visibility.Hidden)
End If
Next
End If
End Sub
Private Sub ClearWindows(StackPanels() As StackPanel)
For Each s In StackPanels
Dim g As Grid = (From a In s.Children Where a.GetType = GetType(Grid)
Select TryCast(a, Grid)).FirstOrDefault
Dim t As TextBox = (From a In g.Children Where a.GetType = GetType(TextBox)
Select TryCast(a, TextBox)).FirstOrDefault
If s.Visibility = Visibility.Visible Then t.Clear()
Next
End Sub
Private Sub ResetMatrix_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles button_ResetMatrix.Click
'CenterAboutPoint(New Point(150, 150), e) 'top-left
CenterAboutPoint(New Point(Me.Width / 2, (Me.Height / 2) - myToolBar.Height), False, False, False, e) 'middle of window
End Sub
Private Sub label_ZoomIn_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles label_ZoomIn.MouseDown
CenterAboutPoint(New Point(Me.Width / 2, (Me.Height / 2) - myToolBar.Height), True, True, False, e)
End Sub
Private Sub label_ZoomOut_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles label_ZoomOut.MouseDown
CenterAboutPoint(New Point(Me.Width / 2, (Me.Height / 2) - myToolBar.Height), True, False, False, e)
End Sub
Private Sub CenterAboutPoint(ByVal p As Point, ByVal JustZoom As Boolean, ByVal ZoomDir As Boolean, ByVal JustTranslate As Boolean, ByVal e As RoutedEventArgs)
'Dim rectToMove As Rectangle = CType(manRect, Rectangle)
Dim rectToMove As Canvas = CType(manRect, Canvas)
Dim rectsMatrix As Matrix = CType(rectToMove.RenderTransform, MatrixTransform).Matrix
Dim ZoomLevel As Double = rectsMatrix.M11
Dim transform = TransformToVisual(manRect)
'textbox_NE.Text = "zoom: " & ZoomLevel & ", width: " & manRect.Width & ", height: " & manRect.Height
Dim elemPosTopLeft = manRect.TranslatePoint(New Point(0, 0), canvas_Main)
'textbox_NE.AppendText(vbCrLf & "elemPosTopLeft: " & elemPosTopLeft.ToString)
Dim elemPosBottomRight = manRect.TranslatePoint(New Point(manRect.ActualWidth, manRect.ActualHeight), canvas_Main)
'textbox_NE.AppendText(vbCrLf & "elemPosBottomRight: " & elemPosBottomRight.ToString)
Dim elemPosWidth = (elemPosBottomRight.X - elemPosTopLeft.X) '* -ZoomLevel
'textbox_NE.AppendText(vbCrLf & "elemPosWidth: " & elemPosWidth.ToString)
Dim elemPosHeight = (elemPosBottomRight.Y - elemPosTopLeft.Y) '* -ZoomLevel
'textbox_NE.AppendText(vbCrLf & "elemPosHeight: " & elemPosHeight.ToString)
Dim elemPosLeft = elemPosTopLeft.X
'textbox_NE.AppendText(vbCrLf & "elemPosLeft: " & elemPosLeft.ToString)
Dim elemPosTop = elemPosTopLeft.Y
'textbox_NE.AppendText(vbCrLf & "elemPosTop: " & elemPosTop.ToString)
Dim elemPosBottom = elemPosBottomRight.Y
'textbox_NE.AppendText(vbCrLf & "elemPosBottom: " & elemPosBottom.ToString)
Dim elemPosRight = elemPosBottomRight.X
'textbox_NE.AppendText(vbCrLf & "elemPosRight: " & elemPosRight.ToString)
Dim elemPosCenterX = elemPosLeft + (elemPosWidth / 2)
'textbox_NE.AppendText(vbCrLf & "elemPosCenterX: " & elemPosCenterX.ToString)
Dim elemPosCenterY = elemPosTop + (elemPosHeight / 2)
'textbox_NE.AppendText(vbCrLf & "elemPosCenterY: " & elemPosCenterY.ToString)
'offsets from point
Dim elemPosLeftOffset = p.X - elemPosCenterX
'textbox_NE.AppendText(vbCrLf & "elemPosLeftOffset: " & elemPosLeftOffset.ToString)
Dim elemPosTopOffset = p.Y - elemPosCenterY
'textbox_NE.AppendText(vbCrLf & "elemPosTopOffset: " & elemPosTopOffset.ToString)
'scale
If JustTranslate = False Then
If JustZoom = False Then
If ZoomLevel <> 1 Then
rectsMatrix.ScaleAt((1 / ZoomLevel), (1 / ZoomLevel), elemPosCenterX, elemPosCenterY)
End If
Else
Dim NewZoomLevel = IIf(ZoomDir = True, (1 + ZoomFactor), (1 - ZoomFactor))
'textbox_NE.AppendText(vbCrLf & "NewZoomLevel: " & NewZoomLevel.ToString)
If ((ZoomLevel * NewZoomLevel) >= ZoomMin) And ((ZoomLevel * NewZoomLevel) <= ZoomMax) Then
rectsMatrix.ScaleAt(NewZoomLevel, NewZoomLevel, elemPosCenterX, elemPosCenterY)
End If
End If
End If
'translate
If JustZoom = False Then
rectsMatrix.Translate(elemPosLeftOffset, elemPosTopOffset)
End If
'transform
rectToMove.RenderTransform = New MatrixTransform(rectsMatrix)
If Not IsNothing(e) Then e.Handled = True
End Sub
Private Sub Window_ManipulationStarting(ByVal sender As Object, ByVal e As ManipulationStartingEventArgs)
e.ManipulationContainer = Me
e.Handled = True
End Sub
Private Sub Window_ManipulationDelta(ByVal sender As Object, ByVal e As ManipulationDeltaEventArgs)
'Reference: https://www.tutorialspoint.com/wpf/wpf_multi_touch.htm
'Dim rectToMove As Rectangle = CType(e.OriginalSource, Rectangle)
Dim rectToMove As Canvas = CType(e.OriginalSource, Canvas)
Dim rectsMatrix As Matrix = CType(rectToMove.RenderTransform, MatrixTransform).Matrix
Dim ZoomLevel As Double = rectsMatrix.M11
'scale
Dim scale As Double = (e.DeltaManipulation.Scale.X + e.DeltaManipulation.Scale.Y) / 2
rectsMatrix.ScaleAtPrepend(scale, scale, e.ManipulationOrigin.X, e.ManipulationOrigin.Y)
'translate
If CausedByCode = False AndAlso (Math.Abs(e.DeltaManipulation.Translation.X) > 1 Or Math.Abs(e.DeltaManipulation.Translation.Y) > 1) Then
rectsMatrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y)
CausedByCode = True
Else
CausedByCode = False
End If
'apply transformation
If (rectsMatrix.M11 >= ZoomMin) And (rectsMatrix.M11 <= ZoomMax) Then
rectToMove.RenderTransform = New MatrixTransform(rectsMatrix)
End If
Dim containingRect As Rect = New Rect(CType(e.ManipulationContainer, FrameworkElement).RenderSize)
Dim shapeBounds As Rect = rectToMove.RenderTransform.TransformBounds(New Rect(rectToMove.RenderSize))
If (e.IsInertial AndAlso Not containingRect.Contains(shapeBounds)) Then
e.Complete()
End If
e.Handled = True
End Sub
Private Sub Window_InertiaStarting(ByVal sender As Object, ByVal e As ManipulationInertiaStartingEventArgs)
e.TranslationBehavior.DesiredDeceleration = (10 * (96 / (1000 * 1000))) 'inches per second squared
e.ExpansionBehavior.DesiredDeceleration = (0.1 * (96 / (1000 * 1000))) 'inches per second squared
e.RotationBehavior.DesiredDeceleration = (720 / (1000 * 1000)) 'degrees per second squared
e.Handled = True
End Sub
End Class
End Namespace
该程序运行良好,尽管在按比例缩小后长时间拖动矩阵时会出现问题...这可能是由于惯性造成的。
以下允许对指定图像进行基本操作:
XAML
<Image Source="https://placehold.it/200x200" IsManipulationEnabled="True" ManipulationDelta="OnManipulationDelta" />
代码隐藏 (C#)
private void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
var transformGroup = GetTransformGroup(sender);
var translateTransform = transformGroup.Children.OfType<TranslateTransform>().First();
var rotateTransform = transformGroup.Children.OfType<RotateTransform>().First();
var scaleTransform = transformGroup.Children.OfType<ScaleTransform>().First();
translateTransform.X += e.DeltaManipulation.Translation.X;
translateTransform.Y += e.DeltaManipulation.Translation.Y;
rotateTransform.Angle += e.DeltaManipulation.Rotation;
scaleTransform.ScaleY *= e.DeltaManipulation.Scale.Y;
scaleTransform.ScaleX *= e.DeltaManipulation.Scale.X;
}
private TransformGroup GetTransformGroup(object sender)
{
var element = sender as UIElement;
element.RenderTransformOrigin = new Point(.5, .5);
var transformGroup = element.RenderTransform as TransformGroup;
if (transformGroup == null)
{
transformGroup = new TransformGroup();
transformGroup.Children.Add(new TranslateTransform());
transformGroup.Children.Add(new ScaleTransform());
transformGroup.Children.Add(new RotateTransform());
element.RenderTransform = transformGroup;
}
return transformGroup;
}