Vertical lines for column borders


The list view control does not provide for any visual
delineation between the columns in the report mode. The code below shows
how to add vertical lines between columns. To do our own drawing we override
the OnPaint() function. Since we dont want to do all the rendering of
the control, we let DefWindowProc() take care of it before we start drawing
the lines. We also make sure that the list view control is indeed in the
report mode.


 

void CMyListCtrl::OnPaint()
{
	// First let the control do its default drawing.
	const MSG *msg = GetCurrentMessage();
	DefWindowProc( msg->message, msg->wParam, msg->lParam );

	// Draw the lines only for LVS_REPORT mode
	if( (GetStyle() & LVS_TYPEMASK) == LVS_REPORT )
	{
		// Get the number of columns
		CClientDC dc(this );
		CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
		int nColumnCount = pHeader->GetItemCount();

		// The bottom of the header corresponds to the top of the line 
		RECT rect;
		pHeader->GetClientRect( &rect );
		int top = rect.bottom;

		// Now get the client rect so we know the line length and
		// when to stop
		GetClientRect( &rect );

		// The border of the column is offset by the horz scroll
		int borderx = 0 - GetScrollPos( SB_HORZ );
		for( int i = 0; i < nColumnCount; i++ )
		{
			// Get the next border
			borderx += GetColumnWidth( i );

			// if next border is outside client area, break out
			if( borderx >= rect.right ) break;

			// Draw the line.
			dc.MoveTo( borderx-1, top);
			dc.LineTo( borderx-1, rect.bottom );
		}
	}

	// Do not call CListCtrl::OnPaint() for painting messages
}

To draw the vertical lines, we use the header control to determine the
column dimensions and also the effective client area after taking into
account the header control itself. Finally, we draw a line to the right
of each column.

Note that the horizontal scrollbars position is taken into account when
determining the border. If we dont do this, we might end up with a line
right in the middle of a column when the list has been horizontally scrolled.
The GetScrollPos() function returns 0 if there is no scrollbar so we dont
need to make a prior check on whether the list view control does have a
horizontal scrollbar. We could also have used GetItemRect() function, but
it works only if the list has atleast one item.

The line is actually drawn one pixel left of the column border. This
aligns it better with the column header. It also introduces a bug. When
you increase a column width, the column area below the last visible item
is not updated, thus leaving traces of the previous line. There are two
approaches you can take to resolve this. First, draw the line exactly on
the column border (e.i. do not subtract 1 from borderx). The second approach
is to handle the HDN_TRACK notification from the header control
and invalidate the exposed area so that it gets redrawn.

More by Author

Must Read