最大自定义窗口失去投影效果
我有一个自定义 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)的窗口状态,我就会失去阴影并且无法将其恢复。有什么想法吗?
投影类:
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
I have a custom WPF window defined as:
<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">
I found a class online that creates drop shadows, shown below. This works well, even with a resize grip, until I maximise the window. Once I maximise the window or change the window state of another window (eg. Visual Studio), I loose the drop shadow and I cannot get it back. Any Ideas?
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
所以我找到了一种方法来让它发挥作用。
您需要使用 WPF Shell 集成库(此处)来为您完成这项工作。由于它是由 MS 编写的,他们已经修复了(看起来)对 P/Invoke 代码执行的任何问题。
因此,很容易得到一个没有 Aero 玻璃、边缘可调整大小、具有 Aero 捕捉行为的标题区域以及在最小/最大后重新出现的阴影的窗口。
这是我的窗口的代码(注意,您需要引用
Microsoft.Windows.Shell
)
是您设置所有不同变量的位置用于互操作。CaptionHeight
:这是标题区域(标题栏)的高度,允许像普通标题栏一样进行 Aero 捕捉、双击行为。GlassFrameThickness
:出于某种原因将其设置为0,0,0,1
会删除镀铬(玻璃),保留方形边框,并添加阴影。ResizeBorderThickness
:这是窗口边缘的厚度,您可以在此处调整窗口大小。其他需要注意的事项是,您应将 Window.WindowStyle 属性保持为
SingleBorderWindow
并让 Shell 库处理删除标题、按钮和其他镶边的操作。所以我在那里浪费了我的赏金,但它看起来是一个完全可行的解决方案,非常有效!
编辑:
这是结果的图片:
我还在 http://code.google.com/p/sample-metro-wpf-application/。这是麻省理工学院的许可证,人们可以随心所欲地使用它。
So I found out a way to get this to work.
You need to use the WPF Shell Integration Library (here) to do the work for you. As it's been written by MS, they have fixed (it seems) any issues with doing to the P/Invoke code.
So it is easy to get a Window that has no Aero glass, is resizable on the edges, has a caption area that behaves with Aero snap, and has a drop shadow that reappears after min/maxing.
This is the code for my window (note, you need to have referenced
Microsoft.Windows.Shell
)The
<shell:WindowChrome>
is where you set all the different variables for the interop.CaptionHeight
: This is the height of the caption area (headerbar) that allows for the Aero snap, double clicking behaviour as a normal title bar does.GlassFrameThickness
: Setting this to0,0,0,1
for some reason removes the chrome (glass), keeps the square border, and adds a drop shadow.ResizeBorderThickness
: This is thickness at the edge of the window which is where you can resize the window.Other things to note as that you keep the Window.WindowStyle property equal to
SingleBorderWindow
and let the Shell Library deal with removing the title, buttons and other chrome.So I kinda wasted my bounty there, but it looks like a completely viable solution that works a treat!
EDIT:
Here is a picture of the result:
I also put up a sample project on http://code.google.com/p/sample-metro-wpf-application/. It's an MIT license and people can use it however they want.
要创建阴影效果,同时能够调整表单大小,请尝试以下操作:
在窗口上设置以下属性:
在窗口声明后,添加
Border
元素Border.Effect
元素用于边框效果添加以下:
这将创建以下内容(右上角没有控制框):
完整的 XAML:
To create a drop shadow effect whilst having the ability to re-size the form try the following:
Set the following properties on the window:
After the window declaration, add a
Border
elementBorder.Effect
element inside of the borderFor the border effect add the following:
This will create the following (without the control box in the top right):
Full XAML:
这是一些可以完成您所追求的任务的最小代码。
该窗口的行为类似于普通窗口,因为它可以:
它还有一个投影。
最终结果如下所示:
Here's some minimal code that does what you're after.
This window behaves like a usual window in that it can be:
It also has a drop shadow.
The end result looks like this: