Reputation: 87
I am showing a simple window with animation (using timers).
Here's a sample code i am using. When the window is being shown, it flickers a lot from right side. Although during hiding, there is no flicker. Also, if i remove the WS_POPUP style, there is no flickering.
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
static TCHAR szWindowClass[] = _T("win32app");
HWND main_wnd_ = 0;
DWORD timer_id = 1000;
DWORD timer_id_2 = 1001;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL
register_main_window_class(HINSTANCE hinstance) {
WNDCLASSEX wcx;
wcx.cbSize = sizeof(wcx);
wcx.style = CS_HREDRAW | CS_VREDRAW;
wcx.lpfnWndProc = WndProc;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hinstance;
wcx.hIcon = 0;
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground = CreateSolidBrush(0xFF0000);
wcx.lpszMenuName = 0;
wcx.lpszClassName = _T("MainWndClass");
wcx.hIconSm = 0;
return RegisterClassEx(&wcx);
}
void CALLBACK show(HWND hwnd, UINT msg, UINT id, DWORD time) {
RECT r = { 0 };
::GetWindowRect(hwnd, &r);
if (r.left > 400) {
SetWindowPos(hwnd, 0, r.left - 10, r.top, r.right - r.left + 10, r.bottom - r.top, SWP_NOZORDER);
} else {
KillTimer(hwnd, timer_id);
}
}
void CALLBACK hide(HWND hwnd, UINT msg, UINT id, DWORD time) {
RECT r = { 0 };
::GetWindowRect(hwnd, &r);
if (r.left < 1500) {
SetWindowPos(hwnd, 0, r.left + 10, r.top, r.right - r.left - 10, r.bottom - r.top, SWP_NOZORDER);
} else {
DestroyWindow(hwnd);
KillTimer(hwnd, timer_id_2);
}
}
BOOL
create_main_window(HINSTANCE hinstance) {
main_wnd_ = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
_T("MainWndClass"), _T(""),
WS_VISIBLE | WS_POPUP,
1500, 800, 0, 200,
0, 0, hinstance, 0);
if (!main_wnd_) {
return FALSE;
}
ShowWindow(main_wnd_, SW_SHOW);
UpdateWindow(main_wnd_);
SetTimer(main_wnd_, timer_id, 10, (TIMERPROC)show);
return TRUE;
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
int x = 0;
if (!register_main_window_class(hInstance)) {
x = 0;
}
if (!create_main_window(hInstance)) {
x = 0;
}
MSG msg;
BOOL result;
while ((result = GetMessage(&msg, 0, 0, 0)) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 1;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:
SetTimer(main_wnd_, timer_id_2, 10, (TIMERPROC)hide);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
Upvotes: 1
Views: 677
Reputation: 13067
This is a serious problem in the Win32 API. And there is no easy solution to it.
What you can try is catch the toplevels WM_ENTERSIZEMOVE and draw the controls into a bitmap using WM_PRINT method, then use the (scaled) bitmap and redraw the dialog controls into another bitmap swapping the two afterwards.
Adding this double buffering is a lot of work and doesn't work if WM_PRINT doesn't work on some 3rd party client control (like all MFC Feature Pack).
But when you have done it it works fine. You also need this for all other fast GUI animations that makes MacOSX so nice.
Upvotes: 1