WPF无边框窗口带阴影VS2012风格

2024-02-19

我正在尝试创建一个看起来像 Visual Studio 2012 的应用程序。我使用过窗口Chrome http://msdn.microsoft.com/en-us/library/system.windows.shell.windowchrome.aspx删除窗口边框,并更改我的 xaml 中的边框颜色。

我不知道该怎么做是绘制窗口的阴影,在这里你可以看到我所说的屏幕截图:

正如你所看到的,有一个阴影,它的颜色也是边框颜色

你知道如何使用WPF实现它吗?


更新(2017 年 10 月)

现在已经四年了,我有兴趣再次解决这个问题,因此我一直在搞乱MahApps.Metro再次和基于它派生出我自己的库 https://github.com/ChristianIvicevic/ModernChrome. My 现代镀铬库提供了一个类似于 Visual Studio 2017 的自定义窗口:

由于您很可能只对发光边框的部分感兴趣,因此您应该使用MahApps.Metro本身或看看我如何创建一个类GlowWindowBehavior它将发光边框附加到我的自定义中ModernWindow班级。它严重依赖于某些内部结构MahApps.Metro和两个依赖属性GlowBrush and NonActiveGlowBrush.

如果您只想在自定义应用程序中包含发光边框,请参考MahApps.Metro并复制我的GlowWindowBehavior.cs并创建一个自定义窗口类并相应地调整引用。这最多也就15分钟的事情。

这个问题和我的答案已经被频繁访问,所以我希望您会发现我最新的正确解决方案很有用:)


原帖(2013 年 2 月)

我一直在开发这样一个库来复制 Visual Studio 2012 用户界面。自定义镀铬并不那么困难,但您应该注意的是很难实现的发光边框。您可以将窗口的背景颜色设置为透明,并将主网格的填充设置为大约 30 像素。网格周围的边框可以是彩色的,并与彩色阴影效果相关联,但这种方法迫使您设置AllowsTransparency设置为 true 会大大降低应用程序的视觉性能,这是您绝对不想做的事情!

我当前创建这样一个窗口的方法,该窗口仅在边框上具有彩色阴影效果并且是透明的,但根本没有内容。每当主窗口的位置发生变化时,我只需更新包含边框的窗口的位置。所以最后我正在处理两个带有消息的窗口,以假装边框将成为主窗口的一部分。这是必要的,因为 DWM 库没有提供一种为窗口提供彩色阴影效果的方法,而且我认为 Visual Studio 2012 的做法与我尝试的类似。

并用更多信息来扩展这篇文章:Office 2013 的做法有所不同。窗口周围的边框只有 1px 厚且有颜色,但阴影是由 DWM 使用如下代码绘制的this one https://stackoverflow.com/a/6313576/796036这里。如果你可以在没有蓝色/紫色/绿色边框而只有普通边框的情况下生活,这就是我会选择的方法!只是不设置AllowsTransparency为真,否则你就输了。

这是我的窗口的屏幕截图,用奇怪的颜色突出显示它的样子:


以下是有关如何开始的一些提示

Please keep in mind that my code is quite long, such that I will only be able to show you the basic things to do and you should be able to at least start somehow. First of all I'm going to assume that we have designed our main window somehow (either manually or with the MahApps.Metro package I tried out yesterday - with some modifications to the sourcecode this is really good(1)) and we are currently working to implement the glowing shadow border, which I will call GlowWindow from now on. The easiest approach is to create a window with the following XAML code

<Window x:Class="MetroUI.Views.GlowWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="GlowWindow"
    Title="" Width="300" Height="100" WindowStartupLocation="Manual"
    AllowsTransparency="True" Background="Transparent" WindowStyle="None"
    ShowInTaskbar="False" Foreground="#007acc" MaxWidth="5000" MaxHeight="5000">
    <Border x:Name="OuterGlow" Margin="10" Background="Transparent"
            BorderBrush="{Binding Foreground, ElementName=GlowWindow}"
            BorderThickness="5">
        <Border.Effect>
            <BlurEffect KernelType="Gaussian" Radius="15" RenderingBias="Quality" />
        </Border.Effect>
    </Border>
