gpt4 book ai didi

c - 调整窗口大小时是否可以完全消除闪烁?

转载 作者:太空狗 更新时间:2023-10-29 16:53:18 25 4
gpt4 key购买 nike

通常情况下,即使使用双缓冲,在调整窗口大小时,闪烁似乎也是不可避免的。

第一步,原始窗口。

Step 1

第2步,调整了窗口大小,但还没有绘制多余的区域。

Step 2

第3步,调整窗口大小,绘制多余区域。

Step 3

是否有可能以某种方式隐藏 setp 2?我可以暂停调整大小过程直到绘画 Action 完成吗?

这是一个例子:

#include <Windows.h>
#include <windowsx.h>
#include <Uxtheme.h>

#pragma comment(lib, "Uxtheme.lib")

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL MainWindow_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct);
void MainWindow_OnDestroy(HWND hWnd);
void MainWindow_OnSize(HWND hWnd, UINT state, int cx, int cy);
void MainWindow_OnPaint(HWND hWnd);

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex = { 0 };
HWND hWnd;
MSG msg;
BOOL ret;

wcex.cbSize = sizeof(wcex);
wcex.lpfnWndProc = WindowProc;
wcex.hInstance = hInstance;
wcex.hIcon = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
wcex.hCursor = (HCURSOR)LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
wcex.lpszClassName = TEXT("MainWindow");
wcex.hIconSm = wcex.hIcon;

if (!RegisterClassEx(&wcex))
{
return 1;
}

hWnd = CreateWindow(wcex.lpszClassName, TEXT("CWin32"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hInstance, NULL);
if (!hWnd)
{
return 1;
}

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (ret == -1)
{
return 1;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
HANDLE_MSG(hWnd, WM_CREATE, MainWindow_OnCreate);
HANDLE_MSG(hWnd, WM_DESTROY, MainWindow_OnDestroy);
HANDLE_MSG(hWnd, WM_SIZE, MainWindow_OnSize);
HANDLE_MSG(hWnd, WM_PAINT, MainWindow_OnPaint);
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}

BOOL MainWindow_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
{
BufferedPaintInit();
return TRUE;
}

void MainWindow_OnDestroy(HWND hWnd)
{
BufferedPaintUnInit();
PostQuitMessage(0);
}

void MainWindow_OnSize(HWND hWnd, UINT state, int cx, int cy)
{
InvalidateRect(hWnd, NULL, FALSE);
}

void MainWindow_OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
HPAINTBUFFER hpb;
HDC hdc;

BeginPaint(hWnd, &ps);
hpb = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &hdc);

FillRect(hdc, &ps.rcPaint, GetStockBrush(DKGRAY_BRUSH));
Sleep(320); // This simulates some slow drawing actions.

EndBufferedPaint(hpb, TRUE);
EndPaint(hWnd, &ps);
}

是否可以消除闪烁?

最佳答案

当窗口在拖动操作期间更新时,操作系统必须在扩展的窗口区域中显示一些东西。如果您无法提供任何内容,那么它将显示背景,直到您提供为止。由于您没有指定任何背景,因此您会变黑。当然你应该指定一个背景画笔?只需将以下内容添加到您的代码中,即可使行为更容易接受:

wcex.hbrBackground = GetStockBrush(DKGRAY_BRUSH);

但是,如果您花费长达 320 毫秒的时间来响应 WM_PAINT,那么您会破坏用户的调整大小 UI。它变得生涩和 react 迟钝。该系统是围绕这样一个假设而设计的,即您可以足够快地绘制窗口以使拖动感觉平滑。解决问题的正确方法是让 WM_PAINT 在合理的时间内运行。

如果您真的无法实现足够快的绘画以实现平滑拖动,那么我建议您采用几种替代方法:

  1. 在拖动过程中禁用窗口更新。我确信这可以针对单个窗口完成,但我想不起来如何做到这一点。
  2. 在调整大小/拖动处于事件状态时绘制一些假的东西,并推迟真正的绘制直到调整大小/拖动完成。监听 WM_ENTERSIZEMOVEWM_EXITSIZEMOVE 是实现这一点的关键。此 Microsoft 示例程序说明了如何执行此操作:https://github.com/microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/winui/fulldrag/

关于c - 调整窗口大小时是否可以完全消除闪烁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12130534/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com