Click here to Skip to main content
Click here to Skip to main content
Go to top

Ownerdraw listctrl with transparent background and customized items image on WinCE

, 5 Jan 2012
Rate this:
Please Sign up or sign in to vote.
Ownerdraw listctrl with transparent background and custermized items image on WinCE.

 Introduction 

  Download ownerDrawList.zip - 4.76 MB  

 Owner-draw listctrl with transparent background and customized items(with checkbox) image on wince

ownerdraw_listctrl.PNG 

Background   

I am developing a media player which should be running on windows embedded compact 7 system with customized hardware. Before this project, I have 0 experience of MFC and last time I did a windows based development was 10 years ago using C++builder. I am now actually a linux developer. Luckily with help of google/codeproject, I finished all things in 2 weeks. The purpose of this article is to help those developers which may have similar situation.

At first since I did not get hardware on hand, I have done all the development on windows desktop environment( windows 7). When I am trying to port code to wince platform, I found that  wince did not support owner-draw listbox which I used to display playlist. Then I turn to use listctrl. I spent a day to convert my code from listbox to listctrl. Thanks again for codeproject.

Using the code

I create a new class MyListCtrl inherited from MFC ListCtrl and adding below features

  • ability to set bitmap image for item icon
  • ability to set bitmap image for item highlight
  • ability to set bitmap image for item checkbox
  • ability to be transparent to parent window
  • ability to set item height

 Below are corresponding interfaces for setting the image from resource ID

    //set highlight image     
    void SetItemHighlightImg(UINT id); 
    // set item icon
    void SetItemIcon(UINT id); 
    // set image of "Checkbox" in unchecked status
    void SetItemCheckedImg(UINT id);
    // set image of "Checkbox" in checked status
    void SetItemUnCheckedImg(UINT id); 
    // set background
    void SetBk(CDC *pDC); 

The core function for a owner-draw list ctrl is DrawItem

void MyListCtrl::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
    ASSERT(::IsWindow(m_hWnd));
    ASSERT(lpDrawItemStruct != 0);
    CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    CRect rcItem(lpDrawItemStruct->rcItem);
    int nItem = lpDrawItemStruct->itemID;

    LV_ITEM lvi;
    lvi.mask = LVIF_STATE;
    lvi.iItem = nItem;
    lvi.iSubItem = 0;
    lvi.stateMask = 0xFFFF;     // get all state flags
    GetItem(&lvi);

    BOOL bHighlight = lvi.state & LVIS_FOCUSED;

    CRect rcBounds;
    GetItemRect(nItem, rcBounds, LVIR_BOUNDS);
    CString sLabel = GetItemText(nItem, 0);

    PaintBk(pDC, rcItem);

    HBITMAP		hbmOldBmp	= NULL;

    CDC bitmapDC;
    bitmapDC.CreateCompatibleDC(pDC);

    
    if (bHighlight)
    {
        hbmOldBmp = (HBITMAP)bitmapDC.SelectObject(m_SelImg);
        pDC->BitBlt(rcItem.left, rcItem.top, rcItem.Width(), rcItem.Height(), &bitmapDC,0,0,SRCCOPY);
        bitmapDC.SelectObject(hbmOldBmp);
    }

    ResConfigRec iRec = SkinConfigMgr::GetResConfig(IDB_IMG_ITEM_ICON);
    hbmOldBmp = (HBITMAP)bitmapDC.SelectObject(m_ItemIcon);
    pDC->BitBlt(rcItem.left + iRec.resX, rcItem.top + iRec.resY, iRec.resW, iRec.resH, &bitmapDC,0,0,SRCCOPY);
    bitmapDC.SelectObject(hbmOldBmp);

    // NOTE: Please replace below code block with your own logic
    // In my implementation, I used std::vector<int> to store checkbox status of each items
    // std::vector<int>* m_pStatusMap
#if 0
    iRec = SkinConfigMgr::GetResConfig(IDB_IMG_ITEM_UC);
    int checked = m_pStatusMap->at(nItem);
    if ((rcItem.left + iRec.resX < bMouseDownPos.x && bMouseDownPos.x < rcItem.left + iRec.resX +iRec.resW)
        &&(rcItem.top + iRec.resY < bMouseDownPos.y && bMouseDownPos.y < rcItem.top + iRec.resY +iRec.resH))
    {
        std::vector<int>::iterator iter = m_pStatusMap->begin()+nItem;
        if (checked == 1)
        {
            *iter = 0;
        }
        else
        {
            *iter = 1;
        }
        checked = *iter;
        bMouseDownPos.x = 0;
        bMouseDownPos.y = 0;
    }
#endif

    CFont font;
    font.CreatePointFont(200, _T("Times New Roman")); 
    pDC->SelectObject(&font);
    pDC->SetTextColor(RGB(255,255,255));
    pDC->DrawText(sLabel,rcItem, DT_CENTER);

    if (checked == 1)
    {
        hbmOldBmp = (HBITMAP)bitmapDC.SelectObject(m_CbChecked);
        pDC->BitBlt(rcItem.left + iRec.resX, rcItem.top + iRec.resY, iRec.resW, iRec.resH, &bitmapDC,0,0,SRCCOPY);
        bitmapDC.SelectObject(hbmOldBmp);
    }
    else
    {
        hbmOldBmp = (HBITMAP)bitmapDC.SelectObject(m_CbUnChecked);
        pDC->BitBlt(rcItem.left + iRec.resX, rcItem.top + iRec.resY, iRec.resW, iRec.resH, &bitmapDC,0,0,SRCCOPY);
        bitmapDC.SelectObject(hbmOldBmp);
    }

}

To change the status of checkbox, we need to handle message ON_WM_LBUTTONDOWN  and record mouse down position

CPoint bMouseDownPos;
void MyListCtrl::OnLButtonDown( UINT nFlags, CPoint point )
{
    bMouseDownPos = point;
    Default();
    int iPos = GetNextItem( -1, LVNI_ALL | LVNI_SELECTED);
    CRect rcItem;
    GetItemRect(iPos, &rcItem, LVIR_BOUNDS);
    // NOTE: replace this code with your own logic
    //ResConfigRec iRec = SkinConfigMgr::GetResConfig(IDB_IMG_ITEM_UC);
    //if ((rcItem.left + iRec.resX < bMouseDownPos.x && bMouseDownPos.x < rcItem.left + iRec.resX +iRec.resW)
     //   &&(rcItem.top + iRec.resY < bMouseDownPos.y && bMouseDownPos.y < rcItem.top + iRec.resY +iRec.resH))
    //{
    //    InvalidateRect(&rcItem);
    //}
}

Points of Interest  

   The usage of MeasureItem to set item height did not work for listctrl. A simple way to set item height is to use a imagelist.

    m_imageList.Create(24, 58, ILC_COLOR4,10,10 );   
    myList.SetImageList(   &m_imageList,   LVSIL_SMALL   );

History 

Keep a running update of any changes or improvements you've made here.  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Pansion_chen
Software Developer (Senior)
China China
No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 Pinmembershepher_whu1-Aug-13 18:34 
QuestionCompraron el código PinmemberMember 871442110-Aug-12 4:41 
QuestionThe bitmaps are missing?... Pinmembercyfage5-Aug-12 15:36 
Questionbitmaps missing PinmemberRoger656-Jan-12 22:38 
QuestionNo project, no full source code, just waste the readers' time. Pinmembertohjs14-Dec-11 11:43 
AnswerRe: No project, no full source code, just waste the readers' time. PinmemberPansion_chen5-Jan-12 17:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 5 Jan 2012
Article Copyright 2011 by Pansion_chen
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid