随笔 - 41  文章 - 2 评论 - 0 阅读 - 52537
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

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

posted on   lazybee  阅读(429)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示