CListCtrl自绘背景图片 是这样的,我的界面都是用自绘的,如果用Invalidate(),刷新时感觉整个界面都闪动一次,用InvalidateRect(),只刷新CListCtrl区域,我查了一下资料,据说用,InvalidateRect()后马上调用UpdateWindow()我试过了,也没用! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 对话框中InvalidateRect()。不行的要m_list。InvalidateRect(),有没有UpdateWindow()无所谓。也可以:m_List.RedrawWindow void CMy3dvstarDlg::OnBnClickedDelete(){ // TODO: 在此添加控件通知处理程序代码 CRect rect; m_list.GetClientRect(&rect); //InvalidateRect(NULL,false); int total = m_list.GetItemCount(); for(int i=total-1;i>=0;i--)//删除所选中的项,如果循环从小到大,那么后面的小标会发生改变,删除一个后,后面的不会删除,直到下一次点击delete { if(m_list.m_bItemCheckState[i]) { m_list.DeleteItem(i); m_list.m_bItemCheckState[i]=false;//更新状态 InvalidateRect(&rect,false); } total=m_list.GetItemCount(); } //UpdateWindow(); //Invalidate(); InvalidateRect(&rect,true); UpdateWindow(); //InvalidateRect(NULL,true);}这是我的删除CListCtrl的记录的函数 RedrawWindow后面两个参数什么意思啊m_list.RedrawWindow(&rect,,RDW_UPDATENOW); 如果是报表模式 推荐看看 Codeproject 上的 MFC Grid Ctrl 用双缓冲应该可以的,我也是用双缓冲自绘的,不难 你试试。//缓存dc背景CDC m_dcMem;CBitmap m_bmpMem;m_pDC = GetDC();m_dcMem.CreateCompatibleDC(m_pDC);m_bmpMem.CreateCompatibleBitmap(m_pDC, rc.Width(), rc.Height());CBitmap *poldbmp = m_dcMem.SelectObject(&m_bmpMem);//开始绘制Graphics g(m_dcMem.m_hDC);g.DrawImage(&pGif,RectF(rc.right,rc.top,100,100),0,0,100,100,UnitPixel); //这里绘制控件背景图//把缓存DC贴出来m_pDC->BitBlt(rect.left,rect.top,100,rect.Height(), &m_dcMem, 0, 0, SRCCOPY); //删除资源m_dcMem.SelectObject(poldbmp);g.ReleaseHDC(m_dcMem.m_hDC);ReleaseDC(m_pDC);m_dcMem.DeleteDC();m_bmpMem.DeleteObject();大概这样 你自己根据需要改一改就好了 不难的 呵呵 我也刚学会一点点 用双缓冲这样写错了吗?我的怎么没用啊void CListCtrlCl::OnPaint() { CListCtrl::OnPaint(); CPaintDC dc(this);//画设备内容 CRect rect; GetClientRect(&rect); CDC MemDC; MemDC.CreateCompatibleDC(&dc);//创建一个与指定设备兼容的内存设备上下文环境(DC) CBitmap memBmp; memBmp.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());//创建与指定的设备环境相关的设备兼容的位图 //成功返回位图句柄 CBitmap* pOldMemBmp=MemDC.SelectObject(&memBmp); //画背景图片到内存中 //CBitmap* pnewbmp=dc.SelectObject(&m_Bmp); MemDC.BitBlt(0,0,rect.Width(),rect.Height(),&dc,0,0,SRCCOPY);//保存图片 dc.SelectObject(pOldMemBmp); //dc.SelectObject(pnewbmp);//选择一对象到指定的设备上下文环境中 rect.top=0; rect.left=0; rect.right=rect.Width(); rect.bottom=rect.top+rect.Height();//GetItemHeight(0); int size=GetHeaderCtrl()->GetItemCount();//GetCount(); for(int i=0;i<size&&rect.top<rect.Height();i++) { rect.OffsetRect(0,20); } dc.BitBlt(0,0,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY);//绘图 MemDC.SelectObject(pOldMemBmp); } 把你的DrawItem贴出来看下 呵呵 一起探讨下 void CListCtrlCl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){ /*绘制背景图片*/ CDC* dc=GetDC(); CRect rect; GetClientRect(&rect); int Width=rect.Width(); int Height=rect.Height(); CDC MemDC; MemDC.CreateCompatibleDC(dc);//创建一个与指定设备兼容的内存设备上下文环境(DC) CBitmap memBmp; memBmp.CreateCompatibleBitmap(dc,Width,Height);//创建与指定的设备环境相关的设备兼容的位图 //成功返回位图句柄 CBitmap* pOldMemBmp=MemDC.SelectObject(&memBmp); //画背景图片到内存中 CBitmap* pnewbmp=dc->SelectObject(&m_Bmp); MemDC.BitBlt(0,0,Width,Height,dc,0,0,SRCCOPY);//保存图片 dc->SelectObject(pnewbmp);//选择一对象到指定的设备上下文环境中 rect.top=0; rect.left=0; rect.right=Width; rect.bottom=rect.top+Height;//GetItemHeight(0); int size=GetHeaderCtrl()->GetItemCount();//GetCount(); for(int i=0;i<size&&rect.top<Height;i++) { //DrawItem(MemDC,i,rect,i); rect.OffsetRect(0,20); } dc->BitBlt(0,0,Width,Height,&MemDC,0,0,SRCCOPY);//绘图 MemDC.SelectObject(pOldMemBmp); int total=GetItemCount();//设置复选框的状态,界面未刷新 if(m_Header.bFlag==false) { for(int i=0;i<total;i++) { m_bItemCheckState[i] = !m_bItemCheckState[i]; InvalidateRect(NULL,false);//点击列表头复选框时,不会重绘下面的内容 } } m_Header.bFlag=true; if (lpDrawItemStruct->CtlType != ODT_LISTVIEW) return; RECT rectiSubItem = {0}; RECT rectCheckBox = {0}; CDC* pDC; pDC = CDC::FromHandle(lpDrawItemStruct->hDC); WCHAR szBuffer[256] = {0}; int nTotalColumn = 0; CHeaderCtrl* pListHeader = NULL; LV_ITEM lvi; pListHeader = (CHeaderCtrl*)GetDlgItem(0); nTotalColumn = pListHeader->GetItemCount(); //第一列是要显示复选框的一列 pListHeader->GetItemRect(0,&rectCheckBox); //循环地绘制列表控件各个子项 LV_COLUMN lvc;//, lvcprev ; ::ZeroMemory(&lvc, sizeof(lvc)); lvc.mask = LVCF_WIDTH | LVCF_FMT; for(int iColumn=0;GetColumn(iColumn,&lvc);iColumn++) { CDC* pDC; pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CRect rtClient; GetClientRect(&rtClient); if ( iColumn >0 ) { GetColumn(iColumn-1, &lvc) ; lpDrawItemStruct->rcItem.left+= lvc.cx; lpDrawItemStruct->rcItem.right += lpDrawItemStruct->rcItem.left; } CRect rcItem; if (!GetSubItemRect(lpDrawItemStruct->itemID,iColumn,LVIR_LABEL,rcItem)) continue; ::ZeroMemory(&lvi, sizeof(lvi)); lvi.iItem = lpDrawItemStruct->itemID; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iSubItem = iColumn;//0; lvi.pszText = szBuffer; lvi.cchTextMax = sizeof(szBuffer); VERIFY(GetItem(&lvi)); //pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT)); if (iColumn == 0) { rectCheckBox.top = lpDrawItemStruct->rcItem.top; rectCheckBox.bottom = lpDrawItemStruct->rcItem.bottom; m_nRowHeight=lpDrawItemStruct->rcItem.bottom-lpDrawItemStruct->rcItem.top; DrawFrameControl(lpDrawItemStruct->hDC,&rectCheckBox,DFC_BUTTON,DFCS_CHECKED); //绘制复选框 if (m_bItemCheckState[lpDrawItemStruct->itemID]) { m_bItemCheckState[lpDrawItemStruct->itemID]=true; DrawFrameControl(lpDrawItemStruct->hDC,&rectCheckBox,DFC_BUTTON,DFCS_CHECKED);//已选中 }else { m_bItemCheckState[lpDrawItemStruct->itemID]=false; DrawFrameControl(lpDrawItemStruct->hDC,&rectCheckBox,DFC_BUTTON,DFCS_BUTTONCHECK);//未选中 } }else { int len=_tcslen(szBuffer); CRect tRect; GetSubItemRect(lpDrawItemStruct->itemID,iColumn,LVIR_BOUNDS,tRect);//根据lpDrawItemStruct->itemID获取当前单元格的tRect CSize pixLen=pDC->GetTextExtent(szBuffer,len);//获得所选字体中指定字符串的高度和宽度 if(pixLen.cx<tRect.Width())//如果字符串的宽度小于单元格的宽度 pDC->DrawText(szBuffer,len,&lpDrawItemStruct->rcItem,DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT);//画文字 else pDC->DrawText(szBuffer,tRect.Width(),&tRect,DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT);//画文字,tRect当前单元格矩形框的大小,tRect.Width()单元格宽度 pDC->DrawEdge(&lpDrawItemStruct->rcItem,EDGE_RAISED,BF_BOTTOM);//下划线 } UINT uFormat=DT_CENTER ; if (m_Header.m_Format[iColumn]=='0') { uFormat = DT_LEFT; }else if (m_Header.m_Format[iColumn]=='1') { uFormat = DT_CENTER; }else if (m_Header.m_Format[iColumn]=='2') { uFormat = DT_RIGHT; } }} 好像不是图片的问题,我现在纳闷的时,我在OnPaint函数中给CListCtrl画横线为什么没效果呢? 你要明白整个过程。如果你还是用我给你的结构。(即 使用DefWindowProc)那么。已经给了一个MemDC了,DefWindowProc(WM_PAINT,MemDC.m_hDC)你的自绘将画在这个MemDC上。而:[color=#FF0000]CDC* dc=GetDC();这句把原来给的DC破坏了。[/color]即使不用我给你的结构,也不能要这句,因为:LPDRAWITEMSTRUCT lpDrawItemStruct里有DC。 我后面把他改成CDC* dc=CDC::FromHandle(lpDrawItemStruct->hDC);如果函数里面有DC我不能重新定义一个吗? "如果函数里面有DC我不能重新定义一个吗?"为什么重新定义一个?如果给你的是一个MemDC,你再 dc=GetDC();那么 你画的东西就会到窗口DC(GetDC()的结果)上,另外 DrawItem会调用 Items 次,每次给你的DC 有上次 绘制内容。总之 重新定义一个 是错误的。 正如我贴出来的DrawItem函数我在画完CListCtrl的文本后画线pDC->DrawEdge(&lpDrawItemStruct->rcItem,EDGE_RAISED,BF_BOTTOM);//下划线没添加一行都会画一行,然后在OnNMCustomdraw函数中画剩余部分的线,我想知道这样写是不是每次添加一行下面的都会重绘,这样会不会造成闪???void CListCtrlCl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult){ LPNMLVCUSTOMDRAW lpnmcd = (LPNMLVCUSTOMDRAW) pNMHDR; if (lpnmcd ->nmcd.dwDrawStage == CDDS_PREPAINT) { *pResult = CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT; return; } else if (lpnmcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) { *pResult = CDRF_NOTIFYSUBITEMDRAW; return; } else if (lpnmcd ->nmcd.dwDrawStage == (CDDS_SUBITEM|CDDS_ITEMPREPAINT)) { int iItem = lpnmcd->nmcd.dwItemSpec; int iSubItem = lpnmcd->iSubItem; if(iItem >= 0 && iSubItem >= 0) { CRect rSubItem; HDC hDC = lpnmcd->nmcd.hdc; GetSubItemRect(iItem, iSubItem, LVIR_LABEL,rSubItem); if (iSubItem == 0) { rSubItem.left = 0; } rSubItem.NormalizeRect(); CDC dc; dc.Attach(lpnmcd->nmcd.hdc); //DrawSubItem(&dc,iItem,iSubItem,rSubItem,bSelected,bFocus); dc.SetBkMode(TRANSPARENT); CString strText; strText=GetItemText(iItem,iSubItem); dc.DrawText(strText,strText.GetLength(),rSubItem,DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS|DT_LEFT); dc.Detach(); *pResult = CDRF_SKIPDEFAULT; return; } } else if (lpnmcd ->nmcd.dwDrawStage == CDDS_POSTPAINT) { DrawRemainSpace(lpnmcd); *pResult = CDRF_SKIPDEFAULT; return; } *pResult = 0;} 那我应该怎样自绘ClistCtrl的横线(网格线我不要竖线,只要横线)呢?而且只画一次让他不清除??? 通常部分自绘用OnNMCustomdraw全部自绘就不要再OnNMCustomdraw了 那我应该放在哪里才会自绘一次呢?或者说要怎样写才只会画一次,放在OnNMCustomdraw中如果上面有记录的就不会重新画线,但是没有的部分就会重画一次,看上去有点闪 DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)是每个item被调用一次,所以一个item的内容要全部画完就行了。 你调:int total=GetItemCount();//设置复选框的状态,界面未刷新干什么?是每个item被调用一次,所以一个item的内容要全部画完就行了。 调用一次DrawItem可以将插入的一行记录画完,这个我知道,画完一条记录我就在该记录的下面用pDC->DrawEdge(&lpDrawItemStruct->rcItem,EDGE_RAISED,BF_BOTTOM);绘制一条线,但是如果只画有记录的,下面没有内容的看上去就很丑,所以我也要画下面的,现在的问题是,我每添加一条记录,剩余部分的都会画线,而你在画CListCtrl第一条记录时,剩余部分的线已经被画出来了,再次添加的时候线还是会被画,所以界面就会有闪的感觉 你说的item是单个的单元格还是每一行?int total=GetItemCount();//设置复选框的状态,界面未刷新 if(m_Header.bFlag==false) { for(int i=0;i<total;i++) { m_bItemCheckState[i] = !m_bItemCheckState[i]; InvalidateRect(NULL,false);//点击列表头复选框时,不会重绘下面的内容 } } m_Header.bFlag=true;我自绘了CHeaderCtrl继承类,在列头添加了一个复选框,添加上面的代码的目的是,当点击列头复选框时CListCtrl的第一列的复选框进行反选。这个与我绘制横线没关系 vc60安装盘Samples里有一个ROWLIST例子,很好的ListCtrl自绘。你把它的DrawItem好好看看,复制过来,改改就能用。 我在列头添加一个复选框,点击列头复选框,我怎么让CListCtrl的记录的第一列复选框进行刷新呢?我之前用的是在Dlg中用定时器刷新,有没有更好的办法 已经上传到我的资源。‘ROWLIST.rar’//// offsets for first and other columns#define OFFSET_FIRST 2#define OFFSET_OTHER 6void CListViewEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){ CListCtrl& ListCtrl=GetListCtrl(); CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CRect rcItem(lpDrawItemStruct->rcItem); UINT uiFlags = ILD_TRANSPARENT; CImageList* pImageList; int nItem = lpDrawItemStruct->itemID; BOOL bFocus = (GetFocus() == this); COLORREF clrTextSave, clrBkSave; COLORREF clrImage = m_clrBkgnd; static _TCHAR szBuff[MAX_PATH]; LPCTSTR pszText;// get item data LV_ITEM lvi; lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvi.iItem = nItem; lvi.iSubItem = 0; lvi.pszText = szBuff; lvi.cchTextMax = sizeof(szBuff); lvi.stateMask = 0xFFFF; // get all state flags ListCtrl.GetItem(&lvi); BOOL bSelected = (bFocus || (GetStyle() & LVS_SHOWSELALWAYS)) && lvi.state & LVIS_SELECTED; bSelected = bSelected || (lvi.state & LVIS_DROPHILITED);// set colors if item is selected CRect rcAllLabels; ListCtrl.GetItemRect(nItem, rcAllLabels, LVIR_BOUNDS); CRect rcLabel; ListCtrl.GetItemRect(nItem, rcLabel, LVIR_LABEL); rcAllLabels.left = rcLabel.left; if (m_bClientWidthSel && rcAllLabels.right<m_cxClient) rcAllLabels.right = m_cxClient; if (bSelected) { clrTextSave = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT)); clrBkSave = pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT)); pDC->FillRect(rcAllLabels, &CBrush(::GetSysColor(COLOR_HIGHLIGHT))); } else pDC->FillRect(rcAllLabels, &CBrush(m_clrTextBk));// set color and mask for the icon if (lvi.state & LVIS_CUT) { clrImage = m_clrBkgnd; uiFlags |= ILD_BLEND50; } else if (bSelected) { clrImage = ::GetSysColor(COLOR_HIGHLIGHT); uiFlags |= ILD_BLEND50; }// draw state icon UINT nStateImageMask = lvi.state & LVIS_STATEIMAGEMASK; if (nStateImageMask) { int nImage = (nStateImageMask>>12) - 1; pImageList = ListCtrl.GetImageList(LVSIL_STATE); if (pImageList) { pImageList->Draw(pDC, nImage, CPoint(rcItem.left, rcItem.top), ILD_TRANSPARENT); } }// draw normal and overlay icon CRect rcIcon; ListCtrl.GetItemRect(nItem, rcIcon, LVIR_ICON); pImageList = ListCtrl.GetImageList(LVSIL_SMALL); if (pImageList) { UINT nOvlImageMask=lvi.state & LVIS_OVERLAYMASK; if (rcItem.left<rcItem.right-1) { ImageList_DrawEx(pImageList->m_hImageList, lvi.iImage, pDC->m_hDC,rcIcon.left,rcIcon.top, 16, 16, m_clrBkgnd, clrImage, uiFlags | nOvlImageMask); } }// draw item label ListCtrl.GetItemRect(nItem, rcItem, LVIR_LABEL); rcItem.right -= m_cxStateImageOffset; pszText = MakeShortString(pDC, szBuff, rcItem.right-rcItem.left, 2*OFFSET_FIRST); rcLabel = rcItem; rcLabel.left += OFFSET_FIRST; rcLabel.right -= OFFSET_FIRST; pDC->DrawText(pszText,-1,rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);// draw labels for extra columns LV_COLUMN lvc; lvc.mask = LVCF_FMT | LVCF_WIDTH; for(int nColumn = 1; ListCtrl.GetColumn(nColumn, &lvc); nColumn++) { rcItem.left = rcItem.right; rcItem.right += lvc.cx; int nRetLen = ListCtrl.GetItemText(nItem, nColumn, szBuff, sizeof(szBuff)); if (nRetLen == 0) continue; pszText = MakeShortString(pDC, szBuff, rcItem.right - rcItem.left, 2*OFFSET_OTHER); UINT nJustify = DT_LEFT; if(pszText == szBuff) { switch(lvc.fmt & LVCFMT_JUSTIFYMASK) { case LVCFMT_RIGHT: nJustify = DT_RIGHT; break; case LVCFMT_CENTER: nJustify = DT_CENTER; break; default: break; } } rcLabel = rcItem; rcLabel.left += OFFSET_OTHER; rcLabel.right -= OFFSET_OTHER; pDC->DrawText(pszText, -1, rcLabel, nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER); }// draw focus rectangle if item has focus if (lvi.state & LVIS_FOCUSED && bFocus) pDC->DrawFocusRect(rcAllLabels);// set original colors if item was selected if (bSelected) { pDC->SetTextColor(clrTextSave); pDC->SetBkColor(clrBkSave); }}//复制到 CMyListCtrl 后:删除:CListCtrl& ListCtrl=GetListCtrl();// 父类 CListView和 ListCtrl。 ‘ROWLIST.rar’ 0 分http://download.csdn.net/detail/schlafenhamster/4384517 //复制到 CMyListCtrl 后:删除:CListCtrl& ListCtrl=GetListCtrl();// 父类 CListView和 ListCtrl。这句在哪里,我的CListCtrl继承类中没有这一句啊 void CListViewEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){CListCtrl& ListCtrl=GetListCtrl();因为他是CListView所以要这句取List你从list派生就不要这句了。下面所有ListCtrl.都去掉 幸好我把关键代码贴出来了。void CListViewEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)你改改。不要头文件的,缺什么变量你定义一个就行。 MakeShortString函数主要干嘛的? MakeShortString函数就是解决你以前说的列宽不够 text写到下一列的问题。 我之前把与ListCtrl变量相关的全删了,当我添加一条记录时,不会画横线啊,当我点击的时候才会有横线,而且没有文字的部分就没有横线,我的目的是想让CListCtrl自绘横线,但是不要每次添加一条记录时没有文字的部分都重新画一次?但是好像不行 CListCtrl自绘横线就是TextOut后,再LineTo 没有记录的地方呢?也用LineTo也行,但是我在动态的增加一条记录,就是把以前的覆盖重画一次吗?但是那样看上去感觉有记录的地方没有闪动,没有记录的地方就闪动,因为他重画了?有没有什么办法只让没有记录的地方画一次呢? CListCtrl不是有很多行吗?有的行填了数据,有的没有填,用LineTo画了?你是说插入一条数据就画一条横线?还是一次画CListCtrl可视区域的所有的横线? 是这样的,我知道CListCtrl中的行是用insert插入的,但是有的情况是没有完全插满啊?比如说,我只插入三条记录即三行,而当前CListCtrl窗口的大小可以看到十行,如果我只在插入一条记录后才画一条横线(自绘横线,而不是ClistCtrl的网格),那么下面还有七行的横线不就没有画了吗? '而当前CListCtrl窗口的大小可以看到十行'你是说窗口大小是十行,你没插入不用管吧另外:LPCTSTR CListViewEx::MakeShortString(CDC* pDC, LPCTSTR lpszLong, int nColumnLen, int nOffset){ static const _TCHAR szThreeDots[] = _T("..."); int nStringLen = lstrlen(lpszLong); if(nStringLen == 0 || (pDC->GetTextExtent(lpszLong, nStringLen).cx + nOffset) <= nColumnLen) { return(lpszLong); } static _TCHAR szShort[MAX_PATH]; lstrcpy(szShort,lpszLong); int nAddLen = pDC->GetTextExtent(szThreeDots,sizeof(szThreeDots)).cx; for(int i = nStringLen-1; i > 0; i--) { szShort[i] = 0; if((pDC->GetTextExtent(szShort, i).cx + nOffset + nAddLen) <= nColumnLen) { break; } } lstrcat(szShort, szThreeDots); return(szShort);} '那样看上去不是很怪吗'ListCtrl就是这样,Grid控件可以无数据有Grid 唉,我就是在OnNMCustomdraw中画剩余部分的横线,但是画线的位置控制不好,好像每次画的都会有点偏移,看上去有点怪,但是他又会把之前的重画一次,所以就感觉上像闪,但又不是 void CListCtrlCl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar){ CRect listRect; GetClientRect(&listRect); InvalidateRect(&listRect); CListCtrl::OnVScroll(nSBCode,nPos,pScrollBar);}背景图片不动,但是文字重叠,这怎么解决啊 //CRect listRect;//GetClientRect(&listRect);//InvalidateRect(&listRect); CListCtrl::OnVScroll(nSBCode,nPos,pScrollBar);最后一句会调paint 既然会调OnPaint函数为什么还是文字重叠呢? OnPaint中要加入与滚动条位置有关的代码。 list背景是固定的还是随滚动条滚动的?背景是固定的:CListCtrl::OnVScroll(nSBCode,nPos,pScrollBar);InvalidateRect(&listRect);//固定后在重绘,闪烁! 是随滚动条滚动的:1,背景要大于list2.擦背景时把滚动条位置加上。(scrollinfo) 背景是固定的:CListCtrl::OnVScroll(nSBCode,nPos,pScrollBar);InvalidateRect(&listRect);//固定后在重绘,闪烁! 没明白 InvalidateRect(0);//滚动后再重绘,可能闪烁! 列头要响应click, 就是Invalidte、、再说一遍‘背景是固定的’,任何动作都要 Invalidate。所以闪烁比较厉害。 在列头点击事件中调用Invalidate吗?有没有办法解决闪的问题? 在列头点击事件中调用Invalidate吗?是 "有没有办法解决闪的问题?"使用双缓冲要好一些。这时要用到3个MemDC。一个memDC放背景(就是说背景要放在MemDC中,这样OnEraseBackGrnd就直接返回 TRUE)一个memDC要放LictCtrl的图(即DefWindowProc)一个memDC把他们2个and起来。最后把这个memDC的内容bitblt到dc(CPaintDC dc) 中。dc图形变化一次这样搞是因为看到的闪烁是dc上图形变化的结果,让这个变化过程缩短就可以减小闪烁(但不会一点没有)。 听上去好像有点道理,但是我没做过,我做的就用一个memDC,1.一个memDC放背景(就是说背景要放在MemDC中,这样OnEraseBackGrnd就直接返回 TRUE)这个好像就是我们平时那样截图。2.一个memDC要放LictCtrl的图(即DefWindowProc)我怎么将DefWindowProc的图片放入memDC中呢?3.一个memDC把他们2个and起来。??? void CHeaderCtrlCl::OnHdnItemclickList2(NMHDR *pNMHDR, LRESULT *pResult){ LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR); MessageBox(_T("click")); Invalidate(); // TODO: 在此添加控件通知处理程序代码 *pResult = 0;}没有进来 http://topic.csdn.net/t/20030326/18/1580461.html为什么我只看到了OnNotifyFormat函数? 这个HD有点问题。ON_NOTIFY(HD_CLICKEDA,OnHeadClicked);ON_NOTIFY(HD_CLICKEDW,OnHeadClicked);其实是W的那个会进来。还有:HD_ENDTRACK也是要这样。 我怎么将DefWindowProc的图片放入memDC中呢?我不是给你代码了吗:DefWindowProc(WM_PAINT,memdc.m_hdc)不用这个也可以,把你的自绘放这里。“一个memDC把他们2个and起来。”就是 一个是 SRCCOPY另一个是 SRCAND我的代码你没看懂? 改正:ON_NOTIFY(HDN_ITEMCLICKA,0,OnHeadItemClick);ON_NOTIFY(HDN_ITEMCLICKW,0,OnHeadItemClick);0是Header ID CHeaderCtrl有ON_NOTIFY(HD_CLICKEDW,OnHeadClicked);吗?为什么我的继承类变成只读了,消息都不能添加好奇怪啊 在派生的List中,不是派生的header。Notify是给父类的。 把你的ON_NOTIFY给我看看。(全部有关的) afx_msg void OnHdnItemclick(NMHDR *pNMHDR, LRESULT *pResult);ON_NOTIFY(HDN_ITEMCLICKA, 0, &CListCtrlCl::OnHdnItemclick)ON_NOTIFY(HDN_ITEMCLICKW, 0, &CListCtrlCl::OnHdnItemclick)void CListCtrlCl::OnHdnItemclick(NMHDR *pNMHDR, LRESULT *pResult){ LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 Invalidate(); *pResult = 0;} 还有一个header宽度调整结束时的 HDN_ENDTRACK。也试试。Invalidate(); CDC* dc=GetDC(); CRect rect; GetClientRect(&rect); int Width=rect.Width(); int Height=rect.Height(); CDC MemDC; MemDC.CreateCompatibleDC(dc);//创建一个与指定设备兼容的内存设备上下文环境(DC) CBitmap memBmp; memBmp.CreateCompatibleBitmap(dc,Width,Height);//创建与指定的设备环境相关的设备兼容的位图 //成功返回位图句柄 CBitmap* pOldMemBmp=MemDC.SelectObject(&memBmp); //画背景图片到内存中 MemDC.BitBlt(0,0,Width,Height,dc,0,0,SRCCOPY);//保存图片 rect.top=0; rect.left=0; rect.right=Width; rect.bottom=rect.top+Height; int size=GetHeaderCtrl()->GetItemCount(); for(int i=0;i<size&&rect.top<Height;i++) { rect.OffsetRect(0,20); } dc->BitBlt(0,0,Width,Height,&MemDC,0,0,SRCCOPY);//绘图 MemDC.SelectObject(pOldMemBmp);请教一个问题,我在MemDC.SelectObject(pOldMemBmp);之前可不可以在memBmp上画横线?并且将图片保存,每次刷新后都显示的是这张图片呢???? 大家帮我设计一个socket通讯模型吧!(C++ and Java) 关于在VC++中弹出对话框后显示画面,及如何显示动态曲线的问题 CListCtrl的checkbox,如何调整它的位置在高度上居中??? 一个初学者关于MFC的几个小疑问 请问怎么获得某个进程所创建的互斥量啊 CMSComm控件读写问题 我要疯掉了,一个简单的任务栏图标问题,求救(API)的,MFC莫入 有关强制转换的问题? 100分求vc中能以列表方式显示数据库查询结果的控件。 关于键盘钩子的问题 vs2008使用MFC为什么有些响应函数没法添加呢? 为什么MAKEINTRESOURCE要把一个整数强转成指针类型?
要m_list。InvalidateRect(),有没有UpdateWindow()无所谓。
也可以:
m_List.RedrawWindow
{
// TODO: 在此添加控件通知处理程序代码
CRect rect;
m_list.GetClientRect(&rect);
//InvalidateRect(NULL,false);
int total = m_list.GetItemCount();
for(int i=total-1;i>=0;i--)//删除所选中的项,如果循环从小到大,那么后面的小标会发生改变,删除一个后,后面的不会删除,直到下一次点击delete
{
if(m_list.m_bItemCheckState[i])
{
m_list.DeleteItem(i);
m_list.m_bItemCheckState[i]=false;//更新状态
InvalidateRect(&rect,false);
}
total=m_list.GetItemCount();
}
//UpdateWindow();
//Invalidate();
InvalidateRect(&rect,true);
UpdateWindow();
//InvalidateRect(NULL,true);
}
这是我的删除CListCtrl的记录的函数
CDC m_dcMem;
CBitmap m_bmpMem;m_pDC = GetDC();
m_dcMem.CreateCompatibleDC(m_pDC);
m_bmpMem.CreateCompatibleBitmap(m_pDC, rc.Width(), rc.Height());
CBitmap *poldbmp = m_dcMem.SelectObject(&m_bmpMem);//开始绘制
Graphics g(m_dcMem.m_hDC);
g.DrawImage(&pGif,RectF(rc.right,rc.top,100,100),0,0,100,100,UnitPixel); //这里绘制控件背景图//把缓存DC贴出来
m_pDC->BitBlt(rect.left,rect.top,100,rect.Height(), &m_dcMem, 0, 0, SRCCOPY); //删除资源
m_dcMem.SelectObject(poldbmp);
g.ReleaseHDC(m_dcMem.m_hDC);
ReleaseDC(m_pDC);
m_dcMem.DeleteDC();
m_bmpMem.DeleteObject();
大概这样 你自己根据需要改一改就好了 不难的 呵呵 我也刚学会一点点
void CListCtrlCl::OnPaint()
{
CListCtrl::OnPaint();
CPaintDC dc(this);//画设备内容
CRect rect;
GetClientRect(&rect);
CDC MemDC;
MemDC.CreateCompatibleDC(&dc);//创建一个与指定设备兼容的内存设备上下文环境(DC) CBitmap memBmp;
memBmp.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());//创建与指定的设备环境相关的设备兼容的位图
//成功返回位图句柄
CBitmap* pOldMemBmp=MemDC.SelectObject(&memBmp);
//画背景图片到内存中
//CBitmap* pnewbmp=dc.SelectObject(&m_Bmp);
MemDC.BitBlt(0,0,rect.Width(),rect.Height(),&dc,0,0,SRCCOPY);//保存图片
dc.SelectObject(pOldMemBmp);
//dc.SelectObject(pnewbmp);//选择一对象到指定的设备上下文环境中
rect.top=0;
rect.left=0;
rect.right=rect.Width();
rect.bottom=rect.top+rect.Height();//GetItemHeight(0);
int size=GetHeaderCtrl()->GetItemCount();//GetCount();
for(int i=0;i<size&&rect.top<rect.Height();i++)
{
rect.OffsetRect(0,20);
}
dc.BitBlt(0,0,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY);//绘图
MemDC.SelectObject(pOldMemBmp);
}
{ /*绘制背景图片*/
CDC* dc=GetDC();
CRect rect;
GetClientRect(&rect);
int Width=rect.Width();
int Height=rect.Height();
CDC MemDC;
MemDC.CreateCompatibleDC(dc);//创建一个与指定设备兼容的内存设备上下文环境(DC) CBitmap memBmp;
memBmp.CreateCompatibleBitmap(dc,Width,Height);//创建与指定的设备环境相关的设备兼容的位图
//成功返回位图句柄
CBitmap* pOldMemBmp=MemDC.SelectObject(&memBmp);
//画背景图片到内存中
CBitmap* pnewbmp=dc->SelectObject(&m_Bmp);
MemDC.BitBlt(0,0,Width,Height,dc,0,0,SRCCOPY);//保存图片
dc->SelectObject(pnewbmp);//选择一对象到指定的设备上下文环境中
rect.top=0;
rect.left=0;
rect.right=Width;
rect.bottom=rect.top+Height;//GetItemHeight(0);
int size=GetHeaderCtrl()->GetItemCount();//GetCount();
for(int i=0;i<size&&rect.top<Height;i++)
{
//DrawItem(MemDC,i,rect,i);
rect.OffsetRect(0,20);
}
dc->BitBlt(0,0,Width,Height,&MemDC,0,0,SRCCOPY);//绘图
MemDC.SelectObject(pOldMemBmp); int total=GetItemCount();//设置复选框的状态,界面未刷新
if(m_Header.bFlag==false)
{
for(int i=0;i<total;i++)
{
m_bItemCheckState[i] = !m_bItemCheckState[i];
InvalidateRect(NULL,false);//点击列表头复选框时,不会重绘下面的内容
}
}
m_Header.bFlag=true;
if (lpDrawItemStruct->CtlType != ODT_LISTVIEW)
return;
RECT rectiSubItem = {0};
RECT rectCheckBox = {0};
CDC* pDC;
pDC = CDC::FromHandle(lpDrawItemStruct->hDC); WCHAR szBuffer[256] = {0};
int nTotalColumn = 0; CHeaderCtrl* pListHeader = NULL;
LV_ITEM lvi; pListHeader = (CHeaderCtrl*)GetDlgItem(0);
nTotalColumn = pListHeader->GetItemCount(); //第一列是要显示复选框的一列
pListHeader->GetItemRect(0,&rectCheckBox);
//循环地绘制列表控件各个子项
LV_COLUMN lvc;//, lvcprev ;
::ZeroMemory(&lvc, sizeof(lvc));
lvc.mask = LVCF_WIDTH | LVCF_FMT;
for(int iColumn=0;GetColumn(iColumn,&lvc);iColumn++)
{
CDC* pDC;
pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rtClient;
GetClientRect(&rtClient);
if ( iColumn >0 )
{
GetColumn(iColumn-1, &lvc) ;
lpDrawItemStruct->rcItem.left+= lvc.cx;
lpDrawItemStruct->rcItem.right += lpDrawItemStruct->rcItem.left;
}
CRect rcItem;
if (!GetSubItemRect(lpDrawItemStruct->itemID,iColumn,LVIR_LABEL,rcItem))
continue; ::ZeroMemory(&lvi, sizeof(lvi));
lvi.iItem = lpDrawItemStruct->itemID;
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iSubItem = iColumn;//0;
lvi.pszText = szBuffer;
lvi.cchTextMax = sizeof(szBuffer);
VERIFY(GetItem(&lvi)); //pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT));
if (iColumn == 0)
{
rectCheckBox.top = lpDrawItemStruct->rcItem.top;
rectCheckBox.bottom = lpDrawItemStruct->rcItem.bottom;
m_nRowHeight=lpDrawItemStruct->rcItem.bottom-lpDrawItemStruct->rcItem.top;
DrawFrameControl(lpDrawItemStruct->hDC,&rectCheckBox,DFC_BUTTON,DFCS_CHECKED);
//绘制复选框
if (m_bItemCheckState[lpDrawItemStruct->itemID])
{
m_bItemCheckState[lpDrawItemStruct->itemID]=true;
DrawFrameControl(lpDrawItemStruct->hDC,&rectCheckBox,DFC_BUTTON,DFCS_CHECKED);//已选中
}else
{
m_bItemCheckState[lpDrawItemStruct->itemID]=false;
DrawFrameControl(lpDrawItemStruct->hDC,&rectCheckBox,DFC_BUTTON,DFCS_BUTTONCHECK);//未选中
}
}else
{
int len=_tcslen(szBuffer);
CRect tRect;
GetSubItemRect(lpDrawItemStruct->itemID,iColumn,LVIR_BOUNDS,tRect);//根据lpDrawItemStruct->itemID获取当前单元格的tRect
CSize pixLen=pDC->GetTextExtent(szBuffer,len);//获得所选字体中指定字符串的高度和宽度
if(pixLen.cx<tRect.Width())//如果字符串的宽度小于单元格的宽度
pDC->DrawText(szBuffer,len,&lpDrawItemStruct->rcItem,DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT);//画文字
else
pDC->DrawText(szBuffer,tRect.Width(),&tRect,DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT);//画文字,tRect当前单元格矩形框的大小,tRect.Width()单元格宽度
pDC->DrawEdge(&lpDrawItemStruct->rcItem,EDGE_RAISED,BF_BOTTOM);//下划线
}
UINT uFormat=DT_CENTER ;
if (m_Header.m_Format[iColumn]=='0')
{
uFormat = DT_LEFT;
}else if (m_Header.m_Format[iColumn]=='1')
{
uFormat = DT_CENTER;
}else if (m_Header.m_Format[iColumn]=='2')
{
uFormat = DT_RIGHT;
}
}
}
已经给了一个MemDC了,DefWindowProc(WM_PAINT,MemDC.m_hDC)
你的自绘将画在这个MemDC上。
而:
[color=#FF0000]CDC* dc=GetDC();
这句把原来给的DC破坏了。[/color]即使不用我给你的结构,也不能要这句,因为:
LPDRAWITEMSTRUCT lpDrawItemStruct
里有DC。
为什么重新定义一个?
如果给你的是一个MemDC,
你再 dc=GetDC();
那么 你画的东西就会到窗口DC(GetDC()的结果)上,
另外 DrawItem会调用 Items 次,每次给你的DC 有上次 绘制内容。
总之 重新定义一个 是错误的。
pDC->DrawEdge(&lpDrawItemStruct->rcItem,EDGE_RAISED,BF_BOTTOM);//下划线
没添加一行都会画一行,
然后在OnNMCustomdraw函数中画剩余部分的线,我想知道这样写是不是每次添加一行下面的都会重绘,这样会不会造成闪???
void CListCtrlCl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLVCUSTOMDRAW lpnmcd = (LPNMLVCUSTOMDRAW) pNMHDR;
if (lpnmcd ->nmcd.dwDrawStage == CDDS_PREPAINT)
{
*pResult = CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT;
return;
}
else if (lpnmcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
{
*pResult = CDRF_NOTIFYSUBITEMDRAW;
return;
}
else if (lpnmcd ->nmcd.dwDrawStage == (CDDS_SUBITEM|CDDS_ITEMPREPAINT))
{
int iItem = lpnmcd->nmcd.dwItemSpec;
int iSubItem = lpnmcd->iSubItem;
if(iItem >= 0 && iSubItem >= 0)
{
CRect rSubItem;
HDC hDC = lpnmcd->nmcd.hdc;
GetSubItemRect(iItem, iSubItem, LVIR_LABEL,rSubItem);
if (iSubItem == 0)
{
rSubItem.left = 0;
}
rSubItem.NormalizeRect();
CDC dc;
dc.Attach(lpnmcd->nmcd.hdc);
//DrawSubItem(&dc,iItem,iSubItem,rSubItem,bSelected,bFocus);
dc.SetBkMode(TRANSPARENT);
CString strText;
strText=GetItemText(iItem,iSubItem);
dc.DrawText(strText,strText.GetLength(),rSubItem,DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS|DT_LEFT);
dc.Detach();
*pResult = CDRF_SKIPDEFAULT;
return;
}
}
else if (lpnmcd ->nmcd.dwDrawStage == CDDS_POSTPAINT)
{
DrawRemainSpace(lpnmcd);
*pResult = CDRF_SKIPDEFAULT;
return;
}
*pResult = 0;
}
全部自绘就不要再OnNMCustomdraw了
那我应该放在哪里才会自绘一次呢?或者说要怎样写才只会画一次,放在OnNMCustomdraw中如果上面有记录的就不会重新画线,但是没有的部分就会重画一次,看上去有点闪
是每个item被调用一次,
所以一个item的内容要全部画完就行了。
int total=GetItemCount();//设置复选框的状态,界面未刷新
干什么?
是每个item被调用一次,
所以一个item的内容要全部画完就行了。
调用一次DrawItem可以将插入的一行记录画完,这个我知道,画完一条记录我就在该记录的下面用pDC->DrawEdge(&lpDrawItemStruct->rcItem,EDGE_RAISED,BF_BOTTOM);绘制一条线,但是如果只画有记录的,下面没有内容的看上去就很丑,所以我也要画下面的,现在的问题是,我每添加一条记录,剩余部分的都会画线,而你在画CListCtrl第一条记录时,剩余部分的线已经被画出来了,再次添加的时候线还是会被画,所以界面就会有闪的感觉
你说的item是单个的单元格还是每一行?int total=GetItemCount();//设置复选框的状态,界面未刷新
if(m_Header.bFlag==false)
{
for(int i=0;i<total;i++)
{
m_bItemCheckState[i] = !m_bItemCheckState[i];
InvalidateRect(NULL,false);//点击列表头复选框时,不会重绘下面的内容
}
}
m_Header.bFlag=true;我自绘了CHeaderCtrl继承类,在列头添加了一个复选框,添加上面的代码的目的是,当点击列头复选框时CListCtrl的第一列的复选框进行反选。这个与我绘制横线没关系
你把它的DrawItem好好看看,复制过来,改改就能用。
‘ROWLIST.rar’
//
// offsets for first and other columns
#define OFFSET_FIRST 2
#define OFFSET_OTHER 6void CListViewEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CListCtrl& ListCtrl=GetListCtrl();
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rcItem(lpDrawItemStruct->rcItem);
UINT uiFlags = ILD_TRANSPARENT;
CImageList* pImageList;
int nItem = lpDrawItemStruct->itemID;
BOOL bFocus = (GetFocus() == this);
COLORREF clrTextSave, clrBkSave;
COLORREF clrImage = m_clrBkgnd;
static _TCHAR szBuff[MAX_PATH];
LPCTSTR pszText;// get item data LV_ITEM lvi;
lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
lvi.iItem = nItem;
lvi.iSubItem = 0;
lvi.pszText = szBuff;
lvi.cchTextMax = sizeof(szBuff);
lvi.stateMask = 0xFFFF; // get all state flags
ListCtrl.GetItem(&lvi); BOOL bSelected = (bFocus || (GetStyle() & LVS_SHOWSELALWAYS)) && lvi.state & LVIS_SELECTED;
bSelected = bSelected || (lvi.state & LVIS_DROPHILITED);// set colors if item is selected CRect rcAllLabels;
ListCtrl.GetItemRect(nItem, rcAllLabels, LVIR_BOUNDS); CRect rcLabel;
ListCtrl.GetItemRect(nItem, rcLabel, LVIR_LABEL); rcAllLabels.left = rcLabel.left;
if (m_bClientWidthSel && rcAllLabels.right<m_cxClient)
rcAllLabels.right = m_cxClient; if (bSelected)
{
clrTextSave = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
clrBkSave = pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT)); pDC->FillRect(rcAllLabels, &CBrush(::GetSysColor(COLOR_HIGHLIGHT)));
}
else
pDC->FillRect(rcAllLabels, &CBrush(m_clrTextBk));// set color and mask for the icon if (lvi.state & LVIS_CUT)
{
clrImage = m_clrBkgnd;
uiFlags |= ILD_BLEND50;
}
else if (bSelected)
{
clrImage = ::GetSysColor(COLOR_HIGHLIGHT);
uiFlags |= ILD_BLEND50;
}// draw state icon UINT nStateImageMask = lvi.state & LVIS_STATEIMAGEMASK;
if (nStateImageMask)
{
int nImage = (nStateImageMask>>12) - 1;
pImageList = ListCtrl.GetImageList(LVSIL_STATE);
if (pImageList)
{
pImageList->Draw(pDC, nImage,
CPoint(rcItem.left, rcItem.top), ILD_TRANSPARENT);
}
}// draw normal and overlay icon CRect rcIcon;
ListCtrl.GetItemRect(nItem, rcIcon, LVIR_ICON); pImageList = ListCtrl.GetImageList(LVSIL_SMALL);
if (pImageList)
{
UINT nOvlImageMask=lvi.state & LVIS_OVERLAYMASK;
if (rcItem.left<rcItem.right-1)
{
ImageList_DrawEx(pImageList->m_hImageList, lvi.iImage,
pDC->m_hDC,rcIcon.left,rcIcon.top, 16, 16,
m_clrBkgnd, clrImage, uiFlags | nOvlImageMask);
}
}// draw item label ListCtrl.GetItemRect(nItem, rcItem, LVIR_LABEL);
rcItem.right -= m_cxStateImageOffset; pszText = MakeShortString(pDC, szBuff,
rcItem.right-rcItem.left, 2*OFFSET_FIRST); rcLabel = rcItem;
rcLabel.left += OFFSET_FIRST;
rcLabel.right -= OFFSET_FIRST; pDC->DrawText(pszText,-1,rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);// draw labels for extra columns LV_COLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH; for(int nColumn = 1; ListCtrl.GetColumn(nColumn, &lvc); nColumn++)
{
rcItem.left = rcItem.right;
rcItem.right += lvc.cx; int nRetLen = ListCtrl.GetItemText(nItem, nColumn,
szBuff, sizeof(szBuff));
if (nRetLen == 0)
continue; pszText = MakeShortString(pDC, szBuff,
rcItem.right - rcItem.left, 2*OFFSET_OTHER); UINT nJustify = DT_LEFT; if(pszText == szBuff)
{
switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
{
case LVCFMT_RIGHT:
nJustify = DT_RIGHT;
break;
case LVCFMT_CENTER:
nJustify = DT_CENTER;
break;
default:
break;
}
} rcLabel = rcItem;
rcLabel.left += OFFSET_OTHER;
rcLabel.right -= OFFSET_OTHER; pDC->DrawText(pszText, -1, rcLabel,
nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
}// draw focus rectangle if item has focus if (lvi.state & LVIS_FOCUSED && bFocus)
pDC->DrawFocusRect(rcAllLabels);// set original colors if item was selected if (bSelected)
{
pDC->SetTextColor(clrTextSave);
pDC->SetBkColor(clrBkSave);
}
}
//复制到 CMyListCtrl 后:
删除:CListCtrl& ListCtrl=GetListCtrl();// 父类 CListView
和 ListCtrl。
http://download.csdn.net/detail/schlafenhamster/4384517
删除:CListCtrl& ListCtrl=GetListCtrl();// 父类 CListView
和 ListCtrl。这句在哪里,我的CListCtrl继承类中没有这一句啊
{
CListCtrl& ListCtrl=GetListCtrl();
因为他是CListView所以要这句取List你从list派生就不要这句了。
下面所有ListCtrl.都去掉
void CListViewEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
你改改。
不要头文件的,缺什么变量你定义一个就行。
就是TextOut后,再LineTo
但是那样看上去感觉有记录的地方没有闪动,没有记录的地方就闪动,因为他重画了?有没有什么办法只让没有记录的地方画一次呢?
你是说窗口大小是十行,你没插入不用管吧
另外:LPCTSTR CListViewEx::MakeShortString(CDC* pDC, LPCTSTR lpszLong, int nColumnLen, int nOffset)
{
static const _TCHAR szThreeDots[] = _T("..."); int nStringLen = lstrlen(lpszLong); if(nStringLen == 0 ||
(pDC->GetTextExtent(lpszLong, nStringLen).cx + nOffset) <= nColumnLen)
{
return(lpszLong);
} static _TCHAR szShort[MAX_PATH]; lstrcpy(szShort,lpszLong);
int nAddLen = pDC->GetTextExtent(szThreeDots,sizeof(szThreeDots)).cx; for(int i = nStringLen-1; i > 0; i--)
{
szShort[i] = 0;
if((pDC->GetTextExtent(szShort, i).cx + nOffset + nAddLen)
<= nColumnLen)
{
break;
}
} lstrcat(szShort, szThreeDots);
return(szShort);
}
ListCtrl就是这样,
Grid控件可以无数据有Grid
{
CRect listRect;
GetClientRect(&listRect);
InvalidateRect(&listRect);
CListCtrl::OnVScroll(nSBCode,nPos,pScrollBar);
}
背景图片不动,但是文字重叠,这怎么解决啊
//GetClientRect(&listRect);
//InvalidateRect(&listRect);
CListCtrl::OnVScroll(nSBCode,nPos,pScrollBar);
最后一句会调paint
背景是固定的:
CListCtrl::OnVScroll(nSBCode,nPos,pScrollBar);
InvalidateRect(&listRect);//固定后在重绘,闪烁!
是随滚动条滚动的:
1,背景要大于list
2.擦背景时把滚动条位置加上。(scrollinfo)
CListCtrl::OnVScroll(nSBCode,nPos,pScrollBar);
InvalidateRect(&listRect);//固定后在重绘,闪烁! 没明白
、、
再说一遍‘背景是固定的’,任何动作都要 Invalidate。
所以闪烁比较厉害。
在列头点击事件中调用Invalidate吗?有没有办法解决闪的问题?
是
使用双缓冲要好一些。
这时要用到3个MemDC。
一个memDC放背景(就是说背景要放在MemDC中,这样OnEraseBackGrnd就直接返回 TRUE)
一个memDC要放LictCtrl的图(即DefWindowProc)
一个memDC把他们2个and起来。
最后把这个memDC的内容bitblt到dc(CPaintDC dc) 中。dc图形变化一次
这样搞是因为看到的闪烁是dc上图形变化的结果,让这个变化过程缩短就可以减小闪烁(但不会一点没有)。
这个好像就是我们平时那样截图。
2.一个memDC要放LictCtrl的图(即DefWindowProc)
我怎么将DefWindowProc的图片放入memDC中呢?3.一个memDC把他们2个and起来。???
void CHeaderCtrlCl::OnHdnItemclickList2(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
MessageBox(_T("click"));
Invalidate();
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
}
没有进来
ON_NOTIFY(HD_CLICKEDA,OnHeadClicked);
ON_NOTIFY(HD_CLICKEDW,OnHeadClicked);
其实是W的那个会进来。
还有:
HD_ENDTRACK也是要这样。
我不是给你代码了吗:
DefWindowProc(WM_PAINT,memdc.m_hdc)
不用这个也可以,把你的自绘放这里。“一个memDC把他们2个and起来。”
就是 一个是 SRCCOPY
另一个是 SRCAND我的代码你没看懂?
ON_NOTIFY(HDN_ITEMCLICKA,0,OnHeadItemClick);
ON_NOTIFY(HDN_ITEMCLICKW,0,OnHeadItemClick);0是Header ID
CHeaderCtrl有ON_NOTIFY(HD_CLICKEDW,OnHeadClicked);吗?为什么我的继承类变成只读了,消息都不能添加好奇怪啊
Notify是给父类的。
ON_NOTIFY(HDN_ITEMCLICKW, 0, &CListCtrlCl::OnHdnItemclick)void CListCtrlCl::OnHdnItemclick(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
Invalidate();
*pResult = 0;
}
也试试。
Invalidate();
CRect rect;
GetClientRect(&rect);
int Width=rect.Width();
int Height=rect.Height();
CDC MemDC;
MemDC.CreateCompatibleDC(dc);//创建一个与指定设备兼容的内存设备上下文环境(DC) CBitmap memBmp;
memBmp.CreateCompatibleBitmap(dc,Width,Height);//创建与指定的设备环境相关的设备兼容的位图
//成功返回位图句柄
CBitmap* pOldMemBmp=MemDC.SelectObject(&memBmp);
//画背景图片到内存中
MemDC.BitBlt(0,0,Width,Height,dc,0,0,SRCCOPY);//保存图片
rect.top=0;
rect.left=0;
rect.right=Width;
rect.bottom=rect.top+Height;
int size=GetHeaderCtrl()->GetItemCount();
for(int i=0;i<size&&rect.top<Height;i++)
{
rect.OffsetRect(0,20);
} dc->BitBlt(0,0,Width,Height,&MemDC,0,0,SRCCOPY);//绘图
MemDC.SelectObject(pOldMemBmp);请教一个问题,我在MemDC.SelectObject(pOldMemBmp);之前可不可以在memBmp上画横线?并且将图片保存,每次刷新后都显示的是这张图片呢????