CImageList* 转 LPDISPATCH 在控件中显示图片

         公司将GridCtrl 源码封装成了一个控件,但在往这个控件显示图片的时候可把我给难住了,正常来讲会创建一个CImageList 类型的变量 (比如m_ImageList),然后将很多图片加入到这个变量当中,然后调用SetImageList(CImageList *)就可以了,但是封装完了以后,这个函数就变成了这样的:void SetImageList(LPDISPATCH propVal) 。参数居然是LPDISPATCH 类型,隐隐约约感觉这玩意又跟COM 有点啥关系,COM可是我的盲区啊。硬着头皮各种搜怎么把CImageList 变成 IDISPATCH 。不过并没啥结果。无奈求助了同事,给出了个例子,如下:

LONG nSize=16, nElem=5;
UINT nFlags = ILC_MASK | ILC_COLOR32;
CPictureHolder      m_gridX_PictureHolder;
m_gridX_PictureHolder.CreateFromBitmap(IDB_FMC_GRIDROWS);
m_gridX.PutItemImageListCustom(m_gridX_PictureHolder.GetPictureDispatch(), nSize, nFlags, nElem, RGB_TRANSPARENCY);
m_gridX.ItemImage (0, 0, 3);

由以上的小例子可以看出,借助于CPictureHolder  可以将图片类型转换为LPDISPATCH。顺便也发现我太纠结于SetImageList 了,其实控件还提供了个

PutItemImageListCustom 函数,想想也可以理解,图片转换过去总得告诉他图片尺寸等信息才能显示啊。

        因为我要动态的显示图片,比如删除表格中一行,或者添加一行,所以从文件读取图片的方式更适合我。又是动态添加图片所以又想借助于CImagList 了:

    CBitmap* pBitMap;
    HBITMAP hBitmap;
    pBitMap = new CBitmap;


    //从文件导入位图
    hBitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(),L"res\green2.bmp",
        IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

    pBitMap->Attach(hBitmap);
    m_ImageList.Add(pBitMap,RGB(0,0,0));

    pBitMap->DeleteObject();
    pBitMap->Detach();

    hBitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(),L"res\green.bmp",
        IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
    pBitMap->Attach(hBitmap);
    m_ImageList.Add(pBitMap,RGB(0,0,0));

    pBitMap->DeleteObject();
    pBitMap->Detach();


    IMAGEINFO imgInfo;
    m_ImageList.GetImageInfo(0,&imgInfo); 
    HBITMAP hbm =  (HBITMAP)CopyImage( imgInfo.hbmImage, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG );
UINT nFlags
= ILC_MASK | ILC_COLOR32; CPictureHolder m_gridX_PictureHolder; m_gridX_PictureHolder.CreateFromBitmap(hbm);//IDB_BITMAP2 LONG nElem = m_ImageList.GetImageCount(); LONG nSize = 40; m_Gridx.PutItemImageListCustom(m_gridX_PictureHolder.GetPictureDispatch(),nSize,nFlags,nElem,RGB(0,0,0));

上面标红的代码,其实得到的是添加进去的所有图片拼成的一整张图。于是想当然的整个图片传进去了,结果各种测试发现只能显示第一张图片。于是将从CImageList 中得到的图片转换成BITMAP 类型,查看了下图片的长宽,发现图像不是如我想的那种是横线一个挨着一个排列的。这也就是为什么不能显示所有图片了。

       于是问题又转换成了如何将所有的图片横向拼接成一张图片。拼接图片这种问题要是放到以前分分钟的事情,但是现在已经不搞图像处理了,没有了opencv 加持感觉也没那么顺手了。好在发现VC++ 中有个与Mat 有那么点类似的类就是CImage。下面是图像横线拼接的代码:

    
     CImage  m_GridImage;
    int nImageCount=10;
    
    CImage srcImage;
    srcImage.Load(bmpPath);
    BYTE* srcPtr = (BYTE*)srcImage.GetBits();//指向内存地址的指针
    int srcBitsCount = srcImage.GetBPP();// 每一个像素所占的地址空间大小,单位为bits
    int srcWidth = srcImage.GetWidth();
    int srcHeight = srcImage.GetHeight();
    int srcPitch = srcImage.GetPitch();//获取一张位图一行的间距,单位是字节


    //destroy image
    if (!m_GridImage.IsNull())
    {
        m_GridImage.Destroy();
    }
    m_GridImage.Create(srcWidth*nImageCount,srcHeight,srcBitsCount,0);
     BYTE *destPtr = (BYTE*)m_GridImage.GetBits();
     int destPitch = m_GridImage.GetPitch();//一行的距离

    //merge all the image into m_GridImage
    for (int i=0;i<nImageCount;i++)
    {if (!srcImage.IsNull())
        {
            srcImage.Destroy();
        }
         HRESULT hresult=srcImage.Load(bmpPath);
         if (hresult==E_FAIL)
             continue;

        BYTE* srcPtr = (BYTE*)srcImage.GetBits();//指针

        for (int j=0;j<srcHeight;j++)
        {
             memcpy(destPtr + j*destPitch+ i*abs(srcPitch), srcPtr + j*srcPitch, abs(srcPitch));

        }
    }

        额。。。。,最后也没用用上CImageList,但是我的困惑是从这个问题开始的,标题先这样写吧。

参考: https://www.cnblogs.com/DOMLX/p/9598974.html

        https://www.bbsmax.com/A/gAJGE9K8dZ/

原文地址:https://www.cnblogs.com/small-lazybee/p/12574781.html