WPF Window Resizing(CodeProject原文)
原文中的代码演示了如何动态实时改变WPF窗口的方法,不过在测试中发现一个小问题,即当鼠标按下后一直向一个方向缩小窗口的时候,当鼠标超过了另一条边的时候(在左边框按下,一直向右拖动鼠标,直到鼠标超过右边框时,异常就出现了,其他四个方向同理)会引发异常.
以下代码在原来的基础上,主要修改了updateSize函数,解决了问题.
2013-04-02:新问题,找时间修改
1,当拖动左边框的时候,右边框应固定不动,但现在右边框则在不停的闪动,虽然最后的位置是正确的。同样,上下拖动也存在相同的问题。是因为时时改变了当前窗口的左上角坐标点位置,重绘引起的闪动。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.Threading;
using System.Windows.Media.Effects;
namespace DNBSoft.WPF
{
public class WindowResizer
{
private Window target = null;
private bool resizeRight = false;
private bool resizeLeft = false;
private bool resizeUp = false;
private bool resizeDown = false;
private Dictionary<UIElement, short> leftElements = new Dictionary<UIElement, short>();
private Dictionary<UIElement, short> rightElements = new Dictionary<UIElement, short>();
private Dictionary<UIElement, short> upElements = new Dictionary<UIElement, short>();
private Dictionary<UIElement, short> downElements = new Dictionary<UIElement, short>();
private PointAPI startMousePoint = new PointAPI(); //鼠标左键点下时的坐标点
private Size startWindowSize = new Size(); //鼠标左键点下时,窗口的大小
private Point startWindowLeftUpPoint = new Point(); //鼠标左键点下时,窗口左上角坐标点位置
public int minWidth = 10;
public int minHeight = 10;
private delegate void RefreshDelegate();
public WindowResizer(Window target)
{
this.target = target;
if (target == null)
{
throw new Exception("Invalid Window handle");
}
}
#region add resize components
private void connectMouseHandlers(UIElement element)
{
element.MouseLeftButtonDown += new MouseButtonEventHandler(element_MouseLeftButtonDown);
element.MouseEnter += new MouseEventHandler(element_MouseEnter);
element.MouseLeave += new MouseEventHandler(setArrowCursor);
}
public void addResizerRight(UIElement element)
{
connectMouseHandlers(element);
rightElements.Add(element, 0);
}
public void addResizerLeft(UIElement element)
{
connectMouseHandlers(element);
leftElements.Add(element, 0);
}
public void addResizerUp(UIElement element)
{
connectMouseHandlers(element);
upElements.Add(element, 0);
}
public void addResizerDown(UIElement element)
{
connectMouseHandlers(element);
downElements.Add(element, 0);
}
public void addResizerRightDown(UIElement element)
{
connectMouseHandlers(element);
rightElements.Add(element, 0);
downElements.Add(element, 0);
}
public void addResizerLeftDown(UIElement element)
{
connectMouseHandlers(element);
leftElements.Add(element, 0);
downElements.Add(element, 0);
}
public void addResizerRightUp(UIElement element)
{
connectMouseHandlers(element);
rightElements.Add(element, 0);
upElements.Add(element, 0);
}
public void addResizerLeftUp(UIElement element)
{
connectMouseHandlers(element);
leftElements.Add(element, 0);
upElements.Add(element, 0);
}
#endregion
#region resize handlers
private void element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
GetCursorPos(out startMousePoint);
startWindowSize = new Size(target.Width, target.Height);
startWindowLeftUpPoint = new Point(target.Left, target.Top);
#region updateResizeDirection
UIElement sourceSender = (UIElement)sender;
if (leftElements.ContainsKey(sourceSender))
{
resizeLeft = true;
}
if (rightElements.ContainsKey(sourceSender))
{
resizeRight = true;
}
if (upElements.ContainsKey(sourceSender))
{
resizeUp = true;
}
if (downElements.ContainsKey(sourceSender))
{
resizeDown = true;
}
#endregion
Thread t = new Thread(new ThreadStart(updateSizeLoop));
t.Name = "Mouse Position Poll Thread";
t.Start();
}
private void updateSizeLoop()
{
try
{
while (resizeDown || resizeLeft || resizeRight || resizeUp)
{
target.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, new RefreshDelegate(updateSize));
target.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, new RefreshDelegate(updateMouseDown));
Thread.Sleep(20);
}
target.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, new RefreshDelegate(setArrowCursor));
}
catch (Exception)
{
}
}
#region updates
private void updateSize()
{
PointAPI currentMousePoint = new PointAPI();
GetCursorPos(out currentMousePoint);
try
{
if (resizeRight)
{
//如果当鼠标左键点下时,窗口的宽度已经达到最小值,
if (target.Width == minWidth)
{
//鼠标向右移动,表示当前是将窗口变大,此时窗口只能变大,因为已经达到最小宽度了
if ((startMousePoint.X - currentMousePoint.X) < 0)
{
target.Width = this.startWindowSize.Width - (startMousePoint.X - currentMousePoint.X);
}
}
else
{
//此时,窗口可大可小
if ((th