wpf - 最大自定义窗口丢失阴影效果

标签 wpf vb.net xaml window

我有一个自定义的 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">

我在网上找到了一个创建阴影的类(class),如下所示。即使使用调整大小的 handle ,这也很有效,直到我最大化窗口。一旦我最大化窗口或更改另一个窗口(例如 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

最佳答案

所以我找到了一种方法来让它发挥作用。

您需要使用 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出于某种原因,移除了 Chrome (玻璃),保留了方形边框,并添加了阴影。
  • ResizeBorderThickness :这是窗口边缘的厚度,您可以在此处调整窗口大小。

  • 在保持 Window.WindowStyle 属性等于 SingleBorderWindow 时要注意的其他事项并让 Shell 库处理删除标题、按钮和其他镶边。

    所以我有点在那里浪费了我的赏金,但它看起来像是一个完全可行的解决方案,可以很好地享受!

    编辑:

    这是结果的图片:Sample Metro WPF Application

    我还在 http://code.google.com/p/sample-metro-wpf-application/ 上放了一个示例项目.这是一个 MIT 许可证,人们可以随意使用它。

    关于wpf - 最大自定义窗口丢失阴影效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7369115/

    相关文章:

    c# - 是否有理解/记录 c#/vb.net 分解以及如何合并它们的源代码控制系统?

    c# - 如何在 VB.NET 中实现 Bitboard?

    vb.net - 查找 Outlook.MAPIFolder 的类型

    wpf - WPF DataGrid 的 GroupStyle 上的 HeaderTemplate 和 ContainerStyle 有什么区别?

    c# - OxyPlot 中日期时间轴上的不规则间隔

    c# - UWP ListView 数据模板绑定(bind)

    c# - 自定义 WPF "Slider"控件以在路径上滑动

    wpf 按钮背景悬停颜色

    c# - Windows 8 消息框样式 WPF

    wpf - 默认转换器何时启动?