我正在编写一个自定义的Win32 UI控件,我希望将视觉主题合并到其中。我在其WM_NCCREATE
中加载主题:
case WM_NCCREATE:
{
HTHEME hTheme = ::OpenThemeData(hWnd, L"EDIT");
assert(hTheme);
assert(::GetWindowTheme(hWnd) != 0);
}
return 1;
然后在控制被销毁时释放它们:
case WM_DESTROY:
{
HTHEME hTheme = ::GetWindowTheme(hWnd);
assert(hTheme);
if(::CloseThemeData(hTheme) != S_OK)
{
assert(NULL);
}
}
break;
这很有效,直到有人试图改变该控件的样式。以下调用(只是自己没有更改任何样式):
::SetWindowLongPtr(hChildWnd, GWL_STYLE, dwStyle);
会使GetWindowTheme
上的hChildWnd
返回NULL。
那么,它是一个bug还是一个功能?
PS。为了制作一个可重现的Win32示例,我必须从VS 2017调整股票Win32解决方案。(Here是它的完整源代码。)它的工作方式是:在其中我创建一个小的子控件(如下面灰色所示)有问题的主题:
然后,当您单击主窗口的白色区域时,我尝试更改其样式,其主题消失:
要查看该项目的完整Win32代码,我还要posted it on PasteBin。
根据Window Styles文件:
“创建窗口后,除非另有说明,否则无法修改这些样式。”
因为这是不允许的,所以主题引擎并不总是检查更改的样式,并且在某些情况下将根据旧数据绘制标题。唯一有保证和可支持的解决方案是应用程序破坏窗口并使用新样式重新创建它,而不是试图动态更改它们。