Stuart Blackler Stuart Blackler - 1 month ago 19
Vb.net Question

Maximum custom window loses drop shadow effect

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

Answer

To create a drop shadow effect whilst having the ability to re-size the form try the following:

  1. Set the following properties on the window:

    • ResizeMode="CanResizeWithGrip"
    • AllowsTransparency="True"
    • WindowStyle="None"
    • Background="Transparent"
    • BorderThickness="3"
  2. After the window declaration, add a Border element

  3. Create a Border.Effect element inside of the border
  4. For the border effect add the following:

    <DropShadowEffect BlurRadius="5" Color="Black" Opacity="0.8" ShadowDepth="0.5" />
    

This will create the following (without the control box in the top right):

enter image description here

Full 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>
Comments