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

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • On-demand Event Event Date: October 29, 2014 It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this webcast, Gene Kim discusses these survey findings and shares woeful tales of artifact management gone wrong! Gene also shares examples of how high-performing DevOps …

Most Popular Programming Stories

More for Developers

RSS Feeds