Click here to Skip to main content
15,867,488 members
Articles / Desktop Programming / MFC
Article

Ownerdraw listctrl with transparent background and customized items image on WinCE

Rate me:
Please Sign up or sign in to vote.
5.00/5 (9 votes)
5 Jan 2012CPOL2 min read 42.9K   8.7K   31   7
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

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

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

C++
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

C++
CPoint bMouseDownPos;
C++
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.

C++
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)


Written By
Software Developer (Senior)
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionit is beautiful ,but lack of bmp source,could you submit them Pin
Member 115052866-May-15 23:52
Member 115052866-May-15 23:52 
GeneralMy vote of 5 Pin
shepher_whu1-Aug-13 18:34
shepher_whu1-Aug-13 18:34 
QuestionCompraron el código Pin
Member 871442110-Aug-12 4:41
Member 871442110-Aug-12 4:41 
QuestionThe bitmaps are missing?... Pin
cyfage5-Aug-12 15:36
cyfage5-Aug-12 15:36 
Questionbitmaps missing Pin
Roger656-Jan-12 22:38
Roger656-Jan-12 22:38 
QuestionNo project, no full source code, just waste the readers' time. Pin
tohjs14-Dec-11 11:43
tohjs14-Dec-11 11:43 
AnswerRe: No project, no full source code, just waste the readers' time. Pin
Pansion_chen5-Jan-12 17:04
Pansion_chen5-Jan-12 17:04 

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

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