Dropping shadow on WinForm distorts interface

1.8k views Asked by At

I'm using the following code to create a Windows7 style drop shadow effect on my WinForms:

<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

Private Function CreateDropShadow() As Boolean
    Try
        Dim val As Integer = 2
        Dim ret1 As Integer = DwmSetWindowAttribute(Me.Handle, 2, val, 4)

        If ret1 = 0 Then
            Dim m As New Margins(0, 0, 0, 0)
            Dim ret2 As Integer = DwmExtendFrameIntoClientArea(Me.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

Protected Overrides Sub OnHandleCreated(e As EventArgs)
    CreateDropShadow()
    MyBase.OnHandleCreated(e)
End Sub

The result of above code creates a nice drop shadow effect on my borderless winform, but it causes the UI to distort. All the controls and labels on my form aren't appearing properly, with text not readable.

Am I missing something here? I don't want to use the traditional drop shadow effect using CreateParams, its too 'boxy' look and doesn't give a nice shadow effect.

Here are screenshots of without shadow and with shadow: Form without drop shadow Form with drop shadow

Thanks.

1

There are 1 answers

2
Hans Passant On BEST ANSWER
  Dim m As New Margins(0, 0, 0, 0)

There's a subtle mistake visible here, looks a lot like you are using System.Drawing.Printing.Margins. But that's not a type that's compatible with the Windows' MARGINS type. Which is a structure, not a class.

So this just goes complete wrong, Windows reads nonsense instead of (0, 0, 0, 0). And extends the frame into the entire client area. Which then plays havoc on any control that draws with GDI, it is a 24bpp drawing api that leaves the alpha at 0 so anything that should be black becomes transparent instead.

Fix this by declaring a proper MARGINS structure:

Structure MARGINS
    Public Left, Right, Top, Bottom As Integer
End Structure