Problem
The
AnimateWindow()
API with the
AW_BLEND
parameter
is supposed to fade in and out windows smoothly. Basically, it has two drawbacks:
- Text and ListView controls (and several others) aren't rendered
correctly during fade-in.
- You cannot specify a translucency for the window, i.e., after
the animation is over, the window is opaque.
Clicking 'No' in the sample project demonstrates both problems.
Workaround?
There seemed to be a simple workaround for this: Adding the
WS_EX_LAYERED
extended style to the window and calling
SetLayeredWindowAttributes()
with the desired alpha value, as
described in the MSDN Library and in various other sources.
Unfortunately, this didn't work either, at least on my XP Pro system. The code
produced a very nasty flickering: the window area was
initially black.
Solution
The following code shows how to fade in a dialog to a predefinded
translucency without flickering:
INT_PTR CALLBACK DialogProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
RECT rcDesktop;
RECT rcMe;
BYTE bTranslucency;
const DWORD ANIMATION_MILLIS = 200;
const BYTE TRANSLUCENCY = 192;
const BYTE TRANSLUCENCY_STEP = 16;
const DWORD TRANSLUCENCY_TIMEOUT
= TRANSLUCENCY_STEP * ANIMATION_MILLIS / TRANSLUCENCY;
switch (uMsg) {
case WM_INITDIALOG:
::SetWindowLong(hwndDlg, GWL_EXSTYLE,
::GetWindowLong(hwndDlg, GWL_EXSTYLE) | WS_EX_LAYERED);
::SetLayeredWindowAttributes(hwndDlg, 0, 0, LWA_ALPHA);
::ShowWindow(hwndDlg, SW_SHOW);
::RedrawWindow(hwndDlg, NULL, NULL, RDW_UPDATENOW);
for (bTranslucency = 0; bTranslucency < TRANSLUCENCY;
bTranslucency+=TRANSLUCENCY_STEP) {
::SetLayeredWindowAttributes(hwndDlg, 0, bTranslucency, LWA_ALPHA);
::Sleep(TRANSLUCENCY_TIMEOUT);
}
::SetLayeredWindowAttributes(hwndDlg, 0, bTranslucency, LWA_ALPHA);
break;
}
return 0;
}
Note that the call to
ShowWindow()
is usually done by the
CreateDialogXXX()
functions if the dialog template has the
WS_VISIBLE
style set. For our purposes, we have to do it right
here in response to the
WM_INITDIALOG
message.