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

Stu*_*ler 14 vb.net wpf 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">
Run Code Online (Sandbox Code Playgroud)

我在网上发现了一个创建阴影的课程,如下所示.即使使用调整大小的抓地力,这也很有效,直到我最大化窗口.一旦我最大化窗口或更改另一个窗口的窗口状态(例如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
Run Code Online (Sandbox Code Playgroud)

Ala*_*tts 23

所以我找到了一种方法来实现这一点.

您需要使用WPF Shell集成库(此处)为您完成工作.由于它是由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>
Run Code Online (Sandbox Code Playgroud)

<shell:WindowChrome>是你设置所有的互操作不同的变量.

  • CaptionHeight:这是标题区域(标题栏)的高度,允许Aero快照,双击行为作为普通标题栏.
  • GlassFrameThickness:0,0,0,1由于某种原因将其设置为删除铬(玻璃),保持方形边框,并添加投影.
  • ResizeBorderThickness:这是窗口边缘的厚度,您可以在此处调整窗口大小.

其他注意事项是保持Window.WindowStyle属性等于SingleBorderWindow,让Shell Library处理删除标题,按钮和其他chrome.

所以我在那里浪费了我的赏金,但它看起来像一个完全可行的解决方案,有效!

编辑:

这是结果的图片: 示例Metro WPF应用程序

我还在http://code.google.com/p/sample-metro-wpf-application/上设置了一个示例项目.这是麻省理工学院的许可证,人们可以随意使用它.

  • 如今,您不需要Microsoft.Windows.Shell包。该类在PresentationFramework.dll中作为System.Windows.Shell.WindowChrome`。 (2认同)

Stu*_*ler 16

要创建阴影效果,同时能够重新调整表单大小,请尝试以下操作:

  1. 在窗口上设置以下属性:

    • ResizeMode = "CanResizeWithGrip"
    • AllowsTransparency = "真"
    • WindowStyle = "无"
    • 背景="透明"
    • 了borderThickness = "3"
  2. 窗口声明后,添加一个Border元素

  3. Border.Effect在边框内创建一个元素
  4. 对于边框效果,请添加以下内容:

    <DropShadowEffect BlurRadius="5" Color="Black" Opacity="0.8" ShadowDepth="0.5" />
    
    Run Code Online (Sandbox Code Playgroud)

这将创建以下内容(右上角没有控制框):

在此输入图像描述

完整的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>
Run Code Online (Sandbox Code Playgroud)


Dre*_*kes 5

这是一些您需要执行的最少代码。

<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>
Run Code Online (Sandbox Code Playgroud)

该窗口的行为类似于通常的窗口,因为它可以是:

  • 通过其边缘调整大小
  • 在标题区域内拖动
  • 右键单击标题区域以显示系统菜单
  • 通过双击标题区域最大化/还原
  • 通过拖动或使用热键捕捉到屏幕的侧面(Win 10)

它也有一个阴影。


最终结果如下所示:

在此处输入图片说明