公司将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/