用CListCtrl 我能在某行某列的item上画图吗 能的话怎么实现??? 用CListCtrl 我能在某行某列的item上画图吗 能的话怎么实现???谢谢 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 设置 OwnerDraw 属性,然后 OnDrawItem,可以获取 Item 的 Rect 画图。 可以的,你需要进行手工重绘拦截CListCtrl的NM_CUSTOMDRAW消息并进行重绘即可 是不是要CListCtrl的Item显示的图不是从资源加载的,而是自己画的?我做过,方法很笨,我也没有想到更好的方法。 我的方法是让CListCtrl和一个CImageList关联,CListCtrl里面的图都从CImageList里面来取。而CImageList的图则不是从资源中Load,而是自己在MemDc里画好的。 HIMAGELIST hListShow = ImageList_Create(64,64, ILC_COLOR8 |ILC_MASK ,10, 1);//有10个图片 CImageList m_ImageListShow.Attach(hListShow); /////////////////////////////////////////////////////////////////// //////drawPtn(); //在MemDC上画图然后add到CImageList上(重点)///////// ////////////////////////////////////////////////////////////////// m_LCShowPtn.DeleteAllItems(); m_LCShowPtn.SetImageList(&m_ImageListShow, LVSIL_NORMAL);//m_LCShowPtn是与CListCtrl关联的变量 LVITEM lvi; CString strItem; for(int i=0;i<100;i++) lvi.mask = LVIF_IMAGE | LVIF_TEXT; strItem.Format("%d",i+1); lvi.iItem = i; lvi.iSubItem = 0; lvi.pszText = (LPTSTR)(LPCTSTR)(strItem); lvi.iImage = i%10;//ImageList的图标编号从0开始有10个图就是0到9 m_LCShowPtn.InsertItem(&lvi);/////////////////////////////////////////////////////////////////////////////////////////// 现在讲下画图的方法,这个地方找不到很好的办法,很郁闷。 首先说下CImageList的Add函数(CBitmap *,COLOR);前一个参数是一个位图指针,后一个参数就是屏蔽色表示该颜色会被透明掉。 所以当你获得你画好的位图指针PBitmap后用m_ImageListShow.Add(PBitmap, RGB(192,192, 192));就可以了。 绘图过程如下, void C****::draw() { CClientDC dc(this); CBitmap PtnBitmap; CBitmap* pbmOld = NULL; CRect CirRect; CDC dcMem; dcMem.CreateCompatibleDC(&dc); PtnBitmap.CreateCompatibleBitmap(&dc, 100, 100); //位图大小是100*100 pbmOld = dcMem.SelectObject(&PtnBitmap); //绘制操作 CPen penB(PS_SOLID,3,RGB(0,255,255)); CPen* pOldPen=dcMem.SelectObject (&penB); dcMem.MoveTo(0,50); dcMem.LineTo(100,50); dcMem.MoveTo(50,0); dcMem.LineTo(50,100);//画个蓝色的十字 dcMem.SelectObject (pOldPen); dcMem.StretchBlt(0,0,64,64,&dcMem,0,0,100, 100,SRCCOPY); //此处用StretchBlt函数来进行缩放,注意缩放后位图大小仍是100*100,但是在该位图最左上角64*64的这块空间上是原图的一个缩小图。64*64与ImageList的图片大小相匹配,也可以是32*32,16*16等。 奇怪的地方就在这里了,这时PtnBitmap应该就指向了这个位图,我把该位图保存为一个.bmp的文件也看了就是一个大十字和一个小十字,说明画图没错,PtnBitmap指向了这个位图,但是使用m_ImageListShow.Add(&PtnBitmap, RGB(192,192, 192));之后,CListCtrl上显示一片黑色。这个问题一直解决不了,我估计是因为PtnBitmap所指的位图是100*100的和CImageList的64*64的格式不一致,所以只有用个笨方法,把PtnBitmap所指的位图数据读出来放到一个数组中,然后重新建立一个新的64*64的位图来存。那我为什么一开始不建个64*64的位图呢?因为我要画的是一个大图,如果在一个64*64的图上画,坐标点不好控制,所以只有建大图,画好再后用StretchBlt函数来缩放。继续往下,首先把PtnBitmap的数据读出来: BITMAPINFO *m_pBMI; BYTE *m_pDIBData;//存放像素数据的数组 BITMAPFILEHEADER bfh;//位图文件头 BITMAPINFOHEADER bi; //位图信息头,具体位图格式可以在网上查到 BITMAP BM; CBitmap *PBitmap;//一个新的CBitmap*指针,用来再次指向所画的图 CClientDC dcClient(this); int size=sizeof(BM); PtnBitmap.GetObject(sizeof(BM),&BM); bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = 100; //宽和高要和所画图大小一样 bi.biHeight = 100; bi.biPlanes = 1; bi.biBitCount = 24; bi.biCompression = 0; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; bfh.bfType=0x4d42; bfh.bfOffBits=sizeof(bfh)+sizeof(BITMAPINFOHEADER); bfh.bfSize=bfh.bfOffBits+bi.biWidth*bi.biHeight*3; //BM.bmWidth*BM.bmHeight bfh.bfReserved1=0; bfh.bfReserved2=0; m_pBMI=(BITMAPINFO*)new char[sizeof(BITMAPINFO)]; m_pDIBData=(BYTE*)new char[bfh.bfSize-bfh.bfOffBits]; memcpy(m_pBMI,&bi,sizeof(BITMAPINFOHEADER)); GetDIBits(dcClient.GetSafeHdc(), (HBITMAP)PtnBitmap.GetSafeHandle(), 0l, (DWORD)bi.biHeight, (LPVOID)m_pDIBData,(LPBITMAPINFO)m_pBMI, (DWORD)DIB_RGB_COLORS); //数据已经在m_pDIBData数组中 BITMAPINFOHEADER *bmih=new BITMAPINFOHEADER;//开始建立一个新位图64*64的 bmih->biSize=sizeof(BITMAPINFOHEADER); bmih->biWidth=64; bmih->biHeight=64; bmih->biBitCount=24; bmih->biPlanes=1; bmih->biCompression = 0; bmih->biSizeImage = 0; bmih->biXPelsPerMeter = 0; bmih->biYPelsPerMeter = 0; bmih->biClrUsed = 0; bmih->biClrImportant = 0; unsigned char *Data=new unsigned char[64*64*3];//data用来放象素点信息 for(int height=0;height<64;height++)//Height // read bitmap pixels array to buffer { for(int width=0;width<64;width++)//Width { Data[height*64*3+width*3+0]=m_pDIBData[(bi.biHeight-1-height)*bi.biWidth*3+width*3+0];//注意位图倒着存储的 Data[height*64*3+width*3+1]=m_pDIBData[(bi.biHeight-1-height)*bi.biWidth*3+width*3+1]; Data[height*64*3+width*3+2]=m_pDIBData[(bi.biHeight-1-height)*bi.biWidth*3+width*3+2]; } } BITMAPINFO bmi; ZeroMemory(&bmi, sizeof(BITMAPINFO)); CopyMemory(&(bmi.bmiHeader), bmih, sizeof(BITMAPINFOHEADER)); HWND hWnd=this->m_hWnd; HDC hDc=::GetDC(hWnd); HBITMAP hBitmap = CreateDIBitmap(hDc, bmih, CBM_INIT, Data, &bmi, DIB_RGB_COLORS);//此时已经得到新建的64*64的位图的HBITMP只需要把它转成CBitmap*即可 PBitmap=new CBitmap; PBitmap->Attach (hBitmap); m_ImageListShow.Add(PBitmap, RGB(192,192, 192));//这时在用这句就可以显示画的图了。 PtnBitmap.DeleteObject();//释放资源不可少 dcMem.SelectObject(pbmOld); dcMem.DeleteDC(); delete []m_pBMI ; delete []m_pDIBData; delete []Data; PBitmap->DeleteObject();} 浏览文件夹的对话框如何创建? 求解 MFC 中断 莫名其妙的界面闪烁,mediaplayer控件相关 新手问题请高手指点 如何在对话框中动态创建n个编辑框? 非模式对话框问题 求字符串加密源码,100分。 连接时出现一些错误, 请高手指点, 错误如下: 如何查看*.dll文件 关于Browser/Sever架构下客户端问题 微软是怎么识别自己的程序的? 请教高手如何将普通JPG图片变成VC++对话框中能够直接Import使用的32*32的ICON图标,谢谢!
拦截CListCtrl的NM_CUSTOMDRAW消息并进行重绘即可
我的方法是让CListCtrl和一个CImageList关联,CListCtrl里面的图都从CImageList里面来取。而CImageList的图则不是从资源中Load,而是自己在MemDc里画好的。
HIMAGELIST hListShow = ImageList_Create(64,64, ILC_COLOR8 |ILC_MASK ,10, 1);//有10个图片
CImageList m_ImageListShow.Attach(hListShow); ///////////////////////////////////////////////////////////////////
//////drawPtn(); //在MemDC上画图然后add到CImageList上(重点)/////////
////////////////////////////////////////////////////////////////// m_LCShowPtn.DeleteAllItems();
m_LCShowPtn.SetImageList(&m_ImageListShow, LVSIL_NORMAL);//m_LCShowPtn是与CListCtrl关联的变量
LVITEM lvi;
CString strItem;
for(int i=0;i<100;i++)
lvi.mask = LVIF_IMAGE | LVIF_TEXT;
strItem.Format("%d",i+1);
lvi.iItem = i;
lvi.iSubItem = 0;
lvi.pszText = (LPTSTR)(LPCTSTR)(strItem);
lvi.iImage = i%10;//ImageList的图标编号从0开始有10个图就是0到9
m_LCShowPtn.InsertItem(&lvi);
///////////////////////////////////////////////////////////////////////////////////////////
现在讲下画图的方法,这个地方找不到很好的办法,很郁闷。
首先说下CImageList的Add函数(CBitmap *,COLOR);前一个参数是一个位图指针,后一个参数就是屏蔽色表示该颜色会被透明掉。
所以当你获得你画好的位图指针PBitmap后用m_ImageListShow.Add(PBitmap, RGB(192,192, 192));就可以了。
绘图过程如下,
void C****::draw()
{
CClientDC dc(this);
CBitmap PtnBitmap;
CBitmap* pbmOld = NULL;
CRect CirRect;
CDC dcMem;
dcMem.CreateCompatibleDC(&dc);
PtnBitmap.CreateCompatibleBitmap(&dc, 100, 100); //位图大小是100*100
pbmOld = dcMem.SelectObject(&PtnBitmap);
//绘制操作
CPen penB(PS_SOLID,3,RGB(0,255,255));
CPen* pOldPen=dcMem.SelectObject (&penB);
dcMem.MoveTo(0,50);
dcMem.LineTo(100,50);
dcMem.MoveTo(50,0);
dcMem.LineTo(50,100);//画个蓝色的十字
dcMem.SelectObject (pOldPen); dcMem.StretchBlt(0,0,64,64,&dcMem,0,0,100, 100,SRCCOPY); //此处用StretchBlt函数来进行缩放,注意缩放后位图大小仍是100*100,但是在该位图最左上角64*64的这块空间上是原图的一个缩小图。64*64与ImageList的图片大小相匹配,也可以是32*32,16*16等。
奇怪的地方就在这里了,这时PtnBitmap应该就指向了这个位图,我把该位图保存为一个.bmp的文件也看了就是一个大十字和一个小十字,说明画图没错,PtnBitmap指向了这个位图,但是使用m_ImageListShow.Add(&PtnBitmap, RGB(192,192, 192));之后,CListCtrl上显示一片黑色。这个问题一直解决不了,我估计是因为PtnBitmap所指的位图是100*100的和CImageList的64*64的格式不一致,所以只有用个笨方法,把PtnBitmap所指的位图数据读出来放到一个数组中,然后重新建立一个新的64*64的位图来存。那我为什么一开始不建个64*64的位图呢?因为我要画的是一个大图,如果在一个64*64的图上画,坐标点不好控制,所以只有建大图,画好再后用StretchBlt函数来缩放。继续往下,首先把PtnBitmap的数据读出来:
BITMAPINFO *m_pBMI;
BYTE *m_pDIBData;//存放像素数据的数组
BITMAPFILEHEADER bfh;//位图文件头
BITMAPINFOHEADER bi; //位图信息头,具体位图格式可以在网上查到
BITMAP BM;
CBitmap *PBitmap;//一个新的CBitmap*指针,用来再次指向所画的图
CClientDC dcClient(this); int size=sizeof(BM);
PtnBitmap.GetObject(sizeof(BM),&BM);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = 100; //宽和高要和所画图大小一样
bi.biHeight = 100;
bi.biPlanes = 1;
bi.biBitCount = 24;
bi.biCompression = 0;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bfh.bfType=0x4d42;
bfh.bfOffBits=sizeof(bfh)+sizeof(BITMAPINFOHEADER);
bfh.bfSize=bfh.bfOffBits+bi.biWidth*bi.biHeight*3; //BM.bmWidth*BM.bmHeight
bfh.bfReserved1=0;
bfh.bfReserved2=0;
m_pBMI=(BITMAPINFO*)new char[sizeof(BITMAPINFO)];
m_pDIBData=(BYTE*)new char[bfh.bfSize-bfh.bfOffBits];
memcpy(m_pBMI,&bi,sizeof(BITMAPINFOHEADER));
GetDIBits(dcClient.GetSafeHdc(), (HBITMAP)PtnBitmap.GetSafeHandle(), 0l, (DWORD)bi.biHeight,
(LPVOID)m_pDIBData,(LPBITMAPINFO)m_pBMI, (DWORD)DIB_RGB_COLORS); //数据已经在m_pDIBData数组中 BITMAPINFOHEADER *bmih=new BITMAPINFOHEADER;//开始建立一个新位图64*64的
bmih->biSize=sizeof(BITMAPINFOHEADER);
bmih->biWidth=64;
bmih->biHeight=64;
bmih->biBitCount=24;
bmih->biPlanes=1;
bmih->biCompression = 0;
bmih->biSizeImage = 0;
bmih->biXPelsPerMeter = 0;
bmih->biYPelsPerMeter = 0;
bmih->biClrUsed = 0;
bmih->biClrImportant = 0; unsigned char *Data=new unsigned char[64*64*3];//data用来放象素点信息
for(int height=0;height<64;height++)//Height // read bitmap pixels array to buffer
{
for(int width=0;width<64;width++)//Width
{
Data[height*64*3+width*3+0]=m_pDIBData[(bi.biHeight-1-height)*bi.biWidth*3+width*3+0];//注意位图倒着存储的
Data[height*64*3+width*3+1]=m_pDIBData[(bi.biHeight-1-height)*bi.biWidth*3+width*3+1];
Data[height*64*3+width*3+2]=m_pDIBData[(bi.biHeight-1-height)*bi.biWidth*3+width*3+2];
}
}
BITMAPINFO bmi;
ZeroMemory(&bmi, sizeof(BITMAPINFO));
CopyMemory(&(bmi.bmiHeader), bmih, sizeof(BITMAPINFOHEADER));
HWND hWnd=this->m_hWnd;
HDC hDc=::GetDC(hWnd);
HBITMAP hBitmap = CreateDIBitmap(hDc, bmih, CBM_INIT, Data, &bmi, DIB_RGB_COLORS);//此时已经得到新建的64*64的位图的HBITMP只需要把它转成CBitmap*即可 PBitmap=new CBitmap;
PBitmap->Attach (hBitmap);
m_ImageListShow.Add(PBitmap, RGB(192,192, 192));//这时在用这句就可以显示画的图了。 PtnBitmap.DeleteObject();//释放资源不可少
dcMem.SelectObject(pbmOld);
dcMem.DeleteDC();
delete []m_pBMI ;
delete []m_pDIBData;
delete []Data;
PBitmap->DeleteObject();
}