ravenspoint
ravenspoint

Reputation: 20576

MFC List Control scrolling shows extra grid lines

I use the MFC list control in report view with grid lines to display data in a vaguely spreadsheet manner.

Sometimes when the user scrolls vertically through the control, extra grid lines are drawn, which looks terrible.

This does not happen when the slider or the mousewheel are used to scroll, only when the little down arrow button at the bottom of the scroll control is used.

It seems that this occurs when the size of the list control window is not an exact even number of rows, so that a partial row is visible at the bottom.

If I adjust the size of the list control so that there is no partial rows visible, the problem is solved. However, it will appear when the program is run on another computer, presumably because the number of pixels occupied by a row changes.

I am assuming that it is an interaction between screen resolution, font size and "dialog units".

I guess that I need to programmatically force the size of the control when it is created. But what size?

I have tried using the ApproximateViewRect() method but I cannot get it to work. Perhaps this method does not know about report view?

The other method, I suppose, would be to create my own specialization of CListCtrl and over-ride whatever method is doing the scrolling. This seems likely to be a lot of work.

This screenshot shows a closely related problem where the grid lines go missing

alt text

and here is one with the extra grid lines

alt text

The only difference between these two and between them and one which scrolls perfectly is a few pixels different in the vertical size of the control.

Upvotes: 2

Views: 6301

Answers (4)

ravenspoint
ravenspoint

Reputation: 20576

To fix this bug in the MFC List Control you need to specialize the control, over-ride the method wich responds to the scroll, and force it to redraw the list completely after it has done the scroll.

interface header

class cSmoothListControl : public CListCtrl
{
public:
    DECLARE_MESSAGE_MAP()
    afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
};

implementation:

BEGIN_MESSAGE_MAP(cSmoothListControl, CListCtrl)
ON_WM_VSCROLL()
END_MESSAGE_MAP()

void cSmoothListControl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // call base class method to do scroll
    CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);

    // force redraw to cover any mess that may be created
    Invalidate();
    UpdateWindow();
}

Upvotes: -1

Aidan Ryan
Aidan Ryan

Reputation: 11609

This is indeed a bug related to "smooth scrolling," here's a workaround:

void CMyListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    __super::OnVScroll(nSBCode, nPos, pScrollBar);
    Invalidate();
    UpdateWindow();
}

Upvotes: 6

Aardvark
Aardvark

Reputation: 8571

I recall this being a bug in the ListView (not just through MFC, but the common control in general) itself. A quick google on this seems to hit a lot of people coming to that same conclusion. I guess since Windows Explorer doesn't have gridlines they don't feel the need fix this? I remember this back in the late 90's.

I guess the trick would be to invalidate the window after a scroll - maybe in response to a VSCROLL message? Just a guess.

Upvotes: 1

Roel
Roel

Reputation: 19642

Is this happening with the stock listview, or is it custom draw? I've never seen redrawing issues with the standard windows controls.

Maybe you can post a screenshot to illustrate the problem? I presume you'd prefer to fix the redraw issue and not size the control exactly?

Upvotes: 0

Related Questions