问题
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!
回答1:
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:
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:
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.
来源:https://stackoverflow.com/questions/4985056/windows-aero-glass-background-is-broken-after-hibernate-how-can-i-solve-this