释放MFC中使用Image.load方法分配的内存

释放MFC中使用Image.load方法分配的内存,mfc,Mfc,在MFC中,我加载了一个.PNG图像,然后用静态控件显示它,如下所示: CImage Img; Img.Load(_T(abc.png")); CBitMap Bmp; Bmp.Attach(Img.Detach()); CStatic dispImg; dispImg.SetBitmap(Bmp); void CPNGTestDlg::ChangePic(Cstring img) { CImage Img; Img.Load(img); CBitmap Bmp; Bmp.Attach(Img

在MFC中,我加载了一个.PNG图像,然后用静态控件显示它,如下所示:

CImage Img;
Img.Load(_T(abc.png"));
CBitMap Bmp;
Bmp.Attach(Img.Detach());
CStatic dispImg;
dispImg.SetBitmap(Bmp);
void CPNGTestDlg::ChangePic(Cstring img)
{
CImage Img;
Img.Load(img);
CBitmap Bmp;
Bmp.Attach(Img.Detach());
HBITMAP hBmp=m_pic.SEtBitmap(Bmp);
if(hBmp!=NULL) DeleteObject(hBmp);
}
void CPNGTest::OnBnClickedChngPic()
{
if(SetBlueImg)
{
ChangePic(_T("Blue.png"));
SetBlueImg=false;
}
else
{
ChangePic(_T("Red.png"));
SetBlueImg=true;
}
}
通过这种方式,我有几个图像,我用静态控件重复显示 这导致我的应用程序内存严重泄漏。我通过谷歌搜索找到了一些线索,但我无法决定释放内存的最佳选择。谁能告诉我最好的方法

  • 此代码不完整。以这种方式使用CStatic永远不会起作用。它不是被创建的。 如果你真的需要帮助的话,macthes会对你的问题进行更详细的描述
  • 使用CStatic::SetBitmap时,ypu必须释放函数返回的HBITMAP句柄。读一下这本书。因此,如果在循环中使用此samne CStatic并始终为CStatic分配新位图,则可能会导致泄漏

  • 正如xMRi所建议的,我正在释放CStatic::SetBitmap返回的HBITMAP句柄。在我的测试应用程序中,有一个CStatic控件成员m_pic,一个方法ChangePic,它设置一个位图和一个按钮控件,用于根据布尔变量SetBlueImg的值更改图像。ChangePic的定义如下:

    CImage Img;
    Img.Load(_T(abc.png"));
    CBitMap Bmp;
    Bmp.Attach(Img.Detach());
    CStatic dispImg;
    dispImg.SetBitmap(Bmp);
    
    void CPNGTestDlg::ChangePic(Cstring img)
    {
    CImage Img;
    Img.Load(img);
    CBitmap Bmp;
    Bmp.Attach(Img.Detach());
    HBITMAP hBmp=m_pic.SEtBitmap(Bmp);
    if(hBmp!=NULL) DeleteObject(hBmp);
    }
    
    void CPNGTest::OnBnClickedChngPic()
    {
    if(SetBlueImg)
    {
    ChangePic(_T("Blue.png"));
    SetBlueImg=false;
    }
    else
    {
    ChangePic(_T("Red.png"));
    SetBlueImg=true;
    }
    }
    
    按钮的点击事件定义如下:

    CImage Img;
    Img.Load(_T(abc.png"));
    CBitMap Bmp;
    Bmp.Attach(Img.Detach());
    CStatic dispImg;
    dispImg.SetBitmap(Bmp);
    
    void CPNGTestDlg::ChangePic(Cstring img)
    {
    CImage Img;
    Img.Load(img);
    CBitmap Bmp;
    Bmp.Attach(Img.Detach());
    HBITMAP hBmp=m_pic.SEtBitmap(Bmp);
    if(hBmp!=NULL) DeleteObject(hBmp);
    }
    
    void CPNGTest::OnBnClickedChngPic()
    {
    if(SetBlueImg)
    {
    ChangePic(_T("Blue.png"));
    SetBlueImg=false;
    }
    else
    {
    ChangePic(_T("Red.png"));
    SetBlueImg=true;
    }
    }
    
    SetBlueImg=true的初始值,在OnInitDialog()中我调用了ChangePic(_T(“Red.png”)


    我运行应用程序并不断单击按钮以更改当前图像,但仍然可以通过windows任务管理器看到内存泄漏。点击按钮40/50次或有时不可预测后,内存会增加4KB。请指出导致泄漏的地方。

    为了在用另一个图像替换静态控件上的一个图像时消除重叠图像,我最初遵循以下步骤:

  • 显示窗口(SW_隐藏)
  • SetBitmap()
  • ShowWindow(SW_SHOW)
  • 但我不知道这是否是解决图像重叠的正确方法。我通过谷歌搜索了一下,找到了以下方法:

  • 第一次绘制静态控件之前,在静态控件后面的父窗口上复制区域
  • 每次需要重新绘制静态控件时,将图像复制回父控件

  • 对话框被破坏时,必须删除HBITMAP对象

    void CMFCAppDlg::OnDestroy()
    {
    CDialogEx::OnDestroy();
    DeleteObject(m_pic.GetBitmap());
    }
    

    我在你的代码片段中没有看到内存泄漏。请给出一个SSCCE。请考虑代码片段在一个循环内,因为我正在根据一些事件加载不同的图像。但是,只有显示图像的静态控件对象dispImg在循环外声明。实际上,我已经看到循环的每一次迭代都会增加4KB的内存消耗。如果您显示的代码与您的代码不同(例如关于对象生命周期),那么您希望我们如何提供帮助?因此,如前所述,sscce请。对不起!我不能在这里展示一切。我只是给了你一个样本,告诉你我想做什么。唯一有争议的事情是在循环之外。其他事情如我在文章中提到的。在我的项目中,我使用了一个静态控件并声明了一个成员变量dispImg,用于根据不同的事件设置不同的png图像。相同的dispImg用于在应用程序生命周期的不同时间显示不同的图像。我错说dispImg在循环中;实际上,在一个方法中,我通过CImage加载不同的图像(一次加载一个,取决于某个设备的状态),并获取CBitMap对象以使用dispImg对其进行设置。该方法在事件发生时调用。据我所知,每次释放SetBitmap返回的HBITMAP不会留下任何内存泄漏。您必须释放SetBitmap返回的位图。当你问问题时,如果你能更详细地描述问题,那将是很有帮助的。谢谢xMRI的帮助。我会应用你的建议,然后回来。按照xMRi建议的方式,我用旧的图像替换PNG图像,但图像重叠。我在背景上附加了一个PNG图像,然后在背景上显示了另一个PNG图像,现在当我试图用较小的图像替换第二个图像时,第三个图像将显示在第二个图像上。我只想在背景上显示第三个图像。有人能给我提个建议吗?