1

似乎我无法通过所有者绘制控件解决此问题。我已经对状态控件进行了超分类。我正在尝试自定义但仍保留相同的功能。基本上,我想改变背景和文字。我正在使用 Direct2d(或 ID2D1DCRenderTarget 接口)进行绘图。我已经使用 WM_NCPAINT 成功更改了背景;不过,您可以根据需要使用 WM_ERASEBKGRND。然而,这两种方法在我的实验中都充当了对照,并且仍然发生闪烁。此外,当 SB_SETTEXT 的 WPARAM 未设置为 SBT_OWNERDRAW时,不会发生闪烁。因此,我得出一个结论,WM_DRAWITEM 是罪魁祸首。无论如何我可以用所有者绘制状态栏解决这个闪烁的问题吗?

4

2 回答 2

2

如果您为您的控制打开双缓冲,您可以避免闪烁。

设置 WS_EX_COMPOSITED 扩展样式: http: //msdn.microsoft.com/en-us/library/windows/desktop/ff700543 (v=vs.85).aspx

例如在处理 WM_CREATE 时,调用(WTL 或 MFC):

ModifyStyleEx(0, WS_EX_COMPOSITED);
于 2013-01-28T20:53:10.817 回答
1

嗯,好像我想通了。当对状态栏进行超分类时,请遵循这些设置以避免闪烁。

**注意:这仅在视觉样式关闭的情况下进行了测试。SetWindowTheme(hWndStatus, L"", L""); 此外,父窗口必须在窗口创建期间在样式参数中设置 WS_CLIPCHILDREN。

1:覆盖 WM_SIZE。调用 InvalidateRect(m_hWnd, NULL, TRUE) 并返回 0 ,除非您想要默认大小;在这种情况下,调用 CallWindowProc。

2:覆盖 WM_ERASEBKGND 并返回 -1。

3:覆盖 WM_NCPAINT 并将您的绘图代码放在这里。

处理 WM_NCPAINT。人们似乎很难理解如何处理 WM_NCPAINT。这是我的做法。

if (wParam == 1) {
    hdc = GetWindowDC(m_hWnd);
} else {
    hdc = GetDCEx(m_hWnd, (HRGN) wParam, DCX_WINDOW | DCX_INTERSECTRGN | DCX_CACHE);
}

然后用 DC 画图。

4:在父过程(WndProc 或其他)中,使用状态栏的句柄调用 SetWindowPos(..., SWP_DRAWFRAME)。这将调整您的状态栏的大小。

5:通过 SendMessage(hWndStatusbar, SB_SETPARTS, 1, (LPARAM) &parts) 发送消息;

6:通过 SendMessage(hWndStatusbar, SB_SETTEXT, LOBYTE(0) | SBT_OWNERDRAW, L"Ready") 发送消息。WM_DRAWITEM 的示例代码:

...
WM_DRAWITEM:
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT) lParam;

m_pFramework->m_pD2D1RenderTarget->BindDC(lpDIS->hDC, &lpDIS->rcItem);

m_pFramework->m_pD2D1RenderTarget->BeginDraw();

m_pFramework->m_pD2D1RenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::CadetBlue));

D2D1_RECT_F rf = D2D1::RectF(
    PixeltoDipX(lpDIS->rcItem.left),
    PixeltoDipY(lpDIS->rcItem.top),
    PixeltoDipX(lpDIS->rcItem.right),
    PixeltoDipY(lpDIS->rcItem.bottom)
    );

m_pFramework->m_pD2D1RenderTarget->DrawText(
    (LPCWSTR) lpDIS->itemData,
    wcslen((WCHAR*) lpDIS->itemData) + 1,
    m_pFramework->m_pTextFormat,
    rf,
    m_d2dCaptionTextColor
    );

m_pFramework->m_pD2D1RenderTarget->EndDraw();
break;
....

这应该停止闪烁。另外,不要在父级的 WM_SIZE 中调用 InvalidateRect(hWndStatus, NULL, TRUE)。这是它闪烁的主要原因。

于 2013-01-28T21:05:30.450 回答