代码之家  ›  专栏  ›  技术社区  ›  Thomas Levesque

在无边框的WPF窗口上启用Vista玻璃效果

  •  3
  • Thomas Levesque  · 技术社区  · 16 年前

    我编写了一个附加属性,可以在窗口上设置,将玻璃框架延伸到客户端区域(使用 DwmExtendFrameIntoClientArea

        WindowStyle="None"
        ResizeMode="NoResize"
        Background="Transparent"
        u:WinUtil.EnableGlass="True"
        ShowInTaskbar="False"
    

    但有了这些属性,玻璃根本不会出现:我的窗户只有透明的背景。如果我设置 ResizeMode CanResize ,玻璃显示出来了,但我不想调整窗户的大小。

    我怀疑这是由于玻璃效果是通过将非客户端框架扩展到客户端区域而获得的: WindowStyle = None ResizeMode = NoResize

    1. 如何初始化窗口的样式位?Window类似乎没有任何类似于Windows窗体的东西 CreateParams 财产。..在创建句柄后设置这些位可以吗?
    2. 我找到了 HwndSource 这个类可能是问题2的答案,但如果你不是Win32专家,使用它似乎有点复杂。..这是解决我问题的明智办法吗?

    欢迎提出任何建议

    2 回复  |  直到 16 年前
        1
  •  5
  •   Michael    16 年前
        2
  •  4
  •   user410387    15 年前

    我有一个窗口,我只想给它一个玻璃边框(没有标题栏,也不可调整大小),却遇到了和你一样的问题。仅通过设置窗口的样式无法实现这一点。我的解决方案是设置ResizeMode=“CanResize”和WindowStyle=“None”,然后处理WM_NCHITTEST事件,将可调整大小的边框点击转换为不可调整大小。还需要修改窗口的样式,以禁用最大化和最小化(使用Windows快捷方式)以及系统菜单:

    private void Window_SourceInitialized(object sender, EventArgs e)
    {
        System.Windows.Interop.HwndSource source = (System.Windows.Interop.HwndSource)PresentationSource.FromVisual(this);
        source.AddHook(new System.Windows.Interop.HwndSourceHook(HwndSourceHook));
    
        IntPtr hWnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
        IntPtr flags = GetWindowLongPtr(hWnd, -16 /*GWL_STYLE*/);
        SetWindowLongPtr(hWnd, -16 /*GWL_STYLE*/, new IntPtr(flags.ToInt64() & ~(0x00010000L /*WS_MAXIMIZEBOX*/ | 0x00020000L /*WS_MINIMIZEBOX*/ | 0x00080000L /*WS_SYSMENU*/)));
    }
    
    private static IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        switch (msg)
        {
            case 0x0084 /*WM_NCHITTEST*/:
                IntPtr result = DefWindowProc(hwnd, msg, wParam, lParam);
                if (result.ToInt32() >= 10 /*HTLEFT*/ && result.ToInt32() <= 17 /*HTBOTTOMRIGHT*/ )
                {
                    handled = true;
                    return new IntPtr(18 /*HTBORDER*/);
                }
                break;
        }
        return IntPtr.Zero;
    }
    
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern IntPtr DefWindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
    
    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
    

    这为您在Windows 7中提供了一个适用于通知区域弹出按钮(例如时钟或音量弹出按钮)的窗口。顺便说一句,您可以通过创建高度44的控件并设置其背景来再现弹出按钮底部的着色:

    <Control.Background>
        <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <GradientStop Color="{x:Static SystemColors.GradientActiveCaptionColor}" Offset="0"/>
            <GradientStop Color="{x:Static SystemColors.InactiveBorderColor}" Offset="0.1"/>
        </LinearGradientBrush>
    </Control.Background>