win32c++弹出窗口在以编程方式调整大小时闪烁很多

win32 c++ popup window flickers a lot while resizing programmatically

本文关键字:调整 小时 闪烁 方式 编程 窗口 win32c++      更新时间:2023-10-16

我正在展示一个带有动画的简单窗口(使用计时器)。

这是我正在使用的示例代码。当窗口显示时,它从右侧闪烁很多。虽然在隐藏期间,没有闪烁。此外,如果我删除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);
}

这是Win32 API中的一个严重问题。没有简单的解决办法。

你可以尝试的是捕获顶部WM_ENTERSIZEMOVE并使用WM_PRINT方法将控件绘制成位图,然后使用(缩放)位图并将对话框控件重新绘制成另一个位图,然后交换两者。

添加这种双缓冲是很多工作,如果WM_PRINT不工作在一些第三方客户端控件(如所有MFC功能包)。

但是当你这样做的时候,它工作得很好。你也需要它为所有其他快速GUI动画,使MacOSX如此漂亮。