Win32 GUI调整大小时闪烁

5

我有一个带有选项卡控件的Win32 GUI程序,每个选项卡都有一个列表视图控件。当窗口大小调整时,会出现大量闪烁。我尝试了以下几种方法:

  • 在主wndproc中处理WM_ERASEBKGND并返回TRUE。没有效果。
  • 在事件循环中过滤所有WM_ERASEBKGND消息。没有效果。
  • 在主窗口上设置WM_CLIPCHILDREN样式。现在,当窗口大小调整时,列表视图控件仅被擦除到白色背景,并且不会重新绘制。
  • 使用DefWindowPos而不是MoveWindow。没有效果。
  • 在MoveWindow中将bRepaint传递为FALSE。与设置WS_CLIPCHILDREN的效果相同(见上文)。

以下是RegisterClassEx代码:

memset(&wcex, 0, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = PhMainWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = PhInstanceHandle;
wcex.hIcon = LoadIcon(PhInstanceHandle, MAKEINTRESOURCE(IDI_PROCESSHACKER));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
//wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MAINWND);
wcex.lpszClassName = PhWindowClassName;
wcex.hIconSm = (HICON)LoadImage(PhInstanceHandle, MAKEINTRESOURCE(IDI_PROCESSHACKER), IMAGE_ICON, 16, 16, 0);

WM_SIZE处理程序:

RECT rect;

// Resize the tab control.

GetClientRect(PhMainWndHandle, &rect);
MoveWindow(TabControlHandle, rect.left, rect.top,
    rect.right - rect.left, rect.bottom - rect.top, TRUE);

// Resize the list view.

TabCtrl_AdjustRect(TabControlHandle, FALSE, &rect);

MoveWindow(ListViewHandle, rect.left, rect.top,
    rect.right - rect.left, rect.bottom - rect.top, TRUE);

以下是样式:
  • 主窗口:WS_OVERLAPPEDWINDOW
  • 选项卡控件:WS_CHILD(以及WS_VISIBLE
  • 列表视图控件:WS_CHILD | WS_BORDER | LVS_REPORT(以及WS_VISIBLE

4
啊,没错,win32 窗口闪烁。这让我想起了往事... - Mike Weller
我想知道双缓冲是否能在某种程度上有所帮助... - Nick Bolton
4个回答

5

原来问题出在Z-ordering上 - 在列表视图上调用BringWindowToTop方法解决了问题。


我曾经遇到过同样的问题。调用BringWindowToTop来显示选项卡内容窗口解决了这个问题。我在显示初始选项卡后,在InitDialog中执行了此操作,并在显示新选项卡后每次选择选项卡更改时都进行了操作。 - Adam Badura
5
我也遇到了选项卡控件在调整大小时闪烁的类似问题。通过将WS_CLIPCHILDREN样式添加到父对话框中,问题得以解决。 - Adam Badura
谢谢,我也遇到了同样的问题,调用BringWindowToTop解决了它。 - Lefteris

2

Windows支持一个重新调整大小的批处理操作,旨在避免大量子窗口独立调整大小时引起的闪烁。有关此内容,请参见BeginDeferWindowPos

如果该方法不起作用,则尝试使用WM_SETREDRAW消息。可以停止绘制父窗口-这将禁止所有子控件,然后,在布局完成时再次启用绘制,并调用RedrawWindow以一次性重绘整个窗口。我认为这就是延迟窗口定位内部使用的方法。


1

我已经在列表视图上设置了LVS_EX_DOUBLEBUFFER扩展样式。或者你是在谈论另一种双缓冲技术吗?顺便说一下,我尝试使用WS_EX_COMPOSITED,但与WS_CLIPCHILDREN一样,列表视图不再重新绘制 :( - wj32

0

我没有使用.NET,所以它没有“停靠”。 - wj32
即使这篇文章谈论的是 .net,但问题是一个 win32 通用问题。所有使用 win32api GUI 控件的人,在编写任何不是玩具代码时,都或多或少遇到了列表视图闪烁问题。 - Jonke
你能建议一下这篇文章如何适用于我的情况吗?我已经尝试过过滤掉所有的擦除背景消息,所以那不可能是问题的原因 :( - wj32
你是否已经将问题确定为列表视图的问题?选项卡控件有自己搞砸事情的方式。也许你只是错过了一些强制更新的调用。 - Jonke
你期望我知道用哪些功能吗? ;) 我是一个相当有经验的开发人员,但我对Win32 GUI毫无经验。 - wj32

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接