分享

NM_CUSTOMDRAW自绘控件简介

 3D建模仿真 2014-09-09
此例以list控件中添加edit和改变字体和项的背景色为例
1、添加自定义类CListCtrlWithCustomDraw继承与CListCtrl
2、在类面板中右键CListCtrlWithCustomDraw属性添加OnNMCustomdraw方法
3、开始绘制
void CListCtrlWithCustomDraw::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLVCUSTOMDRAW lpLVCustomDraw = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
switch ( lpLVCustomDraw->nmcd.dwDrawStage )
{
case CDDS_PREPAINT:
{
*pResult = CDRF_NOTIFYITEMDRAW;
}
break;
case CDDS_ITEMPREPAINT :
{
if ( lpLVCustomDraw->nmcd.dwItemSpec % 2 == 0)
{
lpLVCustomDraw->clrText = RGB(255,0 ,0);  // 设置字体颜色
lpLVCustomDraw->clrTextBk = RGB(0,255,255); // 背景色
}
else
{
lpLVCustomDraw->clrText = RGB(0,255, 0);
lpLVCustomDraw->clrTextBk = RGB(255,0,255);
}

*pResult = CDRF_NOTIFYITEMDRAW/*CDRF_DODEFAULT*/; 
}
break;
}
case CDDS_ITEMPREPAINT|CDDS_SUBITEM:
{
if (    lpLVCustomDraw->iSubItem == 2)// 在每行的第三列添加edit控件
{
CreateCtrl(lpLVCustomDraw->nmcd.dwItemSpec, lpLVCustomDraw->iSubItem);
}
*pResult = CDRF_DODEFAULT;
}
break;
}

}

4、添加edit的接口
void CListCtrlWithCustomDraw::CreateCtrl(int nItem, int nSubItem)
{
CRect rect;
int offset = 0;
GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rect);
// Now scroll if we need to expose the column
CRect rcClient;
GetClientRect(rcClient);
if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
{
CSize size(offset + rect.left,0); 
Scroll(size);
rect.left -= size.cx;
}
rect.left += offset;
rect.right = rect.left + GetColumnWidth(nSubItem);
if(rect.right > rcClient.right)
rect.right = rcClient.right;
// Get Column alignment
LV_COLUMN lvcol;
lvcol.mask = LVCF_FMT;
GetColumn(nSubItem, &lvcol);
DWORD dwStyle;
if((lvcol.fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT)
dwStyle = ES_LEFT;
else if((lvcol.fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_RIGHT)
dwStyle = ES_RIGHT;
else
dwStyle = ES_CENTER;

dwStyle |=WS_BORDER|WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL;
CEdit *pEdit = NULL;
CString strText = GetItemText(nItem, nSubItem);
pEdit = new CEdit;
pEdit->Create(dwStyle, rect, this, 0xff);
pEdit->SetWindowText(strText);
pEdit->SetFont(GetFont());
EDIT_LIST* edit_info = new EDIT_LIST;
memset(edit_info, NULL, sizeof(EDIT_LIST));
edit_info->nItem = nItem;
edit_info->nSubItem = nSubItem;
edit_info->pEdit = pEdit;
m_vecEditlist.push_back(edit_info);
}

5、表头移动时要重新设置edit控件的位置, 在CDDS_ITEMPREPAINT|CDDS_SUBITEM中添加
CRect rect;
GetSubItemRect(lpLVCustomDraw->nmcd.dwItemSpec, lpLVCustomDraw->iSubItem, LVIR_BOUNDS, rect);
vector<EDIT_LIST*>::iterator it = m_vecEditlist.begin();
while ( it != m_vecEditlist.end())
{
EDIT_LIST* pEDit = (*it);
if ( pEDit != NULL && pEDit->nItem == lpLVCustomDraw->nmcd.dwItemSpec
&& pEDit->nSubItem == lpLVCustomDraw->iSubItem)
{
pEDit->pEdit->MoveWindow(rect);
}
++it;
}
6、拖动是可有能闪烁, 可以用双缓冲画背景来解决闪烁
void CListCtrlWithCustomDraw::OnPaint()
{
//双缓冲画背景
CPaintDC dc(this); // device context for painting
CRect rect; 
CRect headerRect; 
CDC MenDC;      //内存DC    
CBitmap MemMap;
GetClientRect(&rect);     
GetDlgItem(0)->GetWindowRect(&headerRect);
MenDC.CreateCompatibleDC(&dc);
MemMap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
MenDC.SelectObject(&MemMap);
MenDC.FillSolidRect(&rect,RGB(255,255,255));    

//调用默认的OnPaint(),把图形画在内存DC表上
DefWindowProc(WM_PAINT,(WPARAM)MenDC.m_hDC,(LPARAM)0);    

//输出到显示设备 
dc.BitBlt(0,headerRect.Height(),
rect.Width(),
rect.Height(),
&MenDC,
0,
headerRect.Height(),
SRCCOPY);
MenDC.DeleteDC();
MemMap.DeleteObject();
}
运行结果:
添加其他的控件也是一样的, 将edit替换就可以!!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多