效果:
下面是右上方文本框的源代码,其他效果请前往github示例代码查看
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; } ////// 拖拽移动 //////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; } ////// 缩放大小 //////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 }
示例代码
参考资料
How to change size of WPF controls at runtime