用CListCtrl 我能在某行某列的item上画图吗 能的话怎么实现???谢谢

解决方案 »

  1.   

    设置 OwnerDraw 属性,然后 OnDrawItem,可以获取 Item 的 Rect 画图。
      

  2.   

    可以的,你需要进行手工重绘
    拦截CListCtrl的NM_CUSTOMDRAW消息并进行重绘即可
      

  3.   

       是不是要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();
    }