</Window>

生成的窗口应如下图所示。

接下来的步骤非常困难 - 当我们的主窗口生成时,我们希望使 GlowWindow 可见,但位于主窗口后面,并且当主窗口移动或调整大小时,我们必须更新 GlowWindow 的位置。为了防止可能发生的视觉故障,我建议在每次更改窗口位置或大小时隐藏 GlowWindow。完成此类操作后,只需再次显示即可。

我有一些在不同情况下调用的方法(可能很多,但只是为了确定)

private void UpdateGlowWindow(bool isActivated = false) {
    if(this.DisableComposite || this.IsMaximized) {
        this.glowWindow.Visibility = System.Windows.Visibility.Collapsed;
        return;
    }
    try {
        this.glowWindow.Left = this.Left - 10;
        this.glowWindow.Top = this.Top - 10;
        this.glowWindow.Width = this.Width + 20;
        this.glowWindow.Height = this.Height + 20;
        this.glowWindow.Visibility = System.Windows.Visibility.Visible;
        if(!isActivated)
            this.glowWindow.Activate();
    } catch(Exception) {
    }
}

我自定义中主要调用这个方法WndProc我已附加到主窗口:

/// <summary>
/// An application-defined function that processes messages sent to a window. The WNDPROC type
/// defines a pointer to this callback function.
/// </summary>
/// <param name="hwnd">A handle to the window.</param>
/// <param name="uMsg">The message.</param>
/// <param name="wParam">Additional message information. The contents of this parameter depend on
/// the value of the uMsg parameter.</param>
/// <param name="lParam">Additional message information. The contents of this parameter depend on
/// the value of the uMsg parameter.</param>
/// <param name="handled">Reference to boolean value which indicates whether a message was handled.
/// </param>
/// <returns>The return value is the result of the message processing and depends on the message sent.
/// </returns>
private IntPtr WindowProc(IntPtr hwnd, int uMsg, IntPtr wParam, IntPtr lParam, ref bool handled) {
    // BEGIN UNMANAGED WIN32
    switch((WinRT.Message)uMsg) {
        case WinRT.Message.WM_SIZE:
            switch((WinRT.Size)wParam) {
                case WinRT.Size.SIZE_MAXIMIZED:
                    this.Left = this.Top = 0;
                    if(!this.IsMaximized)
                        this.IsMaximized = true;
                    this.UpdateChrome();
                    break;
                case WinRT.Size.SIZE_RESTORED:
                    if(this.IsMaximized)
                        this.IsMaximized = false;
                    this.UpdateChrome();
                    break;
            }
            break;

        case WinRT.Message.WM_WINDOWPOSCHANGING:
            WinRT.WINDOWPOS windowPosition = (WinRT.WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WinRT.WINDOWPOS));
            Window handledWindow = (Window)HwndSource.FromHwnd(hwnd).RootVisual;
            if(handledWindow == null)
                return IntPtr.Zero;
            bool hasChangedPosition = false;
            if(this.IsMaximized == true && (this.Left != 0 || this.Top != 0)) {
                windowPosition.x = windowPosition.y = 0;
                windowPosition.cx = (int)SystemParameters.WorkArea.Width;
                windowPosition.cy = (int)SystemParameters.WorkArea.Height;
                hasChangedPosition = true;
                this.UpdateChrome();
                this.UpdateGlowWindow();
            }
            if(!hasChangedPosition)
                return IntPtr.Zero;
            Marshal.StructureToPtr(windowPosition, lParam, true);
            handled = true;
            break;
    }
    return IntPtr.Zero;
    // END UNMANAGED WIN32
}

