是否有可能消除调整窗口时闪烁完全? [英] Is it possible to eliminate flickering entirely when resizing a window?

查看:140
本文介绍了是否有可能消除调整窗口时闪烁完全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常情况下,使用双缓冲,即使,调整窗口时,它似乎是不可避免的闪烁会发生的。

Normally, even when using double buffering, when resizing a window, it seems that it's inevitable that the flickering will happen.

步骤1中,原来的窗口。

Step 1, the original window.

步骤2,调整窗口大小,但多余的面积并没有被画。

Step 2, the window is resized, but the extra area hasn't been painted.

步骤3,调整窗口大小,以及额外的面积已画。

Step 3, the window is resized, and the extra area has been painted.

是否有可能以某种方式隐藏SETP 2?我可以暂停调整过程,直到绘画动作是做?

Is it possible somehow to hide setp 2? Can I suspend the resizing process until the painting action is done?

下面是一个例子:

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

是否有可能消除闪烁?

Is it possible to eliminate the flickering?

推荐答案

在拖动操作过程中更新窗口,那么OS有显示的的东西的在扩展窗口区域。如果你不能提供任何东西,然后它会显示背景,直到你怎么做。既然你没有指定任何背景你的黑暗。当然,你应该指定一个背景刷?只需添加以下到您的code,使行为更可口:

When the window is updated during a drag operation, then the OS has to show something in the extended window region. If you can't provide anything then it will show the background until you do. Since you didn't specify any background you get blackness. Surely you ought to be specifying a background brush? Simply adding the following to your code makes the behaviour more palatable:

wcex.hbrBackground = GetStockBrush(DKGRAY_BRUSH);

不过,如果你需要长达320ms来回应一个 WM_PAINT 那么你毁了用户的调整大小UI。它变得生涩,反应迟钝。该系统的设计是围绕你可以绘制窗口的速度不够快的拖动到手感滑爽的假设。解决您的问题的正确方法是让 WM_PAINT 运行在合理的时间。

However, if you take as long as 320ms to respond to a WM_PAINT then you ruin the resize UI for the user. It becomes jerky and unresponsive. The system is designed around the assumption that you can paint the window quickly enough for dragging to feel smooth. The right way to fix your problem is to make WM_PAINT run in a reasonable time.

如果你真的无法实现平滑拖动速度不够快画那么我建议几个选择:

If you really can't achieve quick enough painting for smooth dragging then I suggest a couple of alternatives:


  1. 拖动过程中禁用窗口更新。我敢肯定,这可以为单个窗口来完成,但我不记得如何做到这一点从我的头顶。

  2. 油漆假的东西,同时调整大小/拖拽处于活动状态,并且推迟真正的绘画时,调整大小/阻力已完成,直到。监听 WM_ENTERSIZEMOVE WM_EXITSIZEMOVE 的关键是这一点。这MSDN文章介绍了如何做到这一点: http://support.microsoft.com/kb/121541

  1. Disable window updates during dragging. I'm sure this can be done for individual windows, but I can't remember how to do it off the top of my head.
  2. Paint something fake whilst a resize/drag is active, and postpone the real painting until when the resize/drag has completed. Listening for WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE are the keys to this. This MSDN article illustrates how to do that: http://support.microsoft.com/kb/121541

这篇关于是否有可能消除调整窗口时闪烁完全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