png按钮的资源释放问题

yjguanjian   2008-11-13 20:50 楼主
开发环境:vc2005  arm   wince5.0
我用网上下的CCePngButtonST类做png按钮,想要实现同一个按钮上的png图片根据不同情况显示不同内容,比如播放器打开时显示一张图片,播放器关闭时显示另一张图片,结果点了n次后把内存都占光了,显然是加载另一张时前一张的内存没有释放完,请问
如何释放?

代码如下:
1:
   CCePngButtonST m_cbtntest;

   
    BOOL CAlphaBlendDlg::OnInitDialog()
{
        CDialog::OnInitDialog();

        // Set the icon for this dialog.  The framework does this automatically
        //  when the application's main window is not a dialog
        SetIcon(m_hIcon, TRUE);                        // Set big icon
        SetIcon(m_hIcon, FALSE);                // Set small icon

        // TODO: Add extra initialization here
        this->ShowWindow(SW_SHOWMAXIMIZED);  //SW_MAXIMIZE是显示窗口为最大化
        m_cbtntest.SetWindowPos(&wndTop,0,190,80,80,SWP_NOZORDER|SWP_SHOWWINDOW);
        m_cbtntest.SetImage(IDB_MAINBKGND,IDB_04,CSize(70,70),IDR_MUSIC,CSize(80,80));

       }


2.    事件判断

         if(i==0){
         m_cbtntest.SetImage(IDB_MAINBKGND,IDB_04,CSize(70,70),IDR_MUSIC,CSize(80,80));
          }
         
        else{
    m_cbtntest.SetImage(IDB_MAINBKGND,IDB_GAME1,CSize(70,70),IDR_GAME,CSize(80,80));
       }
3。    CCePngButtonST类中的函数

        DWORD CCePngButtonST::SetImage(int nBkgndID, int nImageIn, CSize sizeIn, int nImageOut, CSize sizeOut, int nImageDis, CSize sizeDis)
{
        IImage*        pImageIn        = NULL;
        IImage*        pImageOut        = NULL;
        IImage*        pImageDis        = NULL;


        nBkgndImageID = nBkgndID;
        CoInitializeEx(NULL,COINIT_MULTITHREADED);
        //initialize com
        if(!SUCCEEDED(CoCreateInstance(CLSID_ImagingFactory,NULL,CLSCTX_INPROC_SERVER,IID_IImagingFactory,(void **)&pIImgFactory)))
        {
                return BTNST_FAILEDMASK;
        }
        // Set image when the mouse is IN the button
        ImageFromIDResource(nImageIn, L"PNG", &pImageIn);
          // Set image when the mouse is OUT the button
        if (nImageOut)
                ImageFromIDResource(nImageOut, L"PNG", &pImageOut);
          // Set image when the mouse is DISABLED
        if (nImageDis)
                ImageFromIDResource(nImageDis, L"PNG", &pImageDis);
        return SetImage(pImageIn, sizeIn, pImageOut, sizeOut, pImageDis, sizeDis);
} // End of SetImage

DWORD CCePngButtonST::SetImage(IImage* pIImageIn, CSize sizeIn, IImage* pIImageOut, CSize sizeOut, IImage* pIImageDis, CSize sizeDis)
{
        // Free any loaded resource
        FreeResources();

        if (pIImageIn)
        {
                // Image when mouse over button?
                m_csImages[0].pIImage = pIImageIn;
                // Get image dimension
                m_csImages[0].dwWidth        = (DWORD)sizeIn.cx;
                m_csImages[0].dwHeight        = (DWORD)sizeIn.cy;
               
                // Image when mouse outside button?
                if (pIImageOut)
                {
                        m_csImages[1].pIImage = pIImageOut;
                        // Get image dimension
                        m_csImages[1].dwWidth        = (DWORD)sizeOut.cx;
                        m_csImages[1].dwHeight        = (DWORD)sizeOut.cy;
                } // if

                // Image when button disabled?
                if (pIImageDis)
                {
                        m_csImages[2].pIImage = pIImageDis;
                        // Get icon dimension
                        m_csImages[2].dwWidth        = (DWORD)sizeDis.cx;
                        m_csImages[2].dwHeight        = (DWORD)sizeDis.cy;
                } // if
        } // if

        Invalidate();

        return BTNST_OK;
} // End of SetImage



