【问题标题】:Enable Vista glass effect on a borderless WPF window在无边框 WPF 窗口上启用 Vista 玻璃效果
【发布时间】:2009-08-24 19:55:57
【问题描述】:

我编写了一个附加属性,可以在窗口上设置它以将玻璃框架延伸到客户区域(使用DwmExtendFrameIntoClientArea API)。在大多数情况下它工作正常。现在我希望我的窗口是无边框的,所以我在我的窗口上设置了以下属性:

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

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

我怀疑是因为玻璃效果是通过将非客户端框架扩展到客户端区域获得的:WindowStyle = None和ResizeMode = NoResize,没有非客户端框架,所以没有什么可做的延长。当我启用调整大小时,它会在窗口周围创建一个框架,因此可以扩展框架。

我想应该可以通过设置适当的 WS_* 位来创建一个有细边框、没有标题栏且无法调整大小的窗口,但我不知道具体是哪些

所以我的问题是:

  1. 应设置或取消设置哪些样式位以获得所需的外观和行为?
  2. 如何初始化窗口的样式位? Window 类似乎没有类似 Windows Forms CreateParams 属性的东西...在创建句柄后设置这些位是否可以?
  3. 我发现 HwndSource 类可以作为问题 2 的答案,但如果您不是 Win32 专家,使用它似乎有点复杂......这对我的问题来说是一个明智的解决方案吗?李>

欢迎任何建议

【问题讨论】:

    标签: wpf windows aero-glass


    【解决方案1】:

    您是否尝试过使用DwmEnableBlurBehindWindow?这使您可以使窗口客户区的特定部分透明。

    【讨论】:

    • 看起来很有希望,谢谢。现在我必须弄清楚如何使用它,但看起来还不错;)
    • 好的,明白了...我必须将CompositionTarget.BackgroundColor 设置为Transparent,并将AllowsTransparency 设置为true。谢谢!
    【解决方案2】:

    我有一个窗口,我只想给一个玻璃边框(没有标题栏且不可调整大小)并且遇到了和你一样的问题。您不能仅通过设置 Window 的样式来完成此操作。我的解决方案是设置 ResizeMode="CanResize" 和 WindowStyle="None" 然后处理 WM_NCHITTEST 事件以将可调整大小的边框命中转换为不可调整大小的边框命中。还需要修改 Window 的样式以禁用最大化和最小化(使用 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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-19
      • 2010-10-02
      • 1970-01-01
      • 1970-01-01
      • 2013-08-22
      • 1970-01-01
      • 2011-07-22
      • 1970-01-01
      相关资源
      最近更新 更多