然而,仍然存在一个问题 - 一旦您调整主窗口的大小,GlowWindow 将无法以其大小覆盖整个窗口。也就是说,如果您将主窗口的大小调整到屏幕的 MaxWidth 左右,那么 GlowWindow 的宽度将是相同的值 + 20,因为我为其添加了 10 的边距。因此,右边缘将在主窗口右边缘之前被打断,这看起来很难看。为了防止这种情况,我使用了一个钩子使 GlowWindow 成为工具窗口:

this.Loaded += delegate {
    WindowInteropHelper wndHelper = new WindowInteropHelper(this);
    int exStyle = (int)WinRT.GetWindowLong(wndHelper.Handle, (int)WinRT.GetWindowLongFields.GWL_EXSTYLE);
    exStyle |= (int)WinRT.ExtendedWindowStyles.WS_EX_TOOLWINDOW;
    WinRT.SetWindowLong(wndHelper.Handle, (int)WinRT.GetWindowLongFields.GWL_EXSTYLE, (IntPtr)exStyle);
};

我们仍然会遇到一些问题 - 当您将鼠标悬停在 GlowWindow 上并左键单击时,它将被激活并获得焦点,这意味着它将与主窗口重叠,如下所示:

为了防止这种情况,只需抓住Activated边框事件并将主窗口带到前台。

你应该怎么做?

我建议不要尝试这个 - 我花了大约一个月的时间才达到我想要的效果,但仍然存在一些问题,因此我会采用像 Office 2013 那样的方法 - 彩色边框和 DWM API 调用的常见阴影 -没有别的,但看起来仍然不错。


