Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.... ??

like image 666
Kushal Avatar asked Dec 12 '10 05:12

Kushal


1 Answers

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.

like image 118
Cody Gray Avatar answered Sep 20 '22 02:09

Cody Gray