Displaying an Empty ListView Message

When using a ListView it may be useful to inform the user that the control is empty, like Microsoft Outlook does. Doing this is pretty straightforward. Just derive your own ListView control from CListCtrl and add a WM_PAINT event handler to your derived class.



class CEmptyListCtrl : public CListCtrl
{
// Construction
public:

// Overrides
protected:
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CEmptyListCtrl)
	//}}AFX_VIRTUAL

// Implementation
public:

// Generated message map functions
protected:
	//{{AFX_MSG(CEmptyListCtrl)
	afx_msg void OnPaint();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};


Then, in OnPaint member function, implement the code necessary to handle the empty condition.



void CEmptyListCtrl::OnPaint() 
{
    Default();
    if (GetItemCount() <= 0)
    {
        COLORREF clrText = ::GetSysColor(COLOR_WINDOWTEXT);
        COLORREF clrTextBk = ::GetSysColor(COLOR_WINDOW);

        CDC* pDC = GetDC();
        // Save dc state
        int nSavedDC = pDC->SaveDC();

        CRect rc;
        GetWindowRect(&rc);
        ScreenToClient(&rc);

        CHeaderCtrl* pHC;
        pHC = GetHeaderCtrl();
        if (pHC != NULL)
        {
            CRect rcH;
            pHC->GetItemRect(0, &rcH);
            rc.top += rcH.bottom;
        }
        rc.top += 10;

        CString strText((LPCSTR)IDS_NOITEMS); // The message you want!

        pDC->SetTextColor(clrText);
        pDC->SetBkColor(clrTextBk);
        pDC->FillRect(rc, &CBrush(clrTextBk));
        pDC->SelectStockObject(ANSI_VAR_FONT);
        pDC->DrawText(strText, -1, rc, 
                      DT_CENTER | DT_WORDBREAK | DT_NOPREFIX | DT_NOCLIP);

        // Restore dc
        pDC->RestoreDC(nSavedDC);
        ReleaseDC(pDC);
    }
    // Do not call CListCtrl::OnPaint() for painting messages
}




