How can I get Aero Glass on a Windows Form without Borders?

13,670

As you've said, DwmExtendFrameIntoClientArea literally extends the transparent glass effect of the window's frame into its client area, which means that if your form's FormBorderStyle is set to "None", your window will effectively be invisible.

Instead, you need to use the DwmEnableBlurBehindWindow API, which enables the glassy blur effect on a window without requiring it to have a frame/border. It takes two parameters. The first (hWnd) is the handle to the form that you wish to apply the blur behind effect to. The second (pBlurBehind) is a structure passed by reference that contains data or parameters for the effect.

Therefore, you also have to define the DWM_BLURBEHIND structure, which itself contains four members. The first (dwFlags) is a bitwise combination of constant values that indicate which members of this structure have been set. The second (fEnable) indicates whether you want to enable or disable the blur effect. The third (hRgnBlur) allows you to specify a particular region within the client area that the blur effect will be applied to; setting this to Nothing indicates that the entire client area will have the blur effect. The fourth (fTransitionOnMaximized) allows you to specify whether or not the form's colorization should transition to match the maximized windows.

Here are the final API declarations that you have to include in your code in order to use this function:

<StructLayout(LayoutKind.Sequential)> _
Private Structure DWM_BLURBEHIND
    Public dwFlags As Integer
    Public fEnable As Boolean
    Public hRgnBlur As IntPtr
    Public fTransitionOnMaximized As Boolean
End Structure

Private Const DWM_BB_ENABLE As Integer = &H1
Private Const DWM_BB_BLURREGION As Integer = &H2
Private Const DWM_BB_TRANSITIONONMAXIMIZED As Integer = &H4

<DllImport("dwmapi.dll", PreserveSig:=False)> _
Private Shared Sub DwmEnableBlurBehindWindow(ByVal hWnd As IntPtr, ByRef pBlurBehind As DWM_BLURBEHIND)
End Sub

And then here's a simple example of how you would call this function on a particular form:

Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
    MyBase.OnLoad(e)

    ''#Set the form's border style to None
    Me.FormBorderStyle = FormBorderStyle.None

    ''#Whatever region that you fill with black will become the glassy region
    ''# (in this example, the entire form becomes transparent)
    Me.BackColor = Color.Black

    ''#Create and populate the blur-behind structure
    Dim bb As DWM_BLURBEHIND
    bb.dwFlags = DWM_BB_ENABLE
    bb.fEnable = True
    bb.hRgnBlur = Nothing

    ''#Enable the blur-behind effect
    DwmEnableBlurBehindWindow(Me.Handle, bb)
End Sub

If instead, you only want to apply the blur behind effect to a particular subregion of the form, you will need to supply a valid region for the hRgnBlur member, and add the DWM_BB_BLURREGION flag to the dwFlags member.

You can use the Region.GetHrgn method to get a handle to the region you want to specify as the hRgnBlur member. For example, instead of the above code, you can use the following:

Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
    MyBase.OnLoad(e)

    ''#Set the form's border style to None
    Me.FormBorderStyle = FormBorderStyle.None

    ''#Fill the entire form with black to make it appear transparent
    Me.BackColor = Color.Black

    ''#Create a region corresponding to the area of the form you want to render as glass
    Using g As Graphics = Me.CreateGraphics
        Dim glassRect As New Rectangle(0, 0, 100, 150)
        Using rgn As New Region(glassRect)
            ''#Create and populate the blur-behind structure
            Dim bb As DWM_BLURBEHIND
            bb.dwFlags = DWM_BB_ENABLE Or DWM_BB_BLURREGION
            bb.fEnable = True
            bb.hRgnBlur = rgn.GetHrgn(g)

            ''#Enable blur-behind effect
            DwmEnableBlurBehindWindow(Me.Handle, bb)
        End Using
    End Using
End Sub

Notice how, even when specifying a particular subregion to apply the blur-behind effect to, I still set the entire form's background color to black? This will cause the region we specified to render with a glassy blur-behind effect, and the rest of the form to appear transparent. Of course, you can set the rest of the form's background color to any color that you want (although make sure to fill the rectangle that you want to appear as glass with the color black, as before), but it will appear as partially transparent, just without the glassy blur-behind effect. MSDN explains why this is the case:

When you apply the blur-behind effect to a subregion of the window, the alpha channel of the window is used for the nonblurred area. This can cause an unexpected transparency in the nonblurred region of a window. Therefore, be careful when you apply a blur effect to a subregion.

As far as I'm concerned, that makes applying this effect to only a subregion of the form's window relatively worthless. The only time it seems to me like it might make sense is if you want to render an arbitrary non-rectangular shape as glassy, with the rest of the form remaining transparent.

Share:
13,670
Kushal
Author by

Kushal

I design, code and blog.

Updated on June 15, 2022

Comments

  • Kushal
    Kushal almost 2 years

    I'm trying to have Aero Glass look in my forms in VB.NET 2010 app with DWM API, but as function call suggests, it extends look of Frame to the client area, and if form has no border, nothing will happen and form will become invisible. So, can I get Aero glass in a form without any border.... ??

  • Cody Gray
    Cody Gray over 13 years
    @Hans: I added an example of regions, although like I point out, the usefulness of this seems awfully limited, at least in WinForms.
  • Kushal
    Kushal over 13 years
    Thanks for taking time and giving such a brief explanation, It worked as you suggested. Where can I find details regarding other methods of this API, apart from MSDN??
  • Cody Gray
    Cody Gray over 13 years
    @Kush: Other than MSDN, I'm really not sure. You could try pinvoke.net, but I've found their coverage is kind of spotty, and it's best to cross-check their content with what you find on MSDN because some declarations are incorrect or incomplete. Microsoft has unfortunately not made taking complete advantage of DWM features very convenient for us .NET developers. Once you know the function you want to import, a Google search will often turn up some blog entries (lots of them from MS employees), but I'm afraid I don't know of any central resource.
  • Oscar Jara
    Oscar Jara about 12 years
    This works good but what about using win forms elements and then apply this glass effect? I think it doesn't look fine, what will be the solution for that?
  • Cody Gray
    Cody Gray about 12 years
    @Oscar: Yes, that starts getting complicated. The real answer is not to place controls on top of the glassy area: there's rarely a circumstance where that makes sense. The problem is that controls often have text drawn in black, but black is the transparent color as far as DWM is concerned, so everything black is actually rendered as transparent (glass). To really make things work, you need to draw using GDI+, which understands transparency and differentiates between black that is going to be transparent, and regular solid black. The WinForms controls wrap Win32 controls, which draw using GDI.
  • Cody Gray
    Cody Gray about 12 years
    A search will reveal several questions along those lines, but there just isn't a good solution. And the comment thread certainly isn't the place for me to try and propose one.
  • Oscar Jara
    Oscar Jara about 12 years
    Thank you very much for this information. Today I made some search regarding this and found something. Take a look at this: stackoverflow.com/questions/9694688/aeroglass-with-vb-net :-)
  • Cody Gray
    Cody Gray about 12 years
    @oscar: Haha yes, the accepted answer to that question links to my answer to another question. I'd forgotten that I'd already answered a question on this topic...
  • Oscar Jara
    Oscar Jara about 12 years
    @CodyGray haha, no problem :-)