先看效果图:

大致思路是:通过反射获取Popup内部的原生窗口句柄,然后通过前文已经实现的WindowMaterial类来应用窗口特效;对于ToolTip,为了保持其易用性,我使用了附加属性+全局样式的方式来实现,ToolTip也是一个特殊的Popup.
前文链接:WPF 模拟UWP原生窗口样式——亚克力|云母材质、自定义标题栏样式、原生DWM动画 (附我封装好的类)
本文的Demo:

TwilightLemon/WindowEffectTest: 测试win10/11的模糊效果 (github.com)

一、获取原生窗口句柄

通过查阅.NET源码得知,Popup内部通过一个类型为PopupSecurityHelper的私有字段_secHelper来管理窗口hWnd,并且在创建完成之时会触发Popup.Opened事件。
通过反射来获取窗口句柄:

const BindingFlags privateInstanceFlag = BindingFlags.NonPublic | BindingFlags.Instance;
public static IntPtr GetNativeWindowHwnd(this Popup popup)
{
//获取Popup内部的_secHelper字段Info
var field = typeof(Popup).GetField("_secHelper", privateInstanceFlag);
if (field != null)
{
//获取popup的_secHelper字段值
if (field.GetValue(popup) is { } _secHelper)
{
//获取_secHelper的Handle属性Info
if (_secHelper.GetType().GetProperty("Handle", privateInstanceFlag) is { } prop)
{
if (prop.GetValue(_secHelper) is IntPtr handle)
{
//返回句柄
return handle;
}
}
}
}
//未找到
return IntPtr.Zero;
}

同样地,能在ToolTip内部找到私有字段_parentPopup

public static IntPtr GetNativeWindowHwnd(this ToolTip tip)
{
var field=tip.GetType().GetField("_parentPopup", privateInstanceFlag);
if (field != null)
{
if(field.GetValue(tip) is Popup{ } popup)
{
return popup.GetNativeWindowHwnd();
}
}
return IntPtr.Zero;
}

二、应用WindowMaterial特效

有了窗口句柄那么一切都好办了,直接调用我封装好的WindowMaterial类,如果你想了解更多请查看前文。

public static void SetPopupWindowMaterial(IntPtr hwnd,Color compositionColor,
MaterialApis.WindowCorner corner= MaterialApis.WindowCorner.Round)
{
if (hwnd != IntPtr.Zero)
{
int hexColor = compositionColor.ToHexColor();
var hwndSource = HwndSource.FromHwnd(hwnd);
//----
MaterialApis.SetWindowProperties(hwndSource, 0);
MaterialApis.SetWindowComposition(hwnd, true, hexColor);
//----
MaterialApis.SetWindowCorner(hwnd, corner);
}
}

根据微软的设计规范,这里默认对普通Popup使用圆角,对ToolTip使用小圆角,使用亚克力材质并附加compositionColor。
在github中获取完整的WindowMaterial.cs,我可能会不定期地更新它:WindowEffectTest/WindowMaterial.cs at master · TwilightLemon/WindowEffectTest (github.com)

如果你想使用Mica或MicaAlt等材质则将上面框起来的代码替换为:

MaterialApis.SetWindowProperties(hwndSource, -1);
MaterialApis.SetBackDropType(hwnd, MaterialType.Mica);
MaterialApis.SetDarkMode(hwnd, isDarkMode: true);

三、没错我又封装了一个即开即用的类

在Demo中查看封装好的类:WindowEffectTest/FluentPopup.cs at master · TwilightLemon/WindowEffectTest (github.com)

使用FluentPopup

<local:FluentPopup x:Name="testPopup"
StaysOpen="False"
Placement="Mouse"
Background="{DynamicResource PopupWindowBackground}">
<Grid Height="120" Width="180">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
nihao
</TextBlock>
</Grid>
</local:FluentPopup>

其中,Background属性是我自定义的一个依赖属性,只允许使用SolidColorBrush,用于设置亚克力特效的CompositionColor。
如果你希望像Demo中那样让Popup失焦自动关闭,可以设置StaysOpenFalse,在后台打开Popup时使用:

private async void ShowPopupBtn_Click(object sender, RoutedEventArgs e)
{
await Task.Yield();
testPopup.IsOpen = true;
}

关于为什么要加上await Task.Tield(),可以看看吕毅大佬的文章:一点点从坑里爬出来:如何正确打开 WPF 里的 Popup? - Walterlv

在全局内使用FluentToolTip

我自定义了一个附加属性FluentTooltip.UseFluentStyle,你只需要在App.xaml中设置即可全局生效: 这里的PopupWindowBackgroundForeColor是我自定义的颜色资源,你可以根据自己的需要来设置。
同样地Background仅支持SolidColorBrush

<Style TargetType="{x:Type ToolTip}">
<Setter Property="local:FluentTooltip.UseFluentStyle"
Value="True" />
<Setter Property="Background"
Value="{DynamicResource PopupWindowBackground}" />
<Setter Property="Foreground"
Value="{DynamicResource ForeColor}" />
</Style>

这样你就可以方便地创建一个Fluent风格的ToolTip了:

<Button
ToolTip="xxxxx"
/>

参考链接

Popup.cs at Dotnet Source

ToolTip.cs at Dotnet Source

一点点从坑里爬出来:如何正确打开 WPF 里的 Popup? - Walterlv

