当前位置: 首页 > news >正文

解决 WPF 嵌套的子窗口在改变窗口大小的时候闪烁的问题

因为 Win32 的窗口句柄是可以跨进程传递的,所以可以用来实现跨进程 UI。不过,本文不会谈论跨进程 UI 的具体实现,只会提及其实现中的一个重要缓解,使用子窗口的方式。

你有可能在使用子窗口之后,发现拖拽改变窗口大小的时候,子窗口中的内容不断闪烁。如果你也遇到了这样的问题,那么正好可以阅读本文来解决。


本文内容

    • 问题
    • 解决
    • 原因

问题

你可以看一下下面的这张动图,感受一下窗口的闪烁:

窗口闪烁

实际上在拖动窗口的时候,是一直都在闪的,只是每次闪烁都非常快,截取 gif 的时候截不到。

如果你希望实际跑一跑项目看看,可以使用下面的代码:

  • walterlv.demo/Walterlv.Demo.HwndWrapping/Walterlv.Demo.HwndWrapping at a88f81477756af2913349970ba2f0bbab01aaf88 · walterlv/walterlv.demo

我特地提取了一个提交下的代码,如果你要尝试,不能使用 master 分支,因为 master 分支修复了闪烁的问题。

后来使用 CreateWindowEx 创建了一个纯 Win32 窗口,这种闪烁现象更容易被截图:

Win32 窗口闪烁
Win32 窗口闪烁 - 动图

解决

    public class HwndWrapper : HwndHost
    {
        protected override HandleRef BuildWindowCore(HandleRef hwndParent)
        {
            const int WS_CHILD = 0x40000000;
++          const int WS_CLIPCHILDREN = 0x02000000;
            var owner = ((HwndSource)PresentationSource.FromVisual(this)).Handle;

            var parameters = new HwndSourceParameters("demo")
            {
                ParentWindow = owner,
--              WindowStyle = (int)(WS_CHILD),
++              WindowStyle = (int)(WS_CHILD | WS_CLIPCHILDREN),
            };
            var source = new HwndSource(parameters);
            source.RootVisual = new ChildPage();
            return new HandleRef(this, source.Handle);
        }

        protected override void DestroyWindowCore(HandleRef hwnd)
        {
        }
    }

原因

正在探索……


参考资料

  • wpf - Custom dwm drawn window frame flickers on resizing if the window contains a HwndHost element - Stack Overflow
  • WPF多进程UI探索(Like Chrome) - 简书
  • 关于WS_CLIPCHILDREN和WS_CLIPSIBLINGS的理解(个人认为还是相当全面的) - helloj2ee - 博客园

我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • WPF 的 Application.Current.Dispatcher 中,为什么 Current 可能为 null
  • WPF 的 Application.Current.Dispatcher 中,Dispatcher 属性一定不会为 null
  • 提高使用 Visual Studio 开发效率的键盘快捷键
  • WPF 不要给 Window 类设置变换矩阵(分析篇):System.InvalidOperationException: 转换不可逆。
  • WPF 不要给 Window 类设置变换矩阵(应用篇)
  • git fetch 失败,因为 unable to resolve reference 'refs/remotes/origin/xxx': reference broken
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  • 发现电脑屏幕总是不自动关闭?看看你是否打开了这些程序……
  • 临时编写和调试 C++ 代码?用 VSCode 就够了!一分钟搭好 C++ 调试环境
  • WPF 制作高性能的透明背景异形窗口(使用 WindowChrome 而不要使用 AllowsTransparency=True)
  • 在 WPF 中获取一个依赖对象的所有依赖项属性
  • 如何在 WPF 中获取所有已经显式赋过值的依赖项属性
  • .NET 设计一套高性能的弱事件机制
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地定义和使用弱事件
  • 3.7、@ResponseBody 和 @RestController
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • android 一些 utils
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • Apache的基本使用
  • CentOS 7 修改主机名
  • CSS 提示工具(Tooltip)
  • EOS是什么
  • fetch 从初识到应用
  • Iterator 和 for...of 循环
  • Java|序列化异常StreamCorruptedException的解决方法
  • Java程序员幽默爆笑锦集
  • Java多线程(4):使用线程池执行定时任务
  • js作用域和this的理解
  • Sublime Text 2/3 绑定Eclipse快捷键
  • windows下使用nginx调试简介
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 规范化安全开发 KOA 手脚架
  • 猴子数据域名防封接口降低小说被封的风险
  • 如何利用MongoDB打造TOP榜小程序
  • 通过几道题目学习二叉搜索树
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 新书推荐|Windows黑客编程技术详解
  • 正则与JS中的正则
  • 浅谈sql中的in与not in,exists与not exists的区别
  • (16)Reactor的测试——响应式Spring的道法术器
  • (Demo分享)利用原生JavaScript-随机数-实现做一个烟花案例
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (安卓)跳转应用市场APP详情页的方式
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (二)WCF的Binding模型
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)