Windows Aero Glass background is broken after hibernate. How can I solve this?

1.4k views Asked by At

I am developing a program in C# .net 3.5 wpf. It has to work on windows xp, windows vista and windows 7. On the newer operation systems I wantet to create the background in Aero Glass. So this is only a special design. After hibernate, after suspending or after changing windows Desings to a basic design and back to aero all the added glass is displayed completely black.

I display Glass via the GlassHelper Class (can be found with Google).

Actually I see 3 ways to solve this problem. The first is, yea to solve it. But i read somwhere, that this is a bug in the Windows Managed Code so I have no option to sovle it. Correct me, if I am wrong.

So I had the idea to close the window everytime, it is minimized and to rebuild completely, when it s used next time.

That works quite well. After hibernate the window is still displayed black, but i do not have to quit the application, i can still minimize it and maximize again.

Now I see to ways:

1) I close the window everytime, the computer suspends, hibernates or changes the design. And I open it the window again, when it is save. But how can I handle this?

2) I accept, that the window will be displayed in black, until someone minimizes it. (Not my favourite) But then I get a new Problem: The Button in The Taskbar. (Not the Tray Icon). I need it to be displayed permanently. On winxp i need it to open the window, when minimized. And especially on win7 I need it because I want to use some of the new Advantages of the Superbar! (the preview by hoovering will not be the window, it will be a static picture.)

Thank you everyone, for helping me!

3

There are 3 answers

0
Legy On BEST ANSWER

Ok, thank you everyone! But I think I found my own solution!

I handle the Messages: WM_DWMCOMPOSITIONCHANGED (0x031E) & WM_THEMECHANGED (0x031A)

and on catching one of those messages I simply assign the glass again or a new background depending on DwmIsCompositionEnabled().

Actually I have something similar to the following:

const int WM_THEMECHANGED = 0x031A;
const int WM_DWMCOMPOSITIONCHANGED = 0x031E;

private static void ApplyTheme(IntPtr hwnd)
{
    if (DwmIsCompositionEnabled())
    {
        HwndSource.FromHwnd(hwnd).CompositionTarget.BackgroundColor = Colors.Transparent;
        MARGINS margins = new MARGINS(new Thickness(-1));
        DwmExtendFrameIntoClientArea(hwnd, ref margins);
    }
    else
    {
        HwndSource.FromHwnd(hwnd).CompositionTarget.BackgroundColor = SystemColors.ActiveCaptionBrush.Color;
    }
}

private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if (msg == WM_THEMECHANGED)
    {
        ApplyTheme(hwnd);
    }
    if (msg == WM_DWMCOMPOSITIONCHANGED)
    {
        ApplyTheme(hwnd);
    }
    return IntPtr.Zero;
}

I get the hwnd.

I hook it.

HwndSource.FromHwnd(hwnd).AddHook(new HwndSourceHook(WndProc));

I make the WPF Window Background transparent, because later, in the WndProc function I will only be able to access my hwnd Background (Win32).

window.Background = Brushes.Transparent;

And now I only have to assign the style for the first time:

ApplyTheme(hwnd);

Thats it! Works perfectly for me (Win 64 Home Premium) after I disable or enable aero, switch between different aero or non-aero styles or hibernate, so it is exactly, what I was looking for. Thank you, for your great ideas!

3
Marat Khasanov On

Try to handle WM_NCCALCSIZE message and reduce client area (NCCALCSIZE_PARAMS.rgrc0) by one pixel. I'm serious. I found this solution is used in Google Chrome and it works fine for me too.

2
JLaanstra On

You may want to take a look at the WPF Shell Integration Library. I can rememver there were similar problems with that library due to a bug in the Desktop Window Manager in windows 7. The library has its source available so you can take a look how they handle it.