WPF 模拟UWP原生窗口样式——亚克力|云母材质、自定义标题栏样式、原生DWM动画 (附我封装好的类) - TwilightLemon

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名TwilightLemon(https://blog.twlmgatito.cn),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

文章及其代码仓库可能不时更新,查看原文:WPF中为Popup和ToolTip使用WindowMaterial特效 win10/win11 - Twlm's Blog (twlmgatito.cn)

WPF中为Popup和ToolTip使用WindowMaterial特效 win10/win11的更多相关文章

  1. 关于WPF中Popup控件的小记

    在wpf开发中,常需要在鼠标位置处弹出一个“提示框”(在此就以“提示框”代替吧),通过“提示框”进行信息提示或者数据操作,如果仅仅是提示作用,使用ToolTip控件已经足够,但是有些是需要在弹出的框中 ...

  2. WPF中Popup控件在Win7以及Win10等中的对齐点方式不一样的解决方案 - 简书

    原文:WPF中Popup控件在Win7以及Win10等中的对齐点方式不一样的解决方案 - 简书 最近项目中使用弹出控件Popup,发现弹出框的对齐方式在不同的系统中存在不同(Popup在win10上是 ...

  3. 关于wpf中popup跟随鼠标移动显示

    最近在做一个画图工具,里面有一个功能是需要实现,当鼠标移动的时候在,鼠标的旁边显示坐标信息. 第一反应是想到了tooltip,但是tooltip有许多的限制,查询资料的过程中看到了popup,popu ...

  4. 用WPF实现在ListView中的鼠标悬停Tooltip显示

    原文:用WPF实现在ListView中的鼠标悬停Tooltip显示 一.具体需求描述 在WPF下实现,当鼠标悬停在ListView中的某一元素的时候能弹出一个ToolTip以显示需要的信息. 二.代码 ...

  5. WPF中的事件列表 .

    以下是WPF中的常见事件汇总表(按字母排序),翻译不见得准确,但希望对你有用. 事件 描述 Annotation.AnchorChanged 新增.移除或修改 Anchor 元素时发生. Annota ...

  6. 【转】WPF 给DataGridTextColumn统一加上ToolTip

    源地址:http://dongguojun.iteye.com/blog/1671963 我发现WPF中DataGridTextColumn直接设置它的ToolTipService.Tooltip并不 ...

  7. WPF中PasswordBox控件无法绑定Password属性解决办法

    在WPF中,默认的Password控件的Password属性是不允许为之绑定的,下面是一个解决绑定Password的方法的代码: 1.前台代码 <Window x:Class="Pas ...

  8. WPF中的触发器简单总结

    原文 http://blog.sina.com.cn/s/blog_5f2ed5cb0100p3ab.html 触发器,从某种意义上来说它也是一种Style,因为它包含有一个Setter集合,并根据一 ...

  9. WPF中TreeView控件的使用案例

    WPF总体来说还是比较方便的,其中变化最大的主要是Listview和Treeview控件,而且TreeView似乎在WPF是一个备受指责的控件,很多人说他不好用.我这个demo主要是在wpf中使用Tr ...

  10. WPF中自定义MarkupExtension

    在介绍这一篇文章之前,我们首先来回顾一下WPF中的一些基础的概念,首先当然是XAML了,XAML全称是Extensible Application Markup Language (可扩展应用程序标记 ...

随机推荐

  1. Blazor Web 应用如何实现Auto模式

    本文介绍Blazor Web应用Auto交互呈现模式的实现方案,如下示例是基于 Known 框架来实现的,该解决方案共有3个项目,具体实现步骤如下: 1. 前后端共用项目 创建前后端共用类库项目Sam ...

  2. pve 安装配置问题集锦

    官网:https://www.proxmox.com/en/ 下载:https://www.proxmox.com/en/downloads 安装:https://pve.proxmox.com/wi ...

  3. 人形机器人(humanoid)(双足机器人、四足机器人) —— 硬件测试的方法

    硬件测试的方法: 硬件的稳定性.鲁棒性.为机器人设定好固有的执行策略,然后长时间的让机器人重复执行这些既定好的动作.该种测试方法主要测试硬件的设计是否合理,硬件在长时间的运行中是否可以稳定运行而不是出 ...

  4. 新手入门深度学习:在不使用Google的情况下如何在国内获得免费的算力 —— 算力共享,驱动人工智能创新的新引擎

    分享链接地址: 算力获新生 | 算力共享,驱动人工智能创新的新引擎

  5. 利用强化学习算法解释人类脑对高维状态的抽象表示:how humans can map high-dimensional sensory inputs in actions

    论文: <Using deep reinforcement learning to reveal how the brain encodes abstract state-space repre ...

  6. 【转载】 windows python3 安装 openai gym 的 atari_py

    版权声明:本文为CSDN博主「dai1056318647」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/dai ...

  7. 【转载】 推荐算法之Thompson(汤普森)采样

    原文地址: https://www.cnblogs.com/gczr/p/11220187.html ------------------------------------------------- ...

  8. 快速基于 ClickHouse + Grafana 搭建可观测性解决方案 - 日志篇(ClickHouse 官方博客)

    引言 作为一款高性能的 OLAP 数据库,ClickHouse 被用于多种应用场景,包括 时间序列(time series)数据的实时分析.其多样化的应用场景推动了大量分析函数的发展,这些函数有助于查 ...

  9. BMC Genomics | 综合代谢组学和转录组学分析揭示了菊花黄酮和咖啡酰奎宁酸的生物合成机制

    杭白菊是一种流行的药用和食用植物,主要通过黄酮类和咖啡酰奎宁酸(CQAs)的存在发挥其生物活性.然而,菊花头状花序中黄酮和CQA生物合成的调控机制尚不清楚. 本研究采用高效液相色谱法测定了菊花头状花序 ...

  10. PowerShell快速修改多个文件的名称

      本文介绍基于PowerShell语言,对文件夹中全部文件的名称加以批量替换.修改的方法.   在之前的文章中,我们介绍了基于Python语言,批量修改大量文件的名称的方法.当时我们修改文件名的需求 ...