WPF中实现以鼠标为中心的缩放和移动图片或控件对象

前言:因项目中需要用到对图片对象Image控件的放大缩小及移动,且以鼠标为中心点,查了资料,理解后将实现代码记录如下,方便下次使用。

在WPF中要实现控件的缩放和移动,有现成的工具类可以使用,主要是TransformGroup类,ScaleTransform类和TranslateTransform 类。

TransformGroup类是一个组合,下面有一个Children集合,将ScaleTransform和TranslateTransform 丢到集合中,然后将TransformGroup丢给需要缩放平移的控件对象。控件对象如何接收?每个控件都有一个属性叫RenderTransform,专门用来实现控件自身的缩放平移等变换效果。


border.RenderTransform = TransformGroup;//给Border对象设置一个变换组实例

有一个关键点要理解,如果要移动border对象,那么这个border对象是相对于谁而移动?答案是相对于它的父容器。通常我们用Canvas来做父容器。然后在这个Canvas的各种鼠标操作(按下、移动、滑动滚轮、弹起)事件中去实现缩放平移功能。

下面是部分代码说明:

首先是ViewModel部分

private double mouseX = 0;
public double MouseX
{
	get{return mouseX;}
	set{mouseX=value;RaisePropertyChanged();}
}

private double mouseY = 0;
public double MouseY
{
	get{return mouseY;}
	set{mouseY=value;RaisePropertyChanged();}
}

private double delta= 0;
public double Delta
{
	get{return delta;}
	set{delta=value;RaisePropertyChanged();}
}

然后是WPF前端代码部分

<Grid>
	<Grid.RowDefinitions>
		<RowDefinition Height="auto"/>
		<RowDefinition/>
	</Grid.RowDefinitions>
	<StackPanel Grid.Row="0" Orientation="Horizontal">
		<TextBlock Text="{Binding MouseX}" Margin="5"/>
		<TextBlock Text="{Binding MouseY}" Margin="5"/>
		<TextBlock Text="{Binding Delta}" Margin="5"/>
	</StackPanel>
	<Canvas Grid.Row="1" x:Name="canvas" Background="Black" ClipToBounds="True"
			MouseRightButtonDown="Canvas_MouseRightButtonDown"
			MouseRightButtonUp="Canvas_MouseRightButtonUp"
			MouseLeftButtonDown="Canvas_MouseLeftButtonDown"
			MouseLeftButtonUp="Canvas_MouseLeftButtonUp"
			MouseMove="Canvas_MouseMove"
			MouseWheel="Canvas_MouseWheel">
		<Border x:Name="border" Width="200" Height="100" Background="LightCoral">
			<Grid>
				<Border Width="100" Height="100" CornerRadius="100" Background="LightBlue"/>
				<TextBlock Text="Text"/>
			</Grid>
		</Border>
	</Canvas>
</Grid>

最后是cs后台代码部分


