我有一个自定义WPF窗口,定义为:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" MinHeight="300" Height="350" MinWidth="600" Width="700" ResizeMode="CanResizeWithGrip" AllowsTransparency="True" WindowStyle="None">
我在网上发现了一个创建阴影的课程,如下所示。即使使用调整大小的抓地力,这也很有效,直到我最大化窗口。一旦我最大化窗口或更改另一个窗口的窗口状态(例如Visual Studio),我就会松开阴影,我无法将其恢复。任何想法?
Drop Shadow Class:
Public Class DropShadow
Private Shared _handler As EventHandler = New EventHandler(AddressOf window_SourceInitialized)
<DllImport("dwmapi.dll", PreserveSig:=True)> _
Private Shared Function DwmSetWindowAttribute(hwnd As IntPtr, attr As Integer, ByRef attrValue As Integer, attrSize As Integer) As Integer
End Function
<DllImport("dwmapi.dll")> _
Private Shared Function DwmExtendFrameIntoClientArea(hWnd As IntPtr, ByRef pMarInset As Margins) As Integer
End Function
Public Shared Sub DropShadowToWindow(window As Window)
If Not DropShadow(window) Then
AddHandler window.SourceInitialized, _handler
AddHandler window.SizeChanged, New SizeChangedEventHandler(AddressOf windowSizeChanged)
End If
End Sub
Private Shared Sub window_SourceInitialized(sender As Object, e As EventArgs)
Dim window As Window = DirectCast(sender, Window)
DropShadow(window)
RemoveHandler window.SourceInitialized, _handler
End Sub
Private Shared Function DropShadow(window As Window) As Boolean
Try
Dim helper As New WindowInteropHelper(window)
Dim val As Integer = 2
Dim ret1 As Integer = DwmSetWindowAttribute(helper.Handle, 2, val, 4)
If ret1 = 0 Then
Dim m As New Margins() With { _
.Bottom = 0, _
.Left = 0, _
.Right = 0, _
.Top = 0 _
}
Dim ret2 As Integer = DwmExtendFrameIntoClientArea(helper.Handle, m)
Return ret2 = 0
Else
Return False
End If
Catch ex As Exception
' Probably dwmapi.dll not found (incompatible OS)
Return False
End Try
End Function
Private Shared Sub windowSizeChanged(sender As Object, e As SizeChangedEventArgs)
Dim window As Window = DirectCast(sender, Window)
DropShadow(window)
End Sub
End Class
答案 0 :(得分:22)
所以我找到了一种方法让它发挥作用。
您需要使用WPF Shell集成库(here)为您完成工作。由MS编写,他们已经修复了(似乎)与P / Invoke代码相关的任何问题。
因此很容易得到一个没有Aero玻璃的窗口,边缘可调整大小,有一个标注区域,表现为Aero snap,并且有一个投影,在最小/最大化后重新出现。
这是我的窗口的代码(注意,您需要引用Microsoft.Windows.Shell
)
<Window x:Class="MyLibrary.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:shell="http://schemas.microsoft.com/winfx/2006/xaml/presentation/shell"
Title="MainWindow"
WindowStyle="SingleBorderWindow"
ResizeMode="CanResizeWithGrip"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="449"
d:DesignWidth="677"
Foreground="White"
Background="Black">
<shell:WindowChrome.WindowChrome>
<shell:WindowChrome CaptionHeight="35"
GlassFrameThickness="0,0,0,1"
ResizeBorderThickness="5" />
</shell:WindowChrome.WindowChrome>
<Grid x:Name="LayoutRoot">
</gGrid>
</Window>
<shell:WindowChrome>
是您为互操作设置所有不同变量的地方。
CaptionHeight
:这是标题区域(标题栏)的高度,允许Aero快照,双击行为作为普通标题栏。GlassFrameThickness
:由于某种原因将其设置为0,0,0,1
会移除镶边(玻璃),保留方形边框,并添加投影。ResizeBorderThickness
:这是窗口边缘的厚度,您可以在此处调整窗口大小。要注意的其他事项是保持Window.WindowStyle属性等于SingleBorderWindow
并让Shell Library处理删除标题,按钮和其他chrome。
所以我在那里浪费了我的赏金,但它看起来像一个完全可行的解决方案,有效!
编辑:
以下是结果的图片:
我还在http://code.google.com/p/sample-metro-wpf-application/上设置了一个示例项目。它是MIT许可证,人们可以随意使用它。
答案 1 :(得分:16)
要创建投影效果,同时能够重新调整表单大小,请尝试以下操作:
在窗口中设置以下属性:
在窗口声明后,添加Border
元素
Border.Effect
元素对于边框效果,请添加以下内容:
<DropShadowEffect BlurRadius="5" Color="Black" Opacity="0.8" ShadowDepth="0.5" />
这将创建以下内容(右上角没有控制框):
完整的XAML:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" MinHeight="500" Height="350" MinWidth="300" Width="700" ResizeMode="CanResizeWithGrip" AllowsTransparency="True" WindowStyle="None" Background="White" BorderThickness="3">
<Border>
<Border.Effect>
<DropShadowEffect BlurRadius="5" Color="Black" Opacity="0.8" ShadowDepth="0.5" />
</Border.Effect>
<!-- Put your content in here -->
</Border>
</Window>
答案 2 :(得分:4)
这是一些最小的代码,可以完成你所追求的目标。
<Window x:Class="WindowChromeSpike.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<WindowChrome.WindowChrome>
<WindowChrome GlassFrameThickness="0,0,0,1" CornerRadius="0" />
</WindowChrome.WindowChrome>
<!-- window contents: just a blue rectangle for demo purposes -->
<Border Background="#0093C0" />
</Window>
此窗口的行为类似于通常的窗口,因为它可以是:
它也有一个投影。
最终结果如下: