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

  • With JRebel, developers get to see their code changes immediately, fine-tune their code with incremental changes, debug, explore and deploy their code with ease (both locally and remotely), and ultimately spend more time coding instead of waiting for the dreaded application redeploy to finish. Every time a developer tests a code change it takes minutes to build and deploy the application. JRebel keeps the app server running at all times, so testing is instantaneous and interactive.

  • Download the Information Governance Survey Benchmark Report to gain insights that can help you further establish business value in your Records and Information Management (RIM) program and across your entire organization. Discover how your peers in the industry are dealing with this evolving information lifecycle management environment and uncover key insights such as: 87% of organizations surveyed have a RIM program in place 8% measure compliance 64% cannot get employees to "let go" of information for …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds