如何在无窗口的Windows窗体上获取Aero Glass?

问题描述:

我试图让Aero Glass使用DWM API在VB.NET 2010应用程序中查看我的窗体,但是根据函数调用的建议,它将Frame的外观扩展到客户区,并且如果窗体没有边框,则不会发生任何事情形式将变得不可见。那么,我可以在没有任何边界的情况下获得Aero玻璃.... ??如何在无窗口的Windows窗体上获取Aero Glass?

如您所说,DwmExtendFrameIntoClientArea将窗框的透明玻璃效果字面延伸到其客户区域,这意味着如果您的窗体的FormBorderStyle设置为“无”,您的窗口将实际上不可见。

取而代之,您需要使用DwmEnableBlurBehindWindow API,它可以使窗口上的玻璃状模糊效果不需要框架/边框。它需要两个参数。第一个(hWnd)是您希望将模糊效果应用于的表单的句柄。第二个(pBlurBehind)是一个通过引用传递的结构,其中包含该效果的数据或参数。

因此,您还必须定义DWM_BLURBEHIND structure,它本身包含四个成员。第一个(dwFlags)是constant values的按位组合,表示已经设置了此结构的哪些成员。第二个(fEnable)指示您是要启用还是禁用模糊效果。第三个(hRgnBlur)允许您指定模糊效果将应用于客户区域内的特定区域;将其设置为Nothing表示整个客户区都会产生模糊效果。第四个(fTransitionOnMaximized)允许您指定窗体的着色是否应该过渡以匹配最大化的窗口。

在这里,你必须在你的代码,包括为了使用这个功能最终API声明:

<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 

然后这里,你会怎么称呼一个特定的形式对这个函数的简单例子:

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 

相反,如果你只是想后面效果模糊适用于形式的特定分区,则需要为hRgnBlur成员提供有效的区域,DWM_BB_BLURREGION标志添加到dwFlags成员。

您可以使用Region.GetHrgn method来获取您想要指定为hRgnBlur成员的区域的句柄。例如,而不是上面的代码,你可以使用以下命令:

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 

注意如何,指定一个特定的分区,即使应用模糊隐藏效果,我还是设置整个窗体的背景色为黑色?这将导致我们指定的区域以玻璃模糊效果进行渲染,并且窗体的其余部分显示为透明。当然,您可以将窗体背景颜色的其余部分设置为您想要的任何颜色(尽管如以前那样确保填充您希望以黑色显示为玻璃的矩形),但它会显示为部分透明,没有玻璃模糊效果。 MSDN解释了为什么是这样的话:

当应用模糊隐藏效果 到窗口的一个分区,则使用窗口的 alpha通道 为nonblurred区域。这可能会导致 窗口的非模糊区域出现意外透明。 因此,对子区域应用 模糊效果时要小心。

就我而言,这使得只对窗体窗口的子区域应用此效果相对毫无价值。在我看来,唯一可能的情况是,如果你想渲染一个任意的非矩形形状为玻璃状,其余的表单保持透明。

+0

+1,但除非您向他展示如何使用该区域,否则无法使用。 – 2010-12-12 07:14:02

+0

@Hans:我添加了一个区域示例,虽然就像我指出的那样,至少在WinForms中,它的用处似乎非常有限。 – 2010-12-12 07:48:46

+0

感谢您抽出宝贵时间并给出了一个简短的解释,它按照您的建议工作。我在哪里可以找到有关此API的其他方法的详细信息,除了MSDN? – Kushal 2010-12-12 11:21:36