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.



Comments

  • OnPaint() without bugs

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

    Hi! I have OnPaint() method without bugs : http://rapidshare.com/files/41136000/OnPaint.zip.html Best regards, Denis.

    Reply
  • 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="http://support.microsoft.com/default.aspx?scid=kb;en-us;183258"></A>

    Reply
  • Help source code required

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

    Originally posted by: Adeel Siddiqui

    Salam!
    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

    Reply
  • 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?

    Thanks

    Reply
  • HDN_TRACK never called

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

    Originally posted by: Gil Katz

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

    Reply
  • 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?

    Ayudame...
    (Help Me..)

    Reply
  • 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;
    GetUpdateRect(&cRect);
    cRect.InflateRect(-1, 0, 0, 0);
    InvalidateRect(cRect);
    }

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

    // Now draw the lines
    ....
    }

    HTH.

    K.

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

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds