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

3

我编写了一个附加属性,可以在窗口上设置,将玻璃框架扩展到客户区域(使用 DwmExtendFrameIntoClientArea API)。它在大多数情况下都能正常工作。现在我想让我的窗口没有边框,所以我在窗口上设置了以下属性:

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

但是,具有这些属性后,玻璃完全不显示:我的窗口只有一个透明的背景。如果我将ResizeMode设置为CanResize,则会显示玻璃效果,但我不希望该窗口可调整大小。
我怀疑这是由于通过将非客户端框架扩展到客户端区域来获得玻璃效果:使用WindowStyle = NoneResizeMode = NoResize,没有非客户端框架,因此没有可以扩展的内容。当我启用调整大小时,它会在窗口周围创建一个框架,因此可以扩展框架。
我想应该可以创建一个带有细边框、没有标题栏且不能调整大小的窗口,方法是设置适当的WS_*位,但我不知道具体是哪些位。
因此,我的问题如下:
  1. 应该设置或取消哪些样式位以实现所需的外观和行为?
  2. 如何初始化窗口的样式位?Window类似乎没有任何Windows Forms CreateParams 属性... 在创建句柄后设置这些位是否可行?
  3. 我发现了HwndSource类,这可能是问题2的解决方案,但如果您不是Win32专家,使用起来似乎有点复杂...这对我的问题是否是一个明智的解决方案?
欢迎任何建议。
2个回答

5

看起来很有前途,谢谢。现在我得想办法如何使用它,但它看起来并不太难 ;) - Thomas Levesque
3
好的,明白了...我需要将CompositionTarget.BackgroundColor设置为Transparent,并将AllowsTransparency设置为true。谢谢! - Thomas Levesque

4

我有一个窗口,想要给它添加一个玻璃边框(没有标题栏和不可调整大小),遇到了与您相同的问题。仅通过设置窗口的样式是无法实现的。我的解决方案是将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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接