本文遵循 CC 4.0 BY-SA 版权协议
作者:絮大王
通过这篇文章,我们可以实现:
我们可以禁止窗口拖到屏幕边缘时自动最大化。
AllowsTransparency=“True” 怎么放大缩小窗体
作者:不灬赖
原文地址:https://blog.csdn.net/LJianDong/article/details/99844199
C# WPF 如何禁止窗口拖到屏幕边缘自动最大化
作者:Bird鸟人
原文地址:https://blog.csdn.net/wcc27857285/article/details/78223901
WPF窗口比例如何保持恒定?
作者:a7066163、Hauk
原文地址:https://bbs.csdn.net/topics/390257164
“透明窗口”指的是Window.AllowsTransparency属性为true的窗口。
但是想要Window.AllowsTransparency=“True”
,我们需要让Window.WindowStyle="None"
。
如果Window.WindowStyle="None"
,我们就不能够再通过拖拽窗口的边缘,改变窗口的尺寸了;也不能通过拖拽窗口的上方,来移动窗口的位置了。
那怎么办呢?
我们一步一步来,首先我们需要创建1个透明窗口,作为演示。
第3步:但是,我们可以看到,现在窗口的背景是黑色的,并没有变透明,为什么呢?
因为,我们没有允许窗口可以是透明的。
我们在Window控件中,设置AllowsTransparency="True"
,就可以允许窗口变透明啦!
但是这样运行时会报错,因为如果AllowsTransparency="True"
,那么WindowStyle属性必须为None!
我们在Window控件中,设置WindowStyle=“None”,这样一来,我们就得到了一个完全透明的窗口啦!
第4步:我们往窗口里加入一点东西(不然我们什么都看不见啦)。
这里我们在窗口中加入一个白色的背景,并给背景一个圆角,并且让背景有个好看的阴影。
第5步:我们在窗口中,再放入一个按钮。
透明窗口就创建好啦!
代码 (MainWindow.xaml):
现在,我们没有办法通过拖拽窗口的边缘,调整透明窗口的尺寸。
怎么办呢?
别担心,我们可以使用WindowChrome类。这样我们既能让窗口透明,又能实现缩放窗口!
如果你想了解更多关于WindowChrome类的信息,可以查看微软的官方文档:
https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.shell.windowchrome?view=netframework-4.8
第1步:在Window控件中,创建1个WindowChrome。
第2步:此时,我们可以看到,我们把鼠标移动到窗口边缘拖动后,就已经可以改变窗口的大小啦!
第3步:为了更加完美,我们还可以设置下WindowChrome的CaptionHeight属性
和ResizeBorderThickness属性
。
CaptionHeight属性:设置标题栏的高度。
ResizeBorderThickness属性:设置拖拽调整窗口区域的宽度(如果你的窗口有阴影的话,可以把这个值调整的更大一点)
代码 (MainWindow.xaml):
因为我们设置了Window控件的WindowStyle="None"
,因此我们现在没有办法通过拖拽来移动窗口。
怎么办呢?
这个特别简单!
我们只需要在按下鼠标的时候,调用Window的DragMove()
方法,就可以啦!
第1步:我们创建1个Border,命名为TopBorder。
我们希望当我们按住这个Border的时候,就可以拖动窗口。
第2步:注册TopBorder的MouseLeftButtonDown事件。
(当我们在TopBorder控件身上按下鼠标左键时,就会触发这个MouseLeftButtonDown事件)
第3步:我们在MainWindow.cs中,这样写。
Window类的DragMove()方法,用于当鼠标左键按下后,移动鼠标可以拖动窗口。
代码 (MainWindow.xaml):
代码 (MainWindow.cs):
using System.Windows;
using System.Windows.Input;
namespace ResizeTransparentWindow
{
///
/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
///
/// 当用鼠标左键点击TopBorder控件时,触发此方法
/// (This method is triggered when the TopBorder control is clicked with the left mouse button)
///
private void TopBorder_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
/* 当点击拖拽区域的时候,让窗口跟着移动
(When clicking the drag area, make the window follow) */
DragMove();
}
}
}
现在我们的窗口拖拽到屏幕上方时,会自动最大化。
我们可以不最大化窗口吗?
当然可以!
Bird鸟人大佬用了一种非常巧妙的方法实现了这个功能。
原文地址:https://blog.csdn.net/wcc27857285/article/details/78223901
思路:
因为拖到屏幕边缘自动最大化,有个必要条件是鼠标按下去,然后拖。
我们可以利用这个间隙将ResizeMode设置为NoResize,然后鼠标放开之后再把ResizeMode设置回CanResize,就可以啦!
代码 (MainWindow.cs):
using System.Windows;
using System.Windows.Input;
namespace ResizeTransparentWindow
{
///
/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
///
/// 当用鼠标左键点击TopBorder控件时,触发此方法
/// (This method is triggered when the TopBorder control is clicked with the left mouse button)
///
private void TopBorder_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
/* 如何在Window.ResizeMode属性为CanResize的时候,阻止窗口拖动到屏幕边缘自动最大化。
(When the Window.ResizeMode property is CanResize,
when the window is dragged to the edge of the screen,
it prevents the window from automatically maximizing.)*/
if (e.ChangedButton == MouseButton.Left)
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
var windowMode = this.ResizeMode;
if (this.ResizeMode != ResizeMode.NoResize)
{
this.ResizeMode = ResizeMode.NoResize;
}
this.UpdateLayout();
/* 当点击拖拽区域的时候,让窗口跟着移动
(When clicking the drag area, make the window follow) */
DragMove();
if (this.ResizeMode != windowMode)
{
this.ResizeMode = windowMode;
}
this.UpdateLayout();
}
}
}
}
}
那我们可以在拖动鼠标调整窗口大小时,等比例的放大/缩小窗口吗?
比如,可以一直让窗口的比例为4比3吗?
当然可以哒!
这里参考了a7066163、Hauk的方法。
使用这种方法,不仅可以按照比例缩放窗口,还可以避免闪烁的问题!
原文地址:https://bbs.csdn.net/topics/390257164
思路:
【首先Hauk给出了自己的思路】: 拖拉时显示窗口内容 不勾选时:一次拖动只触发一次SizeChanged事件 拖拉时显示窗口内容 勾选时:一次拖动只触发 N 次SizeChanged事件(n=newsize-oldsize) 触发太频繁所以界面更新有点不对劲。 可以使用timer来延迟更新,等用户拖好了来。
【然后a7066163在Hauk想法的基础上做了更改】: 虽然在在鼠标释放的慢的情况下,窗口会退回原来的大小,所以我只在处理鼠标释放的事件就行了。 不过貌似自带边框的鼠标事件不属于窗口事件,最后我直接捕获WM_EXITSIZEMOVE消息,重载了窗口消息处理函数。 通过定时器和WM_EXITSIZEMOVE消息处理的双重保证下,大致能实现窗口比例实时恒定的效果。
代码 (MainWindow.cs):
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
namespace ResizeTransparentWindow
{
///
/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
//最后的宽度(Last Width)
private int LastWidth;
//最后的高度(Last Height)
private int LastHeight;
//这个属性是指 窗口的宽度和高度的比例(宽度/高度)(4:3)
//This property refers to the aspect ratio (width / height) of the window (4: 3)
private float AspectRatio = 4.0f / 3.0f;
///
/// 捕获窗口拖拉消息
/// (Capturing window drag messages)
///
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;
///
/// 重载窗口消息处理函数
/// (Overload window message processing function)
///
private IntPtr WinProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, ref Boolean handled)
{
IntPtr result = IntPtr.Zero;
switch (msg)
{
//处理窗口消息 (Handle window messages)
case WM_EXITSIZEMOVE:
{
//上下拖拉窗口 (Drag window vertically)
if (this.Height != LastHeight)
{
this.Width = this.Height * AspectRatio;
}
// 左右拖拉窗口 (Drag window horizontally)
else if (this.Width != LastWidth)
{
this.Height = this.Width / AspectRatio;
}
LastWidth = (int)this.Width;
LastHeight = (int)this.Height;
break;
}
}
return result;
}
}
}
那我们可以在更改窗口大小时,等比例的更改窗口中控件的大小吗?
当然可以啦!
这里我们用Viewbox控件,就可以实现这个功能啦!
第2步:然后,设置Viewbox的Stretch属性为UniformToFill
第3步:现在,我们缩放窗口时,窗口中的内容也会自动等比例进行缩放啦!
代码 (MainWindow.xaml):
MainWindow.xaml:
MainWindow.cs:
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
namespace ResizeTransparentWindow
{
///
/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
#region [拖动窗口 (Drag Move Window)]
///
/// 当用鼠标左键点击TopBorder控件时,触发此方法
/// (This method is triggered when the TopBorder control is clicked with the left mouse button)
///
private void TopBorder_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
/* 当点击拖拽区域的时候,让窗口跟着移动
(When clicking the drag area, make the window follow) */
DragMove();
}
#endregion
#region [等比例调整窗口尺寸(Proportional Resize window)]
//最后的宽度(Last Width)
private int LastWidth;
//最后的高度(Last Height)
private int LastHeight;
//这个属性是指 窗口的宽度和高度的比例(宽度/高度)(4:3)
//This property refers to the aspect ratio (width / height) of the window (4: 3)
private float AspectRatio = 4.0f / 3.0f;
///
/// 捕获窗口拖拉消息
/// (Capturing window drag messages)
///
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;
///
/// 重载窗口消息处理函数
/// (Overload window message processing function)
///
private IntPtr WinProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, ref Boolean handled)
{
IntPtr result = IntPtr.Zero;
switch (msg)
{
//处理窗口消息 (Handle window messages)
case WM_EXITSIZEMOVE:
{
//上下拖拉窗口 (Drag window vertically)
if (this.Height != LastHeight)
{
this.Width = this.Height * AspectRatio;
}
// 左右拖拉窗口 (Drag window horizontally)
else if (this.Width != LastWidth)
{
this.Height = this.Width / AspectRatio;
}
LastWidth = (int) this.Width;
LastHeight = (int) this.Height;
break;
}
}
return result;
}
#endregion
}
}