MSDN - Windows 窗体绘制的几种类型

沉默年代

  • hWnd:handle of window,在 Win32 GUI 中每一个控件以及窗体都是独立绘制,因此都具有各自的hWnd。一个 Win32 窗体就是层层嵌套的 hWnd。
  • Win32 GUI:使用底层的 Windows API 来控制窗体使用 GDI 绘制,比如直接使用RegisterWindowClassCreateWindow
  • MFC、WinForm:MFC是基于 Win32 GUI API 的封装,提升开发效率,但是最终创建出来的窗体还是和前者一样,基于hWnd。WinForm 是 MFC 的封装,加上 .net 的特性。

一句话总结:如果现在让我选,简单的窗体可以直接 Win32 GUI 百来行代码搞定,还会显得有扫地僧般的深不可测和闲情逸致。当然也可以无缝切换道 MFC,前提是得安装 MFC 相关的 SDK。

DirectX 年代

大一的时候我曾经想过,如果用那些编写游戏的高级图形工具来创建桌面应用(比如 U3D),能写出多么酷炫的界面!事实上早在十几年前,微软的天才工程师们就已经把这个想法付诸实现了。

D3D9

时间回溯到 Vista 版本的时候,Windows GUI 程序突然发生了翻天覆地的变化。别提当时买一张盗版碟,从 XP 升级上来的时候有多震撼了,例如 Aero 特效带来了毛玻璃效果,这些要归功于 DirectX 的“上位”——微软提出了一套新的基于 DX 的桌面开发解决方案:WPF。

在 WPF 中,每一个应用程序的窗体都是一个离屏 DirectX Surface,也就是说,先把图形渲染到内存里。然后,系统使用 DWM(Direct Window Manager)来管理各个渲染出来的窗体界面,并根据层级来决定谁绘制出来。每一个 WPF 窗体只有一个hWnd,窗体内部是一个整体的 DX 内容。

DWM 使用的是 DirectX 9 版本,因此 WPF 饱受诟病的一个大问题就是,一直没有一个很好的办法托管一个 DX 渲染的内容在窗体中。

D3D11

到了 Windows 8 的时候,鲍尔默提出要进军全平台,一次开发,多端 Debug 使用,也即 UWP 应用。这些应用都运行在新的 Windows Runtime(WinRT)下,微软又了给这些应用一套新的底层——D3D11/12。

UWP 应用仍然使用 XAML 进行界面设计,但是在 WinRT 内部编程已经无法触及 Windows API,所以 hWnd 也就此失传了。但是更高级图形接口的使用也带来了很多好处,比如再一次惊艳世人的 Fluent Design 使用光效和亚克力材质的配合,让人看到了界面设计的全新可能。

文艺复兴

不要以为传统的基于 Win32 或者 WPF 的程序就要逐渐退出历史长河了。微软在最新的开发者大会上给出了下一步的计划,看起来UWP在传统桌面端终究是个臭弟弟。

tRrlZj.png

如果我想在一个 Win32 GUI 程序中绘制 D3D11 内容怎么办?总的来说有两种方案:

  1. DirectX 支持使用CreateSwapchainForHwnd()函数,可以直接把交换链渲染到指定的 hWnd(窗体或者控件)中。
  2. 为了支持后来的高级图形环境,微软又搞出了DirectComposition,你可以自己做一些工作来绘制内容到 hWnd 中。

对于 WPF,目前正在进行的 XAML island 就是在解决这个问题。Xaml island 意味着你可以绘制 UWP 控件到传统程序中,包括大家都想要的 Fluent Design,也包括 UWP 里面可以用的swapchanpanel,这一步包括在了上图 WinUI 3 里面。当然我最希望微软从底层(反正都是DX)出面解决 airspace 的问题,允许在 island 的上层继续绘制 WPF 的控件。