错误的CListCtrl项目绘制

3
我有一个派生自CListCtrl的CListCtrlEx列表。该列表具有LVS_REPORT,LVS_OWNERDRAWFIXED和LVS_EX_GRIDLINES样式。我已经添加了更改此列表字体的可能性。这很好用,但有一件坏事——如果在更改字体之前我没有滚动列表,那么所有列表项都会正确重绘,但如果在更改字体之前我已经滚动了列表,则列表项会在列表网格水平线的上方或下方稍微重新绘制,即项目文本被网格线覆盖。
以下是我更改列表字体的方法:
LRESULT CListCtrlEx::OnSetFont(WPARAM wParam, LPARAM)
{
   LRESULT res = Default();

   CRect rc;
   GetWindowRect(&rc);

   WINDOWPOS wp;
   wp.hwnd  = m_hWnd;
   wp.cx    = rc.Width();
   wp.cy    = rc.Height();
   wp.flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER;
   SendMessage(WM_WINDOWPOSCHANGED, 0, (LPARAM)&wp);

   return res;
}

void CListCtrlEx::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
   HDC hDC = ::GetDC(NULL);
   CFont* pFont = GetFont();
   HFONT hFontOld = (HFONT)SelectObject(hDC, pFont->GetSafeHandle());
   CRect rect;

   DrawText(hDC, _T(" "), 1, rect, DT_SINGLELINE | DT_CALCRECT);
   lpMeasureItemStruct->itemHeight = rect.bottom - rect.top;
   SelectObject(hDC, hFontOld);
   ::ReleaseDC(NULL, hDC);
}

这是它的外观:

更新: 三个人点击了UP按钮,但没有人知道它是什么? :(

更新1: 这是类代码 http://pastebin.com/UdXYEpF7 .h http://pastebin.com/2HYe5AEd .cpp


1
你提供的关于类的信息非常少,很难弄清楚任何事情。根据你所描述的,似乎没有错误。如果你想在程序中间更改字体,那么请滚动到零并更改字体,然后再滚回到旧位置。 - Barmak Shemirani
你不需要为Owner Drawn列表控件实现DrawItem()方法吗? - cha
@BarmakShemirani 我已经在问题中添加了我的类代码 - brightside90
@cha 是的,我需要,在我的代码中可以看到(更新1) - brightside90
@BarmakShemirani如果我按照您所说的做,那么它将完美运行,但是我不知道将滚动条返回到旧位置的正确方法,因为字体更改之前的旧位置和更改后的旧位置是两回事。 - brightside90
1个回答

1
我尝试了你的代码,看起来ListView正在与滚动条交换消息,标题也被调整大小,这不值得深究。如果只将位置设置为零,则可以保存旧位置并将其放回。
void CListCtrlEx::SetupFont(int nSize, const CString& strName)
{
    int saveIndex = GetTopIndex();
    EnsureVisible(0, 0);

    if (m_pFont.get()) m_pFont.get()->DeleteObject();
    VERIFY(m_pFont.get()->CreatePointFont(nSize, strName));
    SetFont(m_pFont.get());

    //This scrolls to bottom, it ensures saveIndex will end up on top 
    //once the next EnsureVisible is called
    if (GetItemCount())
        EnsureVisible(GetItemCount() - 1, 1);

    EnsureVisible(saveIndex, 1);
}

好的,这是个不错的方法。我会在我的代码中使用它。只有一件事,我认为需要在这里添加 - 在EnsureVisible(0, 0)之前加上SetRedraw(FALSE);,在EnsureVisible(saveIndex, 1)之后加上SetRedraw(TRUE);以避免滚动条闪烁。谢谢! - brightside90

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