void CCePngButtonST::FreeResources(BOOL bCheckForNULL)
{
        if (bCheckForNULL)
        {
                // Destroy icons
                // Note: the following lines MUST be here! even if
                // BoundChecker says they are unnecessary!
                if (m_csIcons[0].hIcon)        ::DestroyIcon(m_csIcons[0].hIcon);
                if (m_csIcons[1].hIcon)        ::DestroyIcon(m_csIcons[1].hIcon);
                if (m_csIcons[2].hIcon)        ::DestroyIcon(m_csIcons[2].hIcon);
        } // if

        memset(&m_csIcons, 0, sizeof(m_csIcons));
        memset(&m_csBitmaps, 0, sizeof(m_csBitmaps));
        memset(&m_csImages, 0, sizeof(m_csImages));
} // End of FreeResources


     

回复评论 (11)

怎么没有看到CoUninitialize()的调用啊

其它申请的资源,也没有释放吧---没有仔细看,LZ应该清楚吧
点赞  2008-11-13 22:42
IImage* IImageFactory*这些都要Release,还要调CoUninitialize
点赞  2008-11-14 08:33
不知道是这个类写的有问题,还是楼主只是贴了一部分

CoInitializeEx
CoCreateInstance

这些函数都有对应的资源释放问题,并不是调完了就行,需要配对使用,即有Initialize,就应该有Uninitialize

Create和Release对应,

我估计CCePngButtonST这个类应该有响应的接口函数完成释放工作,你好好看看吧
点赞  2008-11-14 10:09
Image*        pImageIn 等只是几个局部的东东,显然用完手没有Release()
点赞  2008-11-14 10:22


顶!

我也顺便打个广告,本人也有支持ESRI ARCGIS的.shp文件的地图的Windows mobile 5.0/6.0手机GIS地图软件----GPS移动GIS(GPSMobileGIS),PC端的服务软件----移动GIS服务平台(GPSMobileGISServer),可成套出售,可以完成以下功能:
1,通过GPRS上网连接后台服务端程序来实时传输在户外工作采集的数据到后台数据库!

2,可以实时发回PDA的GPS信息,在后台地图上直接定位PDA用户的位置,也可以下发PDA的经纬度信息让PDA用户定位和跟踪其它PDA用户,了解自己与其它PDA的位置关系,起到定位和跟踪的作用!

3,可以发回PDA当前所在地名如在天河城附近等,实现在外面工作就知道在何时何地上班打卡的效果,同时可以在后台为相应的PDA用户设置固定时长返回一次当前位置的GPS信息确保对相应PDA用户的定位,跟踪与监控!

4,移动GIS服务平台可以对PDA用户进行登记,注销等管理,在移动GIS服务平台登记的PDA用户才可登陆此服务器,依据IMSI和IMEI号来进行登陆验证,安全可靠,

5,可以对在外面工作的PDA用户进行任务指派和任务管理如
   PDA号码:13800138000
   任务名称:测试线路
   任务说明:主要是在天河北路一带的电力设施进行检测!

6,(此功能为信息采集的核心功能)用户可自行设置需要采集信息的对象及其属性,指派给指定的PDA用户,如测试电路的属性模板:
    //0-编辑属性(可多个) ; 1-下拉属性(可多个) ; 2-选择属性(可多个) ; 3-大文本编辑框(可以没有此属性,但有此属性时只能有一个) ; 4-列表属性(可以没有此属性,但有此属性时只能有一个)(属性0+属性1+属性2/2+属性2%2)<=28
    name,名称,0,;beproject,所属项目,0,;type,类型,1,0:小-1:中-2:大;complete,完成,2,;remark,备注,3,;listbox,设备表,4,

7,可以实时上传文件到后台服务器,实时下载后台服务器的文件和实时更新PDA上客户端的系统!

8,可以实时采集和传输图像信息!

跟据您的需要,还可以增加其它功能!

可以应用在以下系统:
     1、PDA移动办公如户外,异地打卡,上班;
     2、GIS林业资源监控系统;
     3、GIS电力巡检系统等;
     4、GIS通信资源如移动,联通,电信的管线资源巡检系统等!

QQ:546046182
EMail:wang921018@tom.com

点赞  2008-11-14 10:24


顶!

我也顺便打个广告,本人也有支持ESRI ARCGIS的.shp文件的地图的Windows mobile 5.0/6.0手机GIS地图软件----GPS移动GIS(GPSMobileGIS),PC端的服务软件----移动GIS服务平台(GPSMobileGISServer),可成套出售,可以完成以下功能:
1,通过GPRS上网连接后台服务端程序来实时传输在户外工作采集的数据到后台数据库!

