c++ listview自绘例子
By
admin
at 2018-02-09 • 0人收藏 • 1816人看过
//-------------------------------------------------------------------// 名称: tabCtrlMainProc// 类型: LRESULT// 限定符: CALLBACK//// 描述: 用于响应控件TabCtrl - Main的消息//-------------------------------------------------------------------LRESULT CALLBACK tabCtrlMainProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_NOTIFY) { LPNMHDR nmh = (LPNMHDR) lParam; if (nmh->hwndFrom == hListViewPersons && nmh->code == NM_CUSTOMDRAW) // 是来自listViewPersons, 并且消息为NM_CUSTOMDRAW { LPNMLVCUSTOMDRAW lpNMCustomDraw = reinterpret_cast<LPNMLVCUSTOMDRAW>(lParam); int nResult = CDRF_DODEFAULT; // 默认由系统绘制, 除非下面进行了自定义绘制 // 如果处于步骤 - CDDS_PREPAINT, 则告诉系统需要自绘每一行 if (CDDS_PREPAINT == lpNMCustomDraw->nmcd.dwDrawStage) { nResult = CDRF_NOTIFYITEMDRAW; } else if (CDDS_ITEMPREPAINT == lpNMCustomDraw->nmcd.dwDrawStage) { // 这里获得了当前行的信息, 而需要获得当前列的消息. nResult = CDRF_NOTIFYSUBITEMDRAW; } else if ((CDDS_ITEMPREPAINT | CDDS_SUBITEM) == lpNMCustomDraw->nmcd.dwDrawStage) { // 默认由自己绘制 nResult = CDRF_SKIPDEFAULT; const DWORD dwStyle = DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_END_ELLIPSIS; BOOL bCtrlFocused = GetFocus() == hListViewPersons; // 控件是否有焦点 COLORREF clrTextColor = RGB(0, 0, 0); // 保存文本颜色, 默认为黑色 HDC hdc = lpNMCustomDraw->nmcd.hdc; // 获得绘制句柄 int nItem = (int)lpNMCustomDraw->nmcd.dwItemSpec; // 获得当前行 int nSubItem = lpNMCustomDraw->iSubItem; // 获得当前列 // 获得当前行状态 // p.s 本来可以用lpNMCustomDraw->nmcd.uItemState判断的, 但是msdn上说CDIS_SELECTED工作不正常.. BOOL bItemSelected = ListView_GetItemState(hListViewPersons, nItem, LVIS_SELECTED); BOOL bItemFocused = ListView_GetItemState(hListViewPersons, nItem, LVIS_FOCUSED); // 获得列绘制区域 RECT subItemRect; ListView_GetSubItemRect(hListViewPersons, nItem, nSubItem, LVIR_BOUNDS, &subItemRect); // 根据项目的状态绘制背景色 if (bItemSelected) { // 被选中 if (bCtrlFocused) { // 有焦点 FillRect(hdc, &subItemRect, CreateSolidBrush(RGB(185, 213, 241))); if (bItemFocused) { // 焦点所在项 RECT itemRect; ListView_GetItemRect(hListViewPersons, nItem, &itemRect, LVIR_BOUNDS); FrameRect(hdc, &itemRect, CreateSolidBrush(RGB(51, 153, 255))); } } else // 无焦点 FillRect(hdc, &subItemRect, CreateSolidBrush(RGB(240, 240, 240))); } // 获得内容 LPTSTR szText = new TCHAR[MAX_STRING]; ListView_GetItemText(hListViewPersons, nItem, nSubItem, szText, MAX_STRING); // 判断列 switch (nSubItem) { case 0: // 第1列 - "名称" { // 获得图标绘制区域 RECT iconRect; ListView_GetSubItemRect(hListViewPersons, nItem, nSubItem, LVIR_ICON, &iconRect); OffsetRect(&iconRect, 0, 1); // 画图标 HDC memDC = CreateCompatibleDC(hdc); if (bItemSelected) { // 被选中 if (bCtrlFocused) // 有焦点 SelectObject(memDC, (HGDIOBJ) LoadBitmap(AppInfo.hInstance, MAKEINTRESOURCE(IDB_USER_SELECT_FOCUS))); else // 无焦点 SelectObject(memDC, (HGDIOBJ) LoadBitmap(AppInfo.hInstance, MAKEINTRESOURCE(IDB_USER_SELECT_NOTFOCUS))); } else { SelectObject(memDC, (HGDIOBJ) LoadBitmap(AppInfo.hInstance, MAKEINTRESOURCE(IDB_USER_NORMAL))); } BitBlt(hdc, iconRect.left, iconRect.top, 16, 16, memDC, 0, 0, SRCCOPY); DeleteDC(memDC); // 获得文字绘制区 RECT fontRect; ListView_GetSubItemRect(hListViewPersons, nItem, nSubItem, LVIR_LABEL, &fontRect); // 画字 OffsetRect(&fontRect, 18, 0); DrawText(hdc, szText, _tcslen(szText), &fontRect, dwStyle); break; } case 2: // 第3列 - "得分" { // 调整绘制区 subItemRect.left += 2; subItemRect.right -= 2; subItemRect.top += 2; subItemRect.bottom -= 2; // 填充背景为灰色 FillRect(hdc, &subItemRect, CreateSolidBrush(RGB(240, 240, 240))); int nScore = _ttoi(szText); // 获得分数 if (nScore != 0) // 0分就不绘制了 { // 计算绘制区域 RECT scoreRect = subItemRect; scoreRect.right = scoreRect.left + (int)((scoreRect.right - scoreRect.left) * ((float) nScore / 400.0)); FillRect(hdc, &scoreRect, CreateSolidBrush(RGB(189, 189, 189))); // 填充区域 } // 画字 OffsetRect(&subItemRect, 2, 0); DrawText(hdc, szText, _tcslen(szText), &subItemRect, dwStyle); break; } case 4: // 第5列 - "状态" if (!_tcscmp(szText, _T("已评测"))) clrTextColor = RGB(0, 120, 0); // 将颜色设为绿色 else if (!_tcscmp(szText, _T("未评测"))) clrTextColor = RGB(255, 69, 0); // 橘红色 else if (!_tcscmp(szText, _T("正在评测"))) clrTextColor = RGB(0, 0, 255); // 蓝色 else if (!_tcscmp(szText, _T("等待评测"))) clrTextColor = RGB(139, 0, 245); // 紫色 default: // 设置颜色 & 画字(这就是所谓的统一文字绘制) SetTextColor(hdc, clrTextColor); OffsetRect(&subItemRect, 5, 0); DrawText(hdc, szText, _tcslen(szText), &subItemRect, dwStyle); } // 释放 delete[] szText; } return nResult; } // if } // 其他消息都还给Windows return CallWindowProc(Control.tabCtrlMain.oldProc, hWnd, uMsg, wParam, lParam); }
转自:http://www.phpfans.net/ask/MTM0NTA3OQ.html
3 个回复 | 最后更新于 2018-10-10
listview中自绘进度条:
import win.ui; /*DSG{{*/ var winform = win.form(text="listview中添加进度条演示";right=945;bottom=474) winform.add( button={cls="button";text="(点击这里随机更新一次第二行的进度值)";left=0;top=392;right=944;bottom=472;font=LOGFONT(h=-21);z=2}; 流程编辑框={cls="listview";left=0;top=0;right=946;bottom=384;edge=1;font=LOGFONT(name='FontAwesome';h=-19);fullRow=1;vscroll=1;z=1} ) /*}}*/ import win.fontAwesome; import win.graphics; import win.imageList; var imagelist = win.imageList(5,34); winform.流程编辑框.setImageList( imagelist,1/*_LVSIL_SMALL*/ ); winform.流程编辑框.insertColumn("",30,,0x2/*_LVCFMT_CENTER*/) winform.流程编辑框.insertColumn("中断",80,,0x2/*_LVCFMT_CENTER*/) winform.流程编辑框.insertColumn("备注",300,,0x0/*_LVCFMT_LEFT*/) winform.流程编辑框.insertColumn("功能",100,,0x0/*_LVCFMT_LEFT*/) winform.流程编辑框.insertColumn("参数",300,,0x0/*_LVCFMT_LEFT*/) winform.流程编辑框.insertColumn("",30,,0x2/*_LVCFMT_CENTER*/) winform.流程编辑框.insertColumn("",1,,0x2/*_LVCFMT_CENTER*/) //自适应列宽度 winform.流程编辑框.adjust = function(cx,cy){ winform.流程编辑框.fillParent(5/*列序号*/); } winform.流程编辑框.addItem( { text={'\uF00c';'\uF1db';30;"直线运动";'{["速度"]=1000;["模式"]="相对运动";["距离"]="2380";["是否等待"]="否";}';'\uF01a'} } ) winform.流程编辑框.addItem( { text={'\uF00d';'\uF05e';100;"直线运动";'{["速度"]=300;["模式"]="连续运动";["是否等待"]="是";}';'\uF01a'} } ) winform.流程编辑框.addItem( { text={'\uF00c';'\uF1db';200;"调用子程序";'{["调用子程序"]="连续读传感器";["是否等待"]="是";}';'\uF01a'} } ) winform.流程编辑框.addItem( { text={'\uF00c';'\uF1db';50;"调用子程序";'{["调用子程序"]="回字形对准算法";["是否等待"]="是";}';'\uF01a'} } ) winform.流程编辑框.addItem( { text={'\uF00c';'\uF1db';150;"直线运动";'{["速度"]=1000;["模式"]="相对运动";["距离"]="2380";["是否等待"]="否";}';'\uF01a'} } ) winform.流程编辑框.addItem( { text={'\uF00c';'\uF1db';120;"直线运动";'{["速度"]=1000;["模式"]="相对运动";["距离"]="2380";["是否等待"]="否";}';'\uF01a'} } ) winform.流程编辑框.addItem( { text={'\uF00d';'\uF05e';10;"直线运动";'{["速度"]=300;["模式"]="连续运动";["是否等待"]="是";}';'\uF01a'} } ) winform.流程编辑框.addItem( { text={'\uF00c';'\uF1db';70;"调用子程序";'{["调用子程序"]="连续读传感器";["是否等待"]="是";}';'\uF01a'} } ) winform.流程编辑框.addItem( { text={'\uF00c';'\uF1db';260;"调用子程序";'{["调用子程序"]="回字形对准算法";["是否等待"]="是";}';'\uF01a'} } ) winform.流程编辑框.addItem( { text={'\uF00c';'\uF1db';130;"直线运动";'{["速度"]=1000;["模式"]="相对运动";["距离"]="2380";["是否等待"]="否";}';'\uF01a'} } ) //自绘 winform.流程编辑框.onnotify = function(id,code,ptr){ if( code == 0xFFFFFFF4/*_NM_CUSTOMDRAW*/ ){ var lvcd = winform.流程编辑框.getNotifyCustomDraw(code,ptr); if( lvcd.nmcd.dwDrawStage == 0x10001/*_CDDS_ITEMPREPAINT*/) return 0x20/*_CDRF_NOTIFYSUBITEMDRAW*/ elseif( lvcd.nmcd.dwDrawStage == 1/*_CDDS_PREPAINT*/ ){ return 0x20/*_CDRF_NOTIFYITEMDRAW*/; } elseif( lvcd.nmcd.dwDrawStage == ( 0x10001/*_CDDS_ITEMPREPAINT*/ | 0x20000/*_CDDS_SUBITEM*/) ){ //注意这里 iSubItem 的索引自0开始( 其他函数通常自1开始 ) var cvs = win.graphics.canvas(); // 创建一个画布 cvs.fromHDC(lvcd.nmcd.hdc); // 传入 hDC var nItem = lvcd.nmcd.dwItemSpec+1; var nSubItem = lvcd.iSubItem; var rc = owner.getItemRect(nItem,nSubItem); if(nSubItem == 3){ var RetRc = ::RECT(rc.left+1,rc.top+6,rc.right-tonumber(owner.getItemText(nItem,3)),rc.bottom-6); cvs.brush.color = 0x00ff00; cvs.fillRect(RetRc) } cvs.pen.color = 0xebebeb; // 定义画笔的颜色 cvs.drawEdge(rc); lvcd.update() cvs.destroy(); return 0/*_CDRF_DODEFAULT*/ } } } //演示更新进度 winform.button.oncommand = function(id,event){ winform.流程编辑框.setItemText(tostring(math.random(10,280)),2,3); } winform.show() win.loopMessage();
import win.ui; /*DSG{{*/ var winform = win.form(text="aardio form";right=945;bottom=474) winform.add( 流程编辑框={cls="listview";left=0;top=0;right=946;bottom=350;edge=1;font=LOGFONT(name='FontAwesome';h=-19);fullRow=1;z=1} ) /*}}*/ import win.fontAwesome; import win.graphics; import win.imageList; var imagelist = win.imageList(5,34); winform.流程编辑框.setImageList( imagelist,1/*_LVSIL_SMALL*/ ); winform.流程编辑框.insertColumn("",30,,0x2/*_LVCFMT_CENTER*/) winform.流程编辑框.insertColumn("中断",80,,0x2/*_LVCFMT_CENTER*/) winform.流程编辑框.insertColumn("备注",300,,0x0/*_LVCFMT_LEFT*/) winform.流程编辑框.insertColumn("功能",100,,0x0/*_LVCFMT_LEFT*/) winform.流程编辑框.insertColumn("参数",300,,0x0/*_LVCFMT_LEFT*/) winform.流程编辑框.insertColumn("",30,,0x2/*_LVCFMT_CENTER*/) //自适应列宽度 winform.流程编辑框.adjust = function(cx,cy){ winform.流程编辑框.fillParent(5/*列序号*/); } winform.流程编辑框.addItem( { text={'\uF00c';'\uF1db';"X轴前进到对准位置";"直线运动";'{["速度"]=1000;["模式"]="相对运动";["距离"]="2380";["是否等待"]="否";}';'\uF01a'} } ) winform.流程编辑框.addItem( { text={'\uF00d';'\uF05e';"Z轴缓慢前进";"直线运动";'{["速度"]=300;["模式"]="连续运动";["是否等待"]="是";}';'\uF01a'} } ) winform.流程编辑框.addItem( { text={'\uF00c';'\uF1db';"连续读传感器值直到大于0.8";"调用子程序";'{["调用子程序"]="连续读传感器";["是否等待"]="是";}';'\uF01a'} } ) winform.流程编辑框.addItem( { text={'\uF00c';'\uF1db';"对准操作";"调用子程序";'{["调用子程序"]="回字形对准算法";["是否等待"]="是";}';'\uF01a'} } ) //自绘 winform.流程编辑框.onnotify = function(id,code,ptr){ if( code == 0xFFFFFFF4/*_NM_CUSTOMDRAW*/ ){ var lvcd = winform.流程编辑框.getNotifyCustomDraw(code,ptr); console.log( "------------------------" ) console.log( lvcd.nmcd.dwDrawStage ) if( lvcd.nmcd.dwDrawStage == 0x10001/*_CDDS_ITEMPREPAINT*/){ return 0x20/*_CDRF_NOTIFYSUBITEMDRAW*/ } elseif( lvcd.nmcd.dwDrawStage == 1/*_CDDS_PREPAINT*/ ){ return 0x20/*_CDRF_NOTIFYITEMDRAW*/; } elseif( lvcd.nmcd.dwDrawStage == ( 0x10001/*_CDDS_ITEMPREPAINT*/ | 0x20000/*_CDDS_SUBITEM*/) ){ //注意这里 iSubItem 的索引自0开始( 其他函数通常自1开始 ) var cvs = win.graphics.canvas(); // 创建一个画布 cvs.fromHDC(lvcd.nmcd.hdc); // 传入 hDC var nItem = lvcd.nmcd.dwItemSpec+1; var nSubItem = lvcd.iSubItem; var rc = owner.getItemRect(nItem,nSubItem); cvs.pen.color = 0xebebeb; // 定义画笔的颜色 cvs.drawEdge(rc); lvcd.update() cvs.destroy(); return 0/*_CDRF_DODEFAULT*/ } } winform.show() win.loopMessage();
用下面的代码替换画edge可以实现画任意颜色
cvs.pen.color = 0xff0000//0xebebeb; // 定义画笔的颜色 //cvs.drawEdge(rc); //左上到右上 cvs.moveTo(rc.left, rc.top); // 落笔 cvs.lineTo(rc.right, rc.top); // 提笔 //右上到右下 cvs.moveTo(rc.right, rc.top); // 落笔 cvs.lineTo(rc.right, rc.bottom); // 提笔 //右下到左下 cvs.moveTo(rc.right, rc.bottom); // 落笔 cvs.lineTo(rc.left, rc.bottom); // 提笔 //左下到左上 cvs.moveTo(rc.left, rc.bottom); // 落笔 cvs.lineTo(rc.left, rc.top); // 提笔
登录后方可回帖
于是aar中应该这样写:
最后一列边框没显示出来.(⊙o⊙)…
试了几种办法都不行, 暂时先这样用了,对我来说不影响,后续有其他方案在修改更新.