Why is my window losing its HTMEME when I call SetWindowLongPtr(GWL_STYLE) on it?

294 Views Asked by At

I'm coding a custom Win32 UI control that I want to incorporate visual themes in. I load themes in its WM_NCCREATE as such:

case WM_NCCREATE:
{
    HTHEME hTheme = ::OpenThemeData(hWnd, L"EDIT");
    assert(hTheme);
    assert(::GetWindowTheme(hWnd) != 0);

}
return 1;

and then release them when control is destroyed:

case WM_DESTROY:
{
    HTHEME hTheme = ::GetWindowTheme(hWnd);
    assert(hTheme);
    if(::CloseThemeData(hTheme) != S_OK)
    {
        assert(NULL);
    }
}
break;

This works well, until someone tries to change that control's styles. The following call (just by itself without even changing any styles):

::SetWindowLongPtr(hChildWnd, GWL_STYLE, dwStyle);

will make GetWindowTheme on hChildWnd return NULL.

So, is it a bug or a feature?

PS. To make a reproducible Win32 example I had to adjust the stock Win32 solution from the VS 2017. (Here is its full source code.) The way it works is this: in it I create a small child control (shown in gray below) that has theme in question:

enter image description here

Then when you click on the white area of the main window, I try to change its styles and its theme disappears:

enter image description here

To see the full Win32 code for that project, I also posted it on PasteBin.

1

There are 1 best solutions below

0
On

According to Window Styles document:

"After the window has been created, these styles cannot be modified, except as noted."

Because this is not permitted, the theme engine does not always check for changed styles and in some circumstances will draw the caption based on old data. And the only guaranteed and supportable solution is for the application to destroy the window and recreate it with the new styles rather than trying to change them on the fly.

A similar discussion can be found: http://social.msdn.microsoft.com/Forums/en/windowscompatibility/thread/7b5ef777-ff0d-4f15-afed-5588f93f0e23