在 .NET 3.5 中使用 WindowChrome 创建无边框窗口

关于使用无边框窗口并自绘控件来使 GUI 更符合个性化需求已经被讨论了太多,在.NET 4.5 中借助 WindowChrome 来完成这一需求的范例也已经相当成熟,比如著名开源音乐播放器 Dopamine 就是一例。但如果在某些特殊的要求下,只能使用.NET 3.5 的情况下,很多基础部件都是缺失的,抛去 WindowStyle="None" 这种问题比较多的解决方法,最终比较好的方式是移植微软在.NET 4.5 中为我们写好的库。

那从哪里移植呢?显然 WPF 框架并不开源,但这不妨碍我们能读到 WPF 的源码。令人高兴的是,有人已经为我们反编译了 Microsoft.Windows.Shell,在此处 WPF-Shell-Integration-Library。但是立刻就能发现当它被编译到.NET 3.5 时,工作区的可视区域会发生计算错误,窗口的一部分会被裁掉(而编译到.NET 4.0 时则不会发生),如果去读里面的 WindowChrome.cs,关于布局的计算其实是非常麻烦的,并且涉及到了相当多的 Win32 部分。当然了,我们有理由相信巨硬在.NET 4.0 修复了相关的错误,但是源代码受限制并不能编译到.NET 4.0 上,如何解决呢?

显然去反编译 PresentationFramework.dll@4.0.0.0 是最迅速的,借助 dnSpy,可以轻易地反编译出其中的 WindowChrome,并替换掉 WPF-Shell-Integration-Library 中的 WindowChrome.cs 与 WindowChromeWorker.cs 这两个文件,之后再配合 WPFControls 就能实现在.NET 3.5 中创建无边框窗口。
dotnet35_with_windowchrome

在反编译的 WindowChromeWorker.cs 中,可以看到_FixupFrameworkIssues、_FixupWindows7Issues、_FixupRestoreBounds 等方法,说明在 Windows7 与 WPF4 及更高版本中,确实存在布局的问题,并且巨硬也确实修复了。