• WPF 移动控件、拖动边框修改控件大小


    效果:

    下面是右上方文本框的源代码,其他效果请前往github示例代码查看

    <Canvas x:Name="canvas" MouseMove="Canvas_MouseMove">
    	<!--文本框-->
    	<Border Name="border2" Canvas.Left="500" Canvas.Top="35"
    			BorderBrush="DarkKhaki" BorderThickness="1"  CornerRadius="5" Padding="5"
    			Height="30" Width="200" MinHeight="10" MinWidth="10"
    			MouseLeftButtonDown="border_MouseLeftButtonDown"
    			MouseLeave="border_MouseLeave"
    			MouseEnter="border_MouseEnter">
    		<Border.BitmapEffect>
    			<DropShadowBitmapEffect Color="DarkGray"/>
    		</Border.BitmapEffect>
    		<Border.RenderTransform>
    			<TransformGroup>
    				<ScaleTransform/>
    				<TranslateTransform/>
    			</TransformGroup>
    		</Border.RenderTransform>
    		<!--需要Label/textblock的文字大小随resize改变,则使用Viewbox,否则,去掉Viewbox-->
    		<!--https://stackoverflow.com/questions/1464185/how-to-set-textblock-or-label-with-resizable-font-size-in-wpf-->
    		<Viewbox Stretch="Uniform">
    			<TextBlock Name="myTextBlock" Text="move and rezise TextBlock"></TextBlock>
    		</Viewbox>
    	</Border>
    </Canvas>
    
    private Element current = new Element();
    
    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
    {
    	base.OnMouseLeftButtonDown(e);
    	this.current.X = Mouse.GetPosition(this.canvas).X;
    	this.current.Y = Mouse.GetPosition(this.canvas).Y;
    
    	if (this.current.InputElement != null)
    		this.current.InputElement.CaptureMouse();
    
    	if (!this.current.IsStretching)
    		this.current.IsDragging = true;
    }
    
    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
    {
    	base.OnMouseLeftButtonUp(e);
    
    	if (this.current.InputElement != null)
    		this.current.InputElement.ReleaseMouseCapture();
    
    	this.Cursor = Cursors.Arrow;
    }
    
    private void Canvas_MouseMove(object sender, MouseEventArgs e)
    {
    	if (e.LeftButton == MouseButtonState.Pressed &&
    		 current.InputElement != null)
    	{
    		//increment z-Order and pass it to the current element, 
    		//so that it stays on top of all other elements
    		//递增z-Order并将其传递给当前元素,以使其停留在所有其他元素的顶部
    		((Border)this.current.InputElement).SetValue(Canvas.ZIndexProperty, this.current.ZIndex++);
    
    		//判断操作类型为拖拽移动
    		if (this.current.IsDragging)
    			Drag(sender);
    
    		//缩放大小
    		if (this.current.IsStretching)
    			Stretch(sender);
    	}
    }
    
    private void border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
    	//capture the last highest z index before pointing to new current element
    	//在指向新的当前元素之前捕获最后的最高z索引
    	int newZIndex = (int)((Border)sender).GetValue(Canvas.ZIndexProperty);
    	this.current.ZIndex = newZIndex > this.current.ZIndex ? newZIndex : this.current.ZIndex;
    
    	//capture the new current element
    	//捕获新的当前元素
    	this.current.InputElement = (IInputElement)sender;
    }
    
    private void border_MouseLeave(object sender, MouseEventArgs e)
    {
    	if (e.LeftButton == MouseButtonState.Pressed)
    		return;
    
    	// get coordinates
    	//获得坐标
    	//计算Border
    	Border border = (Border)sender;
    	var rightLimit = border.ActualWidth - border.Padding.Right;
    	var bottomLimit = border.ActualHeight - border.Padding.Bottom;
    	//获得鼠标点击(与特定元素的相对位置)
    	var x = Mouse.GetPosition((IInputElement)sender).X;
    	var y = Mouse.GetPosition((IInputElement)sender).Y;
    
    	// figure out stretching directions - only to Right, Bottom 
    	//找出缩放的方向-仅向右方、底部
    	bool stretchRight = (x >= rightLimit && x < border.ActualWidth) ? true : false;
    	bool stretchBottom = (y >= bottomLimit && y < border.ActualHeight) ? true : false;
    
    	// update current element
    	//更新当前元素
    	this.current.InputElement = (IInputElement)sender;
    	this.current.X = x;
    	this.current.Y = y;
    	//默认为“缩放”操作
    	this.current.IsStretching = true;
    
    	//set cursor to show stretch direction 
    	//设置光标显示
    	//右&底部,光标显示右下箭头
    	if (stretchRight && stretchBottom)
    	{
    		this.Cursor = Cursors.SizeNWSE;
    		return;
    	}
    	//右
    	else if (stretchRight && !stretchBottom)
    	{
    		this.Cursor = Cursors.SizeWE;
    		return;
    	}
    	//底部
    	else if (stretchBottom && !stretchRight)
    	{
    		this.Cursor = Cursors.SizeNS;
    		return;
    	}
    	//非缩放操作,显示箭头光标,设置IsStretching=false
    	else //no stretch
    	{
    		this.Cursor = Cursors.Arrow;
    		this.current.IsStretching = false;
    	}
    
    }
    
    private void border_MouseEnter(object sender, MouseEventArgs e)
    {
    	Border border = (Border)sender;
    
    	var rightLimit = border.ActualWidth - border.Padding.Right;
    	var bottomLimit = border.ActualHeight - border.Padding.Bottom;
    
    	var x = Mouse.GetPosition((IInputElement)sender).X;
    	var y = Mouse.GetPosition((IInputElement)sender).Y;
    
    	if (x < rightLimit && y < bottomLimit)
    		this.Cursor = Cursors.Arrow;
    }
    
    /// <summary>
    /// 拖拽移动
    /// </summary>
    /// <param name="sender"></param>
    private void Drag(object sender)
    {
    	this.Cursor = Cursors.Hand;
    
    	// Retrieve the current position of the mouse.
    	var newX = Mouse.GetPosition((IInputElement)sender).X;
    	var newY = Mouse.GetPosition((IInputElement)sender).Y;
    
    	// Reset the location of the object (add to sender's renderTransform newPosition minus currentElement's position
    	var transformGroup = ((UIElement)this.current.InputElement).RenderTransform as TransformGroup;
    	if (transformGroup == null)
    		return;
    
    	var translateTransforms = from transform in transformGroup.Children
    							  where transform.GetType().Name == "TranslateTransform"
    							  select transform;
    
    	foreach (TranslateTransform tt in translateTransforms)
    	{
    		tt.X += newX - current.X;
    		tt.Y += newY - current.Y;
    	}
    
    	// Update the beginning position of the mouse
    	current.X = newX;
    	current.Y = newY;
    }
    
    /// <summary>
    /// 缩放大小
    /// </summary>
    /// <param name="sender"></param>
    private void Stretch(object sender)
    {
    
    	// Retrieve the current position of the mouse.
    	var mousePosX = Mouse.GetPosition((IInputElement)sender).X;
    	var mousePosY = Mouse.GetPosition((IInputElement)sender).Y;
    
    
    	//get coordinates
    	Border border = (Border)this.current.InputElement;
    	var xDiff = mousePosX - this.current.X;
    	var yDiff = mousePosY - this.current.Y;
    	var width = ((Border)this.current.InputElement).Width;
    	var heigth = ((Border)this.current.InputElement).Height;
    
    
    	//make sure not to resize to negative width or heigth
    	xDiff = (border.Width + xDiff) > border.MinWidth ? xDiff : border.MinWidth;
    	yDiff = (border.Height + yDiff) > border.MinHeight ? yDiff : border.MinHeight;
    
    
    	// stretchRight && stretchBottom ?
    	if (this.Cursor == Cursors.SizeNWSE)
    	{
    		((Border)this.current.InputElement).Width += xDiff;
    		((Border)this.current.InputElement).Height += yDiff;
    	}
    	// stretchRight ? 
    	else if (this.Cursor == Cursors.SizeWE)
    		((Border)this.current.InputElement).Width += xDiff;
    
    	// stretchBottom ?
    	else if (this.Cursor == Cursors.SizeNS)
    		((Border)this.current.InputElement).Height += yDiff;
    
    	//no stretch
    	else
    	{
    		this.Cursor = Cursors.Arrow;
    		this.current.IsStretching = false;
    	}
    
    	// update current coordinates with the latest postion of the mouse
    	this.current.X = mousePosX;
    	this.current.Y = mousePosY;
    }
    

    Element.cs

    public class Element
    {
    	#region Fields
    	private bool isDragging = false;
    	private bool isStretching = false;
    	private bool stretchLeft = false;
    	private bool stretchRight = false;
    	private IInputElement inputElement = null;
    	private double x, y = 0;
    	private int zIndex = 0;
    	#endregion
    
    	#region Constructor
    	public Element() { }
    	#endregion
    
    	#region Properties
    	public IInputElement InputElement
    	{
    		get { return this.inputElement; }
    		set
    		{
    			this.inputElement = value;
    			this.isDragging = false;
    			this.isStretching = false;
    		}
    	}
    	public double X
    	{
    		get { return this.x; }
    		set { this.x = value; }
    	}
    	public double Y
    	{
    		get { return this.y; }
    		set { this.y = value; }
    	}
    	public int ZIndex
    	{
    		get { return this.zIndex; }
    		set { this.zIndex = value; }
    	}
    	public bool IsDragging
    	{
    		get { return this.isDragging; }
    		set
    		{
    			this.isDragging = value;
    			this.isStretching = !this.isDragging;
    		}
    	}
    	public bool IsStretching
    	{
    		get { return this.isStretching; }
    		set
    		{
    			this.isStretching = value;
    			this.IsDragging = !this.isStretching;
    		}
    	}
    	public bool StretchLeft
    	{
    		get { return this.stretchLeft; }
    		set { this.stretchLeft = value; this.stretchRight = !this.stretchLeft; }
    	}
    	public bool StretchRight
    	{
    		get { return this.stretchRight; }
    		set { this.stretchRight = value; this.stretchLeft = !this.stretchRight; }
    	}
    	#endregion
    }
    

    示例代码

    MoveAndResizeControl

    参考资料

    How to change size of WPF controls at runtime

  • 相关阅读:
    解决 react-native 嵌套路由 warning
    在 function component 中设置 navigationOptions
    《客户端存储技术》阅读笔记
    表单实现原理(Vue ElementUI)
    MVVM 响应式原理(Vue)
    react 实现 loading 动效圈,支持配置转一圈的 duration
    CSS 数字设置等宽
    JSONP(Json with padding)
    javascript this对象
    css盒子模型
  • 原文地址:https://www.cnblogs.com/Lulus/p/12715348.html
Copyright © 2020-2023  润新知