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.


  • OnPaint() without bugs

    Posted by Denis_API on 07/05/2007 07:05am

    Hi! I have OnPaint() method without bugs : Best regards, Denis.

  • HDN_TRACK problem solved

    Posted by Legacy on 09/15/2003 12:00am

    Originally posted by: Paul

    For those of you not getting your message handler called, here is a rather useful explanation as to why:

    <A HREF=";en-us;183258"></A>

  • Help source code required

    Posted by Legacy on 06/25/2002 12:00am

    Originally posted by: Adeel Siddiqui

    If it is possible then can u send me the complete source code of a functional program of listcontrol, as i need to use it as a Grid.
    Thanxs in adavance.

    Allah Hafiz

  • how to insert items

    Posted by Legacy on 07/27/2000 12:00am

    Originally posted by: Robert Stalkin

    After I called on paint I got grids, but it removed all items from my list ctrl. When do I need to insert items?


  • HDN_TRACK never called

    Posted by Legacy on 07/27/2000 12:00am

    Originally posted by: Gil Katz

    I Used The Code But HDN_TRACK Never Called
    Any On Got Idea ?

  • Some error in GetDlgItem....

    Posted by Legacy on 10/27/1998 12:00am

    Originally posted by: Kim JungHo

    Hi. I am a beginner of MFC.

    I met some run time error among your source code.

    // 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();

    In GetDlgItem(0) function's return value is NULL.

    How can I solve this problems?

    (Help Me..)

  • Some problems with HDN_TRACK

    Posted by Legacy on 10/20/1998 12:00am

    Originally posted by: Karl

    I've tried to catch HDN_TRACK in my CListCtrl-derived class, but my function was never called :-(

    So I've found an other solution for the bug generated by the drawing of vertical lines with a left-shift of 1 pixel.
    It is a little less efficient, but it works.

    void CMyListCtrl::OnPaint()
    // First, if the list has Report style, increase invalidate
    // rect of 1 pixel to the left
    if((GetStyle() & LVS_TYPEMASK) == LVS_REPORT){
    CRect cRect;
    cRect.InflateRect(-1, 0, 0, 0);

    // Next, let the control do its default drawing.
    const MSG *msg = GetCurrentMessage();
    DefWindowProc(msg->message, msg->wParam, msg->lParam);

    // Now draw the lines



Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Moving from an on-premises environment to Office 365 does not remove the need to plan for disruptions or reduce the business risk requirements for protecting email services. If anything, some risks increase with a move to the cloud. Read how to ease the transition every business faces if considering or already migrating to cloud email. This white paper discusses: Setting expectations when migrating to Office 365 Understanding the implications of relying solely on Exchange Online security Necessary archiving …

  • Anthony Christie, the Chief Marketing Officer for Level Communications, is responsible for customer experience, worldwide marketing and product management. In this informative asset, he shares his insights into why a private network connection to cloud-bases applications is the right decision for your enterprise. Download now to find out more.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date