Comments

  • Displaying an Empty ListView Message

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

    Originally posted by: Charles Curtis

    Works Great! Just thought you might like to know that it is still working. Thanks!

    Reply
  • How do I tell the list view to use the new list control?

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

    Originally posted by: Haim

    Hi,
    I've tried to subclass the list control in the list view OnInitialUpdate(), like this:
    MyListCtrl.SubclassWindow(GetListCtrl().GetSafeHwnd());
    But I always get asserts.

    Any ideas?

    Reply
  • How to use in a DLL

    Posted by Legacy on 05/22/2003 12:00am

    Originally posted by: David Pritchard

    If you include this code in a CListCtrl base class which you have in a DLL (my case!), trying to get the CHeaderCtrl object causes problems because of problems with permanent window maps (this is an awful mess in MFC).

    So to get it to work when this code is not in the same DLL as the CListCtrl object, replace this:

    CHeaderCtrl* pHC;
    pHC = GetHeaderCtrl();
    if (pHC != NULL)
    {
    CRect rcH;
    pHC->GetItemRect(0, &rcH);
    rc.top += rcH.bottom;
    }


    with this:

    HWND hWndHeader = ListView_GetHeader(m_hWnd);

    if (hWndHeader != NULL)
    {
    CRect rcH;
    pHC->GetItemRect( 0, &rcH );
    Header_GetItemRect(hWndHeader, 0, &rcH );
    rc.top += rcH.bottom;
    }

    Reply
  • Simple change for CListView

    Posted by Legacy on 02/19/2002 12:00am

    Originally posted by: Kyle Sluder

    Well, it doesn't work in CListView unless you add the following code to your CListView-derived class:

    Add the following to your message map (after the text "//}}AFX_MSG_MAP"):

    ON_WM_PAINT()

    -----

    Then add the function "void OnPaint()" to your class, and add this code:

    CPaintDC dc(&GetListCtrl());

    CRect Rect;
    GetListCtrl().GetClientRect(Rect);
    CString szStr = _T("There are no items to show in this view.");
    UINT nFormat = DT_CENTER | DT_WORDBREAK
    | DT_NOPREFIX | DT_NOCLIP
    | DT_VCENTER | DT_SINGLELINE;
    dc.SelectStockObject(ANSI_VAR_FONT);
    dc.DrawText(szStr, Rect, nFormat);

    -----

    Take care not to simply change DT_CENTER to DT_LEFT and DT_VCENTER to DT_TOP, otherwise the text will be hidden beneath the header control.

    Reply
  • Doesn't seem to work for CListView

    Posted by Legacy on 10/04/2000 12:00am

    Originally posted by: Kevin M.

    When I try to use it for a list view (report) in my program it never shows the items.  i have run it through the debugger and it skips the 'if' branch entirely but the new item doesn't show up.  It shows a blank window, instead of "There are no items to show..."
    
    

    I had to modify the 'if' code a little bit...

    void CPasswordView::OnPaint( )
    {
    CPaintDC dc( this ); // device context for painting
    OnPrepareDC(&dc);

    // the list items to be checked
    >>> CList < theObject * , theObject * > * pList =
    GetDocument( ) -> GetInfoList( );

    Default( );
    if( pList -> GetCount( ) <= 0 )
    {
    COLOREF...
    ...
    }
    }

    It just doesn't seem to work :(

    Reply
  • same for List Control?

    Posted by Legacy on 08/22/2000 12:00am

    Originally posted by: Tony

    How do you do the same for a List Control?

    Reply
  • probably ON_WM_PAINT() should be added to message map

    Posted by Legacy on 05/26/2000 12:00am

    Originally posted by: Iztok Vidmar

    BEGIN_MESSAGE_MAP(CFileDropListCtrl, CListCtrl)
    
    //{{AFX_MSG_MAP(CFileDropListCtrl)
    ON_WM_PAINT()
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    Reply
  • Flicker fix

    Posted by Legacy on 04/15/2000 12:00am

    Originally posted by: Jeff Miller


    Here's what I created. This works much better.

    void CMpListView::OnPaint()
    {
    if ( GetItemCount() == 0 )
    {
    CPaintDC dc( this );
    int nSavedDC = dc.SaveDC();

    CRect rc;
    GetWindowRect( &rc );
    ScreenToClient( &rc );

    CHeaderCtrl* pHC;
    pHC = GetHeaderCtrl();
    if (pHC != NULL)
    {
    CRect rcH;
    pHC->GetItemRect( 0, &rcH );
    rc.top += rcH.bottom;
    }
    rc.top += 10;

    CString strText;
    strText.LoadString( IDS_NOITEMS );

    dc.SetTextColor( ::GetSysColor( COLOR_WINDOWTEXT ) );
    dc.SetBkColor( ::GetSysColor( COLOR_WINDOW ) );
    dc.SelectStockObject( ANSI_VAR_FONT );
    dc.DrawText( strText, -1,
    rc,
    DT_CENTER | DT_WORDBREAK | DT_NOPREFIX | DT_NOCLIP );

    dc.RestoreDC(nSavedDC);
    }
    else
    {
    Default();
    }

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

    Reply
  • Possible bug + the fix

    Posted by Legacy on 03/06/2000 12:00am

    Originally posted by: Alex M�ller

    The code worked only after one change:

    When the OnPaint() would be changed in that way:

    if (GetItemCount() > 0)
    {
    Default();
    }
    else
    {
    COLORREF ...
    ...
    ReleaseDC(pDC);
    }

    When Default() was called each time, I saw nothing inside the view part.

    Alex

    Reply
  • Flicker on control

    Posted by Legacy on 01/13/2000 12:00am

    Originally posted by: Tim Hodgson

    I implemented your code and the text seems to flicker quite a bit. I tried to set a flag that the message has been "painted", so that it would only do it once, but that causes the message to never be displayed.

    I am using VC++ 5 - maybe that is the problem.

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

Top White Papers and Webcasts

  • Lenovo recommends Windows 8 Pro. "I dropped my laptop getting out of the taxi." This probably sounds familiar to most IT professionals. If your employees are traveling, you know their devices are in for a rough go. Whether it's a trip to the conference room or a convention out of town, any time equipment leaves a user's desk it is at risk of being put into harm's way. Stay connected at all times, whether at the office or on the go, with agile, durable, and flexible devices like the Lenovo® …

  • U.S. companies are desperately trying to recruit and hire skilled software engineers and developers, but there is simply not enough quality talent to go around. Tiempo Development is a nearshore software development company. Our headquarters are in AZ, but we are a pioneer and leader in outsourcing to Mexico, based on our three software development centers there. We have a proven process and we are experts at providing our customers with powerful solutions. We transform ideas into reality.

Most Popular Programming Stories

More for Developers

RSS Feeds

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