public partial class MainWindow : Window
{
	private MainViewModel vm;
	private bool isMouseDown=false;
	private Point mousePosition=new Point();
	private TranslateTransform translateTransform=new TranslateTransform();
	private ScaleTransform scaleTransform=new ScaleTransform();
	private TransformGroup transformGroup=new TransformGroup();
	public MainWindow()
	{
		InitializeComponent();
		vm=DataContext as MainViewModel;
		transformGroup.Children.Add(scaleTransform);//定义缩放
		transformGroup.Children.Add(translateTransform);//定义移动
		border.RenderTransform=transformGroup;//定义变换组
		canvas.Loaded+=(s,e)=>
		{
			//初始化border控件大小适配canvas父容器
			var scale = Math.Min(canvas.ActualWidth/border.Width,canvas.ActualHeight/border.Height);
			scaleTransform.ScaleX=scale;
			scaleTransform.ScaleY=scale;
		};
	}
	private void Canvas_MouseRightButtonDown(object sender,MouseButtonEventArgs e)
	{
		isMouseDown=true;
		mousePosition=e.GetPosition(canvas);
	}
	private void Canvas_MouseRightButtonUp(object sender,MouseButtonEventArgs e)
	{
		isMouseDown=false;
	}
	private void Canvas_MouseLeftButtonDown(object sender,MouseButtonEventArgs e)
	{
		isMouseDown=true;
		mousePosition=e.GetPosition(canvas);
	}
	private void Canvas_MouseLeftButtonUp(object sender,MouseButtonEventArgs e)
	{
		isMouseDown=false;
	}
	private void Canvas_MouseMove(object sender,MouseEventArgs e)
	{
		var position=e.GetPosition(canvas);
		vm.MouseX=position.X;
		vm.MouseY=position.Y;
		if(isMouseDown)
		{
			TranslateTransform translateTransform = transformGroup.Children[1] as TranslateTransform ;
			translateTransform.X+=position.X-mousePosition.X;
			translateTransform.Y+=position.Y-mousePosition.Y;
			mousePosition=position;
		}
	}
	private void Canvas_MouseWheel(object sender,MouseWheelEventArgs e)
	{
		vm.Delta=e.Delta;
		double scale=e.Delta*0.001;
		var position=e.GetPosition(canvas);
		vm.MouseX=position.X;
		vm.MouseY=position.Y;
		Point inversePoint=transformGroup.Inverse.Transform(position);
		ScaleTransform scaleTransform = transformGroup.Children[0] as ScaleTransform;
		TranslateTransform translateTransform = transformGroup.Children[1] as TranslateTransform ;
		if(scaleTransform.ScaleX+scale<1)return;
		scaleTransform.ScaleX+=scale;
		scaleTransform.ScaleY+=scale;
		translateTransform.X=-1*((inversePoint.X*scaleTransform.ScaleX)-position.X);
		translateTransform.Y=-1*((inversePoint.Y*scaleTransform.ScaleY)-position.Y);
	}

}


在这里插入图片描述

以下是一个基于栈的出栈序列检查的C语言代码: ```c #include <stdio.h> #include <stdlib.h> #define MAX_STACK_SIZE 100 int stack[MAX_STACK_SIZE]; int top = -1; void push(int val) { if (top == MAX_STACK_SIZE - 1) { printf("Stack overflow\n"); exit(1); } stack[++top] = val; } int pop() { if (top == -1) { printf("Stack underflow\n"); exit(1); } return stack[top--]; } int main() { int n, i, j; int push_seq[MAX_STACK_SIZE], pop_seq[MAX_STACK_SIZE]; printf("Enter the size of the sequence: "); scanf("%d", &n); printf("Enter the push sequence: "); for (i = 0; i < n; i++) { scanf("%d", &push_seq[i]); } printf("Enter the pop sequence: "); for (i = 0; i < n; i++) { scanf("%d", &pop_seq[i]); } i = 0; j = 0; while (i < n && j < n) { if (push_seq[i] == pop_seq[j]) { i++; j++; } else if (top != -1 && stack[top] == pop_seq[j]) { pop(); j++; } else { push(push_seq[i++]); } } while (top != -1 && j < n) { if (stack[top] == pop_seq[j]) { pop(); j++; } else { break; } } if (top == -1 && j == n) { printf("The pop sequence is valid.\n"); } else { printf("The pop sequence is not valid.\n"); } return 0; } ``` 该程序要求用户输入一个序列的大小,一个压栈序列和一个出栈序列。然后,程序使用一个基于栈的算法来检查出栈序列的合法性。如果出栈序列是合法的,程序将输出“ The pop sequence is valid.”,否则输出“The pop sequence is not valid.”。 该算法的基本思想是模拟压栈和出栈过程。我们从压栈序列的开头开始遍历,遇到一个和出栈序列的当前元素相等的元素时,我们将它出栈。否则,我们将该元素压入栈。如果栈顶元素和出栈序列的当前元素相等,则将栈顶元素出栈。 在遍历完压栈序列后,我们检查栈剩余的元素是否可以与出栈序列的元素匹配。如果可以,则弹出栈顶元素并移动到下一个出栈元素。如果不能匹配,则出栈序列无效。 此算法的时间复杂度为O(n),其n为序列的大小。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值