使用WM_DRAWITEM闪烁

时间:2013-01-28 20:01:37

标签: c++ winapi

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

2 个答案:

答案 0 :(得分:2)

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

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

e.g。处理WM_CREATE时,调用(WTL或MFC):

ModifyStyleEx(0, WS_EX_COMPOSITED);

答案 1 :(得分: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)。这是它闪烁的主要原因。