WPF实现窗口比例恒定不变小结(1)
因工作需要调整一个软件的UI,就是拖放窗口时窗口的比例保持不变。比如16:9就一直是16:9。起初我尝试的是在窗口的SizeChanged事件中调整窗口大小,代码如下:
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
double preWidth = e.PreviousSize.Width;
double preHeight = e.PreviousSize.Height;
double curWidth = e.NewSize.Width;
double curHeight = e.NewSize.Height;
// 上下拖拉窗口
if (this.Height != preHeight)
{
this.Width = curHeight * 1.713;
}
// 左右拖拉窗口
else
{
this.Height = curWidth / 1.713;
}
}
让我困惑的是,这段代码在勾选系统设置“拖拉时显示窗口内容”时,拖拉表现不正常。鼠标在拖住不放的时候,窗口会变大,但是一旦释放鼠标左键,窗口又变回了原来的大小。通过打断点调试又是正常的。如果不勾选 “拖拉时显示窗口内容”,窗口拖拉正常,没有问题。这就让我不得不怀疑是不是有bug了。
于是我放弃了在SizeChanged中修改窗口大小,转而通过截获WM_EXITSIZEMOVE消息,并对其进行处理。代码如下:
private int LastWidth;
private int LastHeight;
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource source = HwndSource.FromVisual(this) as HwndSource;
if (source != null)
{
source.AddHook(new HwndSourceHook(WinProc));
}
}
public const Int32 WM_EXITSIZEMOVE = 0x0232;
private IntPtr WinProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, ref Boolean handled)
{
IntPtr result = IntPtr.Zero;
switch (msg)
{
case WM_EXITSIZEMOVE:
{
if (this.Height != LastHeight)
{
this.Width = this.Height * 1.713;
}
else
{
this.Height = this.Width / 1.713;
}
LastWidth = (int)this.Width;
LastHeight = (int)this.Height;
break;
}
}
return result;
}
这样写的效果就是要在释放鼠标的时候,才能响应WM_EXITSIZEMOVE消息,从而调整窗口大小。不能像SizeChanged时间一样实时修改窗口大小。不过最终结果一样,都能达到窗口比例恒定。