(1) I have just edited some files to enable the border around the window which is disabled on Window 8 for me. Furthermore I have manipulated the Padding of the title bar such that it doesn't look that sqeezed inplace and lastly I have change the All-Caps property to mimic Visual Studio's way of rendering the title. So far the MahApps.Metro is a better way of drawing the main window as it even supports AeroSnap I couldn't implement with usual P/Invoke calls.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WPF无边框窗口带阴影VS2012风格 的相关文章

  • 在 C# 中按元素相乘数组具有意想不到的性能

    我想找到按元素相乘两个数组的最佳方法 这是更广泛项目的一部分 其中性能而不是唯一的考虑因素 我今天开始用 C Linqpad 编写一些函数 因此它还没有以任何方式进行优化 下面代码的输出如下 Environment ProcessorCou
  • 使用 Enumerable.OfType() 或 LINQ 查找特定类型的所有子控件

    Existed MyControl1 Controls OfType
  • 更改 Qt OpenGL 窗口示例以使用 OpenGL 3.3

    我正在尝试更改 Qt OpenGL 示例以使用更现代的 opengl 版本 330 似乎合适 所以我做了 在 main cpp 上设置版本和配置文件 设置着色器版本 更改着色器以使用统一 它现在构建没有任何错误 但我只看到一个空白窗口 我错
  • 在 Xamarin 中隐藏软键盘

    如何隐藏软键盘以便在聚焦时显示Entry在 Xamarin forms 便携式表单项目中 我假设我们必须为此编写特定于平台的渲染器 但以下内容不起作用 我创建自己的条目子类 public class MyExtendedEntry Entr
  • VS 程序在调试模式下崩溃,但在发布模式下不崩溃?

    我正在 VS 2012 中运行以下程序来尝试 Thrust 函数查找 include cuda runtime h include device launch parameters h include
  • 防止 boost::asio::io_context 在空轮询调用时停止

    此代码调用发布的句柄 boost asio io context ioc boost asio post ioc std cout lt lt lol lt lt std endl ioc poll 而这并没有 boost asio io
  • 与 Qt 项目的静态链接

    我有一个在 Visual Studio 2010 Professional 中构建的 Qt 项目 但是 当我运行它 在调试或发布模式下 时 它会要求一些 Qt dll 如果我提供 dll 并将它们放入 System32 中 它就可以工作 但
  • 单例模式和 std::unique_ptr

    std unique ptr唯一地控制它指向的对象 因此不使用引用计数 单例确保利用引用计数只能创建一个对象 那么会std unique ptr与单例执行相同 单例确保只有一个实例属于一种类型 A unique ptr确保只有一个智能指针到
  • 如何从文本文件读取整数到数组

    这就是我想做的 我对此有些不满 但我希望你能容忍我 这对我来说是一个非常新的概念 1 在我的程序中 我希望创建一个包含 50 个整数的数组来保存来自文件的数据 我的程序必须获取用户的文档文件夹的路径 2 文件的名称为 grades txt
  • C++ php 和静态库

    我创建了一个library a 其中包含 cpp 和 h 文件 其中包含很多类 嵌套类和方法 我想在 php 示例中包含这个静态库并尝试使用它 我想提一下 我是 php 新手 我已经在 test cpp 文件中测试了我的 libray a
  • AES 输出是否小于输入?

    我想加密一个字符串并将其嵌入到 URL 中 因此我想确保加密的输出不大于输入 AES 是可行的方法吗 不可能创建任何始终会创建比输入更小的输出的算法 但可以将任何输出反转回输入 如果您允许 不大于输入 那么基本上您只是在谈论同构算法alwa
  • 无法在内存位置找到异常源:cudaError_enum

    我正在尝试确定 Microsoft C 异常的来源 test fft exe 中 0x770ab9bc 处的第一次机会异常 Microsoft C 异常 内存位置 0x016cf234 处的 cudaError enum 我的构建环境是 I
  • 如何分析组合的 python 和 c 代码

    我有一个由多个 python 脚本组成的应用程序 其中一些脚本正在调用 C 代码 该应用程序现在的运行速度比以前慢得多 因此我想对其进行分析以查看问题所在 是否有工具 软件包或只是一种分析此类应用程序的方法 有一个工具可以将 python
  • 如何在c的case语句中使用省略号?

    CASE expr no commas ELLIPSIS expr no commas 我在c的语法规则中看到了这样的规则 但是当我尝试重现它时 int test float i switch i case 1 3 printf hi 它失
  • IEnumerable.Except 不起作用,那么我该怎么办?

    我有一个 linq to sql 数据库 非常简单 我们有 3 个表 项目和用户 有一个名为 User Projects 的连接表将它们连接在一起 我已经有了一个获得的工作方法IEnumberable
  • C++ Streambuf 方法可以抛出异常吗?

    我正在尝试找到一种方法来获取读取或写入流的字符数 即使存在错误并且读 写结束时间较短 该方法也是可靠的 我正在做这样的事情 return stream rdbuf gt sputn buffer buffer size 但如果streamb
  • C++0x中disable_if在哪里?

    Boost 两者都有enable if and disable if 但 C 0x 似乎缺少后者 为什么它被排除在外 C 0x 中是否有元编程工具允许我构建disable if按照enable if 哦 我刚刚注意到std enable i
  • QFileDialog::getSaveFileName 和默认的 selectedFilter

    我有 getSaveFileName 和一些过滤器 我希望当用户打开 保存 对话框时选择其中之一 Qt 文档说明如下 可以通过将 selectedFilter 设置为所需的值来选择默认过滤器 我尝试以下变体 QString selFilte
  • ASP.NET Core MVC 视图组件搜索路径

    在此处的文档中 https learn microsoft com en us aspnet core mvc views view components view aspnetcore 2 2 https learn microsoft
  • Java 和/C++ 在多线程方面的差异

    我读过一些提示 多线程实现很大程度上取决于您正在使用的目标操作系统 操作系统最终提供了多线程能力 比如Linux有POSIX标准实现 而windows32有另一种方式 但我想知道编程语言水平的主要不同 C似乎为同步提供了更多选择 例如互斥锁

随机推荐