2,可以实时发回PDA的GPS信息,在后台地图上直接定位PDA用户的位置,也可以下发PDA的经纬度信息让PDA用户定位和跟踪其它PDA用户,了解自己与其它PDA的位置关系,起到定位和跟踪的作用!

3,可以发回PDA当前所在地名如在天河城附近等,实现在外面工作就知道在何时何地上班打卡的效果,同时可以在后台为相应的PDA用户设置固定时长返回一次当前位置的GPS信息确保对相应PDA用户的定位,跟踪与监控!

4,移动GIS服务平台可以对PDA用户进行登记,注销等管理,在移动GIS服务平台登记的PDA用户才可登陆此服务器,依据IMSI和IMEI号来进行登陆验证,安全可靠,

5,可以对在外面工作的PDA用户进行任务指派和任务管理如
   PDA号码:13800138000
   任务名称:测试线路
   任务说明:主要是在天河北路一带的电力设施进行检测!

6,(此功能为信息采集的核心功能)用户可自行设置需要采集信息的对象及其属性,指派给指定的PDA用户,如测试电路的属性模板:
    //0-编辑属性(可多个) ; 1-下拉属性(可多个) ; 2-选择属性(可多个) ; 3-大文本编辑框(可以没有此属性,但有此属性时只能有一个) ; 4-列表属性(可以没有此属性,但有此属性时只能有一个)(属性0+属性1+属性2/2+属性2%2)<=28
    name,名称,0,;beproject,所属项目,0,;type,类型,1,0:小-1:中-2:大;complete,完成,2,;remark,备注,3,;listbox,设备表,4,

7,可以实时上传文件到后台服务器,实时下载后台服务器的文件和实时更新PDA上客户端的系统!

8,可以实时采集和传输图像信息!

跟据您的需要,还可以增加其它功能!

可以应用在以下系统:
     1、PDA移动办公如户外,异地打卡,上班;
     2、GIS林业资源监控系统;
     3、GIS电力巡检系统等;
     4、GIS通信资源如移动,联通,电信的管线资源巡检系统等!

QQ:546046182
EMail:wang921718@tom.com

点赞  2008-11-14 10:59
我按楼上所说看了一下,ImageFromIDResource()函数应该有释放资源,
现在我就不明白除了CoUninitialize没调用,还有哪些地方没有Release??恳请赐教!

BOOL CCePngButtonST::ImageFromIDResource(UINT nID, LPCTSTR sTR, IImage** pIImage)
{
        HINSTANCE hInst = AfxGetResourceHandle();
        HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),sTR); // type
        if (!hRsrc)
                return FALSE;

        // load resource into memory
        DWORD len = SizeofResource(hInst, hRsrc);
        BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
        if (!lpRsrc)
                return FALSE;

        // Allocate global memory on which to create stream
        HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
        BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
        memcpy(pmem,lpRsrc,len);
        IStream* pStream;
        CreateStreamOnHGlobal(m_hMem,FALSE,&pStream);
        // load from stream
        pIImgFactory->CreateImageFromStream(pStream, pIImage);

        // free/release stuff
        GlobalUnlock(m_hMem);
        pStream->Release();
        FreeResource(lpRsrc);
        if(!pIImage)
                return FALSE;

        return TRUE;
}
点赞  2008-11-14 14:39
最好去查帮忙,每个函数的查一遍,需要释放资源的,帮忙中都会说明的。
这个办法虽然慢一些,但是有一定的积累后,才能进步。
点赞  2008-11-14 14:53
还是没搞定。
这是CCePngButtonST类的源代码下载地址,里面有一个测试代码,我的程序就是从测试代码改过来的
http://download.eeworld.net/source/555815
大家帮我看看吧,不是小弟我不下苦功,搞硬件和c出身的人努力学vc,希望大家多多点拨
点赞  2008-11-14 15:52
资源分:10分......
点赞  2008-11-14 17:48
在此函数:

DWORD CCePngButtonST::SetImage(int nBkgndID, int nImageIn, CSize sizeIn, int nImageOut, CSize sizeOut, int nImageDis, CSize sizeDis)

后加入 pImageIn->Release(); pImageOut->Release(); pImageDis->Release(); 试试.
点赞  2008-11-14 18:15
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复