C# 具有阴影VS2012样式的WPF无边框窗口
我正在尝试创建一个类似Visual Studio 2012的应用程序。我曾经删除过窗口边框,并在xaml中更改了边框颜色 我不知道怎么画窗户的阴影,这里你可以看到我说的截图: 正如你所看到的,有一个阴影,它的颜色也是边框的颜色 您知道如何使用WPF实现它吗?这被称为“Metro风格”(Windows 8风格)。我认为这篇代码项目文章对您来说很有趣,它将帮助您 您可以尝试,它是根据MIT许可证授权的,包括ApplicationBar和ToastNotification类,或者也可以从CodePlex获得 这是一个关于极乐世界的很棒的教程,我认为它对你有帮助 对于阴影,只需从XAML中的C# 具有阴影VS2012样式的WPF无边框窗口,c#,wpf,user-interface,visual-studio-2012,C#,Wpf,User Interface,Visual Studio 2012,我正在尝试创建一个类似Visual Studio 2012的应用程序。我曾经删除过窗口边框,并在xaml中更改了边框颜色 我不知道怎么画窗户的阴影,这里你可以看到我说的截图: 正如你所看到的,有一个阴影,它的颜色也是边框的颜色 您知道如何使用WPF实现它吗?这被称为“Metro风格”(Windows 8风格)。我认为这篇代码项目文章对您来说很有趣,它将帮助您 您可以尝试,它是根据MIT许可证授权的,包括ApplicationBar和ToastNotification类,或者也可以从CodePl
网格
将位图效果
添加到边框
:
<Grid>
<Border BorderBrush="#FF006900" BorderThickness="3" Height="157" HorizontalAlignment="Left" Margin="12,12,0,0" Name="border1" VerticalAlignment="Top" Width="479" Background="#FFCEFFE1" CornerRadius="20, 20, 20, 20">
<Border.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Direction="320" ShadowDepth="10" Opacity="0.5" Softness="5" />
</Border.BitmapEffect>
<TextBlock Height="179" Name="textBlock1" Text="Hello, this is a beautiful DropShadow WPF Window Example." FontSize="40" TextWrapping="Wrap" TextAlignment="Center" Foreground="#FF245829" />
</Border>
</Grid>
更新(10月17日)
四年过去了,我有兴趣再次解决这个问题,因此我一次又一次地和MahApps.Metro混在一起。My ModernChrome库提供了一个类似Visual Studio 2017的自定义窗口:
由于您很可能只对发光边框部分感兴趣,您应该使用MahApps.Metro本身,或者查看我如何创建一个类GlowWindowBehavior
,该类将发光边框附加到我的自定义ModernWindow
类。它严重依赖于MahApps.Metro的一些内部结构以及两个依赖属性GlowBrush
和NonActiveGlowBrush
如果您只想在自定义应用程序中包含发光边框,只需引用MahApps.Metro并复制myGlowWindowBehavior.cs
,然后创建自定义窗口类并相应地调整引用。这最多是15分钟
这个问题和我的答案经常被访问,因此我希望您会发现我最新的正确解决方案很有用:)
原职(二月十三日) 我一直在开发这样一个库来复制Visual Studio 2012用户界面。定制chrome并不是那么难,但是你需要注意的是这个发光的边框,它很难实现。您可以说,将窗口的背景色设置为透明,并将主网格的填充设置为30px左右。网格周围的边框可以是彩色的,并与彩色阴影效果相关联,但这种方法会强制您将
allowTransparency
设置为true,这会大大降低应用程序的视觉性能,这是您绝对不想做的事情
我目前的方法是创建这样一个窗口,它在边框上有一个彩色阴影效果,是透明的,但没有任何内容。每当我的主窗口的位置改变时,我只更新保存边框的窗口的位置。因此,最后我处理两个窗口,其中包含假边界将是主窗口的一部分的消息。这是必要的,因为DWM库没有提供一种为windows提供彩色阴影效果的方法,我认为VisualStudio2012也像我尝试的那样提供了类似的效果
为了扩展这篇文章,提供更多信息:Office 2013的做法有所不同。窗口周围的边框只有1px厚且颜色鲜艳,但阴影是由DWM使用如下代码绘制的。如果你不需要蓝色/紫色/绿色的边框,也不需要普通的边框,这就是我选择的方法!只是不要将allowsttransparency
设置为true,否则将丢失
这是我的窗口的屏幕截图,用奇怪的颜色突出显示它的外观:
以下是一些关于如何开始的提示 请记住,我的代码相当长,因此我只能向您展示要做的基本事情,您至少应该能够以某种方式开始。首先,我将假设我们已经以某种方式设计了主窗口(手动或使用我昨天试用的
MahApps.Metro
包-对源代码进行了一些修改,这非常好(1)),我们目前正在努力实现发光阴影边框,从现在起,我将称之为GlowWindow
。最简单的方法是使用以下XAML代码创建一个窗口
<Window x:Class="MetroUI.Views.GlowWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="GlowWindow"
Title="" Width="300" Height="100" WindowStartupLocation="Manual"
AllowsTransparency="True" Background="Transparent" WindowStyle="None"
ShowInTaskbar="False" Foreground="#007acc" MaxWidth="5000" MaxHeight="5000">
<Border x:Name="OuterGlow" Margin="10" Background="Transparent"
BorderBrush="{Binding Foreground, ElementName=GlowWindow}"
BorderThickness="5">
<Border.Effect>
<BlurEffect KernelType="Gaussian" Radius="15" RenderingBias="Quality" />
</Border.Effect>
</Border>
</Window>
此方法主要在我已附加到主窗口的自定义WndProc
中调用:
/// <summary>
/// An application-defined function that processes messages sent to a window. The WNDPROC type
/// defines a pointer to this callback function.
/// </summary>
/// <param name="hwnd">A handle to the window.</param>
/// <param name="uMsg">The message.</param>
/// <param name="wParam">Additional message information. The contents of this parameter depend on
/// the value of the uMsg parameter.</param>
/// <param name="lParam">Additional message information. The contents of this parameter depend on
/// the value of the uMsg parameter.</param>
/// <param name="handled">Reference to boolean value which indicates whether a message was handled.
/// </param>
/// <returns>The return value is the result of the message processing and depends on the message sent.
/// </returns>
private IntPtr WindowProc(IntPtr hwnd, int uMsg, IntPtr wParam, IntPtr lParam, ref bool handled) {
// BEGIN UNMANAGED WIN32
switch((WinRT.Message)uMsg) {
case WinRT.Message.WM_SIZE:
switch((WinRT.Size)wParam) {
case WinRT.Size.SIZE_MAXIMIZED:
this.Left = this.Top = 0;
if(!this.IsMaximized)
this.IsMaximized = true;
this.UpdateChrome();
break;
case WinRT.Size.SIZE_RESTORED:
if(this.IsMaximized)
this.IsMaximized = false;
this.UpdateChrome();
break;
}
break;
case WinRT.Message.WM_WINDOWPOSCHANGING:
WinRT.WINDOWPOS windowPosition = (WinRT.WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WinRT.WINDOWPOS));
Window handledWindow = (Window)HwndSource.FromHwnd(hwnd).RootVisual;
if(handledWindow == null)
return IntPtr.Zero;
bool hasChangedPosition = false;
if(this.IsMaximized == true && (this.Left != 0 || this.Top != 0)) {
windowPosition.x = windowPosition.y = 0;
windowPosition.cx = (int)SystemParameters.WorkArea.Width;
windowPosition.cy = (int)SystemParameters.WorkArea.Height;
hasChangedPosition = true;
this.UpdateChrome();
this.UpdateGlowWindow();
}
if(!hasChangedPosition)
return IntPtr.Zero;
Marshal.StructureToPtr(windowPosition, lParam, true);
handled = true;
break;
}
return IntPtr.Zero;
// END UNMANAGED WIN32
}
但我们仍然会遇到一些问题-当您将鼠标移到GlowWindow上并左键单击时,它将被激活并获得焦点,这意味着它将与主窗口重叠,如下所示:
为了防止这种情况发生,只需捕捉边框的激活事件
,并将主窗口置于前台即可
您应该如何做到这一点?
我建议不要尝试这种方法——我花了大约一个月的时间才实现了我想要的,但仍然存在一些问题,因此我会选择Office 2013那样的方法——彩色边框和DWM API调用的常规阴影——没有其他方法,但仍然看起来不错
(1) 我刚刚编辑了一些文件以启用窗口周围的边框,这在窗口8上对我是禁用的。此外,我还操纵了标题栏的
填充
,使其看起来不像是在原地被sqeezed,最后我更改了All Caps属性,以模仿Visual Studio呈现标题的方式。到目前为止,MahApps.Metro
是一种更好的绘制主窗口的方法,因为它甚至支持AeroSnap,我无法用普通的P/Invoke调用实现。您可以使用这个简单的xaml代码
<Window x:Class="VS2012.MainWindow"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
Title="MainWindow"
Height="100" Width="200"
AllowsTransparency="True" WindowStyle="None" Background="Transparent">
<Border BorderBrush="DarkOrange" BorderThickness="1" Background="White" Margin="5">
<Border.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="5" Color="DarkOrange"/>
</Border.Effect>
</Border>
</Window>
我试图获得相同的效果,我的应用程序使用.NET 4,因此我无法直接使用
WindowChrome
(因此,我使用库来获得相同的效果
this.Loaded += delegate {
WindowInteropHelper wndHelper = new WindowInteropHelper(this);
int exStyle = (int)WinRT.GetWindowLong(wndHelper.Handle, (int)WinRT.GetWindowLongFields.GWL_EXSTYLE);
exStyle |= (int)WinRT.ExtendedWindowStyles.WS_EX_TOOLWINDOW;
WinRT.SetWindowLong(wndHelper.Handle, (int)WinRT.GetWindowLongFields.GWL_EXSTYLE, (IntPtr)exStyle);
};
<Window x:Class="VS2012.MainWindow"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
Title="MainWindow"
Height="100" Width="200"
AllowsTransparency="True" WindowStyle="None" Background="Transparent">
<Border BorderBrush="DarkOrange" BorderThickness="1" Background="White" Margin="5">
<Border.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="5" Color="DarkOrange"/>
</Border.Effect>
</Border>
</Window>
<Window x:Class="MyProject.MiniWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyProject"
mc:Ignorable="d"
WindowStyle="None"
Title="MiniWindow" Background="Transparent"
Height="200" Width="200"
>
<WindowChrome.WindowChrome>
<WindowChrome
CaptionHeight="0"
ResizeBorderThickness="4" />
</WindowChrome.WindowChrome>
<Grid Margin="0">
<Border BorderThickness="3">
<Border BorderThickness="1" Margin="0" BorderBrush="#ff007acc">
<Border.Effect>
<DropShadowEffect Color="#ff007acc" Direction="132" ShadowDepth="0" BlurRadius="8" />
</Border.Effect>
<Grid Background="#ff2d2d30">
</Grid>
</Border>
</Border>
</Grid>