wince控件之自绘列表
来源:互联网 发布:某交友社区2千万数据 编辑:程序博客网 时间:2024/05/16 12:28
概述
上一篇讲述了如何在wince上实现自绘按钮,这一篇将继续wince上的自绘控件--列表。效果如下图,主要是依据当时的项目需要进行定制,无法像之前的自绘按钮那样具有通用性,不过如果了解了基本流程,修改起来应该没问题的!
- 仅包含一列;
- 在每列的前后显示图标,并且图标支持透明色;
- 对于选中的行,加载并显示设定的底图;
- 隐藏列表原有的滚动条,并重新自绘;
- 未显示列表的头。
本自绘列表参考了codeproject上的文章"How to skin CListCtrl including scrollbars and column headers"(基于pc的实现)
主要步骤
- 从CListCtrl派生子类,如CImageListCtrl;
- 定制列表的样式,使之自绘,无列表头等;
- 列表的自绘
- 隐藏滚动条
- 自绘滚动条
定制列表样式
重载虚函数virtual void PreSubclassWindow(),实现如下:
void CImageListCtrl::PreSubclassWindow(){VERIFY(ModifyStyle(LVS_TYPEMASK | // this styles are removedLVS_SHOWSELALWAYS |LVS_EDITLABELS,LVS_REPORT | // this styles are addedLVS_OWNERDRAWFIXED |LVS_NOCOLUMNHEADER |LVS_SINGLESEL,LVS_NOSCROLL));// Insert at least one column to the list controlVERIFY(InsertColumn(0, _T("Column"), LVCFMT_LEFT) == 0);//SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);CRect clientRect;GetClientRect(&clientRect);SetColumnWidth(0, clientRect.Width()); CListCtrl::PreSubclassWindow();}由于定制的列表只有一列,所以这当中调用函数SetColumnWidth设置列的宽度为客户区的宽度。
列表的自绘
列表的自绘直接明了,重载virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct),其中参数lpDrawItemStruct,包含了当前所要绘制的列表子项(即列表的一行)的相关信息,包括绘制句柄lpDrawItemStruct->hDC,列表子项的客户区lpDrawItemStruct->rcItem。
而列表子项的状态参数可以通过函数GetItem(LV_ITEM& lvi)获得,一旦获取了上面这些参数,那么绘制当前的列表子项就是调用相关绘制函数了,以及如何调整图片,文字的显示位置。详细实现如下:
void CImageListCtrl::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 isSelected = lvi.state & LVIS_SELECTED; CRect rcBounds; GetItemRect(nItem, rcBounds, LVIR_BOUNDS); CString sLabel = GetItemText(nItem, 0);SetBkColor(RGB(192,192,192)); PaintBk(pDC, rcItem); HBITMAPhbmOldBmp = NULL; CDC bitmapDC; bitmapDC.CreateCompatibleDC(pDC); if (isSelected && m_selImg != NULL) { hbmOldBmp = (HBITMAP)bitmapDC.SelectObject(m_selImg); pDC->BitBlt(rcItem.left, rcItem.top, rcItem.Width(), rcItem.Height(), &bitmapDC,0,0,SRCCOPY); bitmapDC.SelectObject(hbmOldBmp); } else {pDC->FillRect(rcItem,&CBrush(GetBkColor())); } if (m_ItemIcon != NULL) { hbmOldBmp = (HBITMAP)bitmapDC.SelectObject(m_ItemIcon); TransparentImage(pDC->m_hDC,rcItem.left+29, rcItem.top+12, 32, 32, bitmapDC.m_hDC,0, 0, 32, 32,RGB(0,0,0)); bitmapDC.SelectObject(hbmOldBmp); } CFont font; font.CreatePointFont(200, _T("Times New Roman")); pDC->SelectObject(&font); pDC->SetTextColor(m_textColor); pDC->DrawText(sLabel,rcItem, DT_CENTER|DT_VCENTER|DT_SINGLELINE); font.DeleteObject(); HBITMAP hbmNewBmp = NULL; if (isSelected) { if (m_checkedImg != NULL) { hbmNewBmp = m_checkedImg; } } else if(m_uncheckedImg) { hbmNewBmp = m_uncheckedImg; } if (hbmNewBmp != NULL) { hbmOldBmp = (HBITMAP)bitmapDC.SelectObject(hbmNewBmp); TransparentImage(pDC->m_hDC,rcItem.right-50, rcItem.top+12, 32, 32, bitmapDC.m_hDC,0, 0, 32, 32,RGB(0,0,0)); bitmapDC.SelectObject(hbmOldBmp); }}此外,如果想绘制列表子项的边框,需要边界大小,可以通过如下方式得到:
CRect rcBounds;GetItemRect(nItem, rcBounds, LVIR_BOUNDS);
隐藏滚动条
wince平台上想要隐藏(禁用)滚动条,没有直接的办法。因为列表的窗口包括显示列表子项的区域和显示滚动条的部分(我的猜测),所以间接的办法是:
- 设置列表的窗口大小 = 原来的窗口大小 + 滚动条的大小
- 设置列表的裁剪区域 = 原来的窗口大小
通过如上的方式,滚动条就因为被裁剪区域裁剪掉,而不会显示了。具体实现如下:
void CImageListCtrl::HideScrollBars() { RECT ierect; int cxvs, cyvs; GetClientRect(&ierect); //Get client width and height cxvs = GetSystemMetrics (SM_CXVSCROLL); //Get the system metrics - VERT cyvs = GetSystemMetrics (SM_CYVSCROLL); //Get the system metrics - HORZ //if(Which==SB_HORZ) cxvs=0; //Set VERT to zero when choosen HORZ //if(Which==SB_VERT) cyvs=0; //Set HORZ to zero when choosen VERT //Here we set the position of the window to the clientrect + the size of the scrollbars SetWindowPos(NULL, ierect.left, ierect.top, ierect.right+cxvs, ierect.bottom+cyvs, SWP_NOMOVE | SWP_NOZORDER); //Her we modify the rect so the right part is subbed from the rect. ierect.bottom -= ierect.top;ierect.right -= ierect.left;//Just to be safe that the left/top corner is 0... ierect.top = 0; ierect.left = 0; HRGN iehrgn = NULL; //This range is created base on which scrollbar that is going to be removed! //The -2 is probably a border of some kind that we also need to remove. I could not find any good //metrics that gave me an 2 as an answer. So insted we makes it static with -2. iehrgn=CreateRectRgn (ierect.left, ierect.top, ierect.right-2, ierect.bottom-2);//After the range has been made we add it... SetWindowRgn (iehrgn, TRUE);}
自绘滚动条
剩下的事情,就是添加自绘的滚动条,响应滚动事件并更新滚动条的位置。其中比较麻烦的就是给滚动条设置合适的位置,具体方法为:
- 得到列表的窗口位置并转换为屏幕坐标
- 考虑到滚动条的宽度、标题栏的宽度等参数,用上一步的坐标计算出滚动条的位置并设置。
这当中第二步的位置计算不是绝对的,根据绘制的需要和经验可以进行相应的调整。具体实现参见函数CImageListCtrl::PositionScrollBars()。
至于滚动条的绘制和滚动都封装在类CSkinHorizontalScrollbar和CSkinVerticleScrollbar中,并不难理解。
滚动条自动滚动的问题
前面的文章--CListCtrl自动滚动的问题曾经提到列表会自动滚动,你可以选择按照文章中的办法禁用掉,或者在函数void CImageListCtrl::OnTimer(UINT nIDEvent)中处理对应的nIDEvent事件,然后调用类CSkinHorizontalScrollbar和CSkinVerticleScrollbar的函数UpdateThumbPosition()来更新滚动条的位置。
用例
在对话框类中定义成员变量CImageListCtrl m_imageListCtrl,并通过DDX_Control(pDX, IDC_LIST2, m_imageListCtrl)将控件与变量绑定,然后在对话框类的初始化函数中
m_imageListCtrl.LoadVScrollImages(IDB_VERTICLE_SCROLLBAR_BOTTOM,IDB_VERTICLE_SCROLLBAR_DOWNARROW,IDB_VERTICLE_SCROLLBAR_SPAN,IDB_VERTICLE_SCROLLBAR_THUMB,IDB_VERTICLE_SCROLLBAR_TOP,IDB_VERTICLE_SCROLLBAR_UPARROW);m_imageListCtrl.LoadHScrollImages(IDB_HORIZONTAL_SCROLLBAR_LEFTARROW,IDB_HORIZONTAL_SCROLLBAR_RIGHTARROW,IDB_HORIZONTAL_SCROLLBAR_SPAN,IDB_HORIZONTAL_SCROLLBAR_THUMB);m_imageListCtrl.InitCtrl();//m_imageListCtrl.SetImageList( &m_imageList, LVSIL_SMALL );m_imageListCtrl.SetItemCheckedImg(IDB_LISTCTRL_CHECKED_BITMAP);m_imageListCtrl.SetItemSelectedImg(IDB_LISTCTRL_ITEM_SEL_BITMAP);m_imageListCtrl.SetItemIcon(IDB_LISTCTRL_ICON_BITMAP);//m_imageListCtrl.SetItemUnCheckedImg(IDB_LISTCTRL_UNCHECK_BITMAP);for (int n = 0; n < 8; n++){CString str;str.Format(_T("Item %d"), n);m_imageListCtrl.InsertItem(n, str);}
http://download.csdn.net/detail/ryanzll/4551633
- wince控件之自绘列表
- 自绘 列表控件
- Wince下自绘文本控件
- 自绘列表控件例子网址
- wince控件之自绘按钮(支持多种状态的图像加载、可通过图像创建不规程按钮)
- MFC之自绘控件
- MFC之自绘控件
- wince自绘按钮
- VC ++MFC列表框(CListBox)控件简单自绘
- WINCE 自绘位图按钮
- WINCE MFC 自绘控件的WM_PAINT与WM_ERASEBKGND、WM_TIMER 问题总结
- 【WTL】控件自绘之Button
- 【WTL】控件自绘之ProgressBar
- 【MFC】控件自绘之CTreeCtrl
- 【MFC】控件自绘之CListCtrl
- 【MFC】控件自绘之CSliderCtrl
- MFC控件自绘之(四)
- MFC控件自绘之(五)
- 高斯消元专题
- 全局变量、局部变量、静态全局变量、静态局部变量的区别
- 淘宝首页PK京东首页,HTML5将开创web前端新纪元
- C++ const与指针的学习
- malloc (0)详解
- wince控件之自绘列表
- 正则表达式、sed、awk
- hdu 4310 Hero
- url rewrite和struts2整合
- 数据流程图
- ORACLE11G自动维护任务简析
- ListView中的CheckedTextView 多选/单
- Volatile关键字详解
- 基于fpga设计9/7小波变换的解交织过程详解