【问题标题】:WS_EX_COMPOSITED cause unexpected WM_PAINTWS_EX_COMPOSITED 导致意外的 WM_PAINT
【发布时间】:2013-09-11 07:07:08
【问题描述】:

创建一个具有 WS_EX_COMPOSITED 样式的窗口:

   hWnd = CreateWindowEx(WS_EX_COMPOSITED, szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

为窗口设置插入符号:

case WM_PAINT:
    OutputDebugStringA("WM_PAINT");
    hdc = BeginPaint(hWnd, &ps);
    // TODO: Add any drawing code here...
    EndPaint(hWnd, &ps);
    break;
case WM_SETFOCUS:
    ::DestroyCaret();
    ::CreateCaret(hWnd, NULL, 2, 12);
    ::SetCaretPos(200, 200);
    ::ShowCaret(hWnd);
    break;
case WM_KILLFOCUS:
    ::DestroyCaret();
    break;
case WM_CHAR:
    ::DestroyCaret();
    ::CreateCaret(hWnd, NULL, 2, 12);
    ::SetCaretPos(200, 200);
    ::ShowCaret(hWnd);
    break;

启动应用程序,什么都不做。在隐藏插入符号或破坏插入符号之前,它们将是无限的 WM_PAINT。

Spy++ 显示: 每个闪烁插入符号的 0x118(WM_SYSTIMER) 后跟一条 WM_PAINT 消息。

BeginPaint 返回的绘制结构是

WM_PAINT : invaliate rect width = 2, height = 12

这只是插入符号的宽度和高度。总之,WM_PAINT 用于闪烁插入符号。

但如果我从窗口的额外样式中删除 WM_EX_COMPOSITED 样式,则不再有无限的 WM_PAINT。

这是windows的bug吗?

PS:测试环境 windows 7 64bit + visual studio 2012。

【问题讨论】:

  • 您的 WndProc 是否返回 0 以表明它处理了 WM_PAINT?
  • @selbie: 是的,我的项目是从visual studio 2012 win32 应用程序模板派生的,它肯定返回0。实际上,我只是添加了以上几行。
  • WS_EX_COMPOSITED 对窗口的呈现方式具有 效果。顶层窗口及其所有子控件都是双缓冲的。您不希望重新绘制整个窗口堆栈以仅更新插入符号。所以这几乎可以肯定是设计使然。这应该不是问题。
  • 如果您只是在调整大小时使用复合来防止闪烁,一种可能的解决方案是仅在您进入大小循环时打开样式,然后再将其关闭。

标签: c windows winapi user-interface


【解决方案1】:

插入符号也被视为控件。不要将 WS_EX_COMPOSITED 用于顶级窗口。要么将其用于特定的有问题的控制。

或者忽略一个控件的 WndProc 中的 WM_ERASEBACKGROUND,该控件的前景内容覆盖了它的整个客户区,并且当您调整大小时控件会闪烁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    • 1970-01-01
    • 1970-01-01
    • 2021-04-24
    • 1970-01-01
    相关资源
    最近更新 更多