winapi — всплывающее окно win32 c ++ часто мерцает при программном изменении размера

Я показываю простое окно с анимацией (с использованием таймеров).

Вот пример кода, который я использую. Когда окно показывается, оно сильно мигает с правой стороны. Хотя во время сокрытия мерцания нет. Кроме того, если я удаляю стиль WS_POPUP, мерцание отсутствует.

#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);
}

1

Решение

Это серьезная проблема в Win32 API. И нет простого решения этого.

То, что вы можете попробовать, это перехватить верхний уровень WM_ENTERSIZEMOVE и нарисовать элементы управления в растровое изображение с помощью метода WM_PRINT, затем использовать (масштабированное) растровое изображение и перерисовать диалоговые элементы управления в другое растровое изображение, поменяв их местами впоследствии.

Добавление этой двойной буферизации — большая работа, которая не работает, если WM_PRINT не работает на каком-либо стороннем клиентском элементе управления (как и во всех пакетах MFC Feature Pack).

Но когда ты это сделал, все работает нормально. Это также необходимо для всех других быстрых анимаций с графическим интерфейсом, которые делают MacOSX таким приятным.

1

Другие решения


По вопросам рекламы [email protected]