在我的程序中引用了一个别人提供的类:CxSkinButton,这个类可以根据Button的状态显示不同的位图,是非常不错的一个类。但最近发现这个类显示位图存在内存泄漏的问题,通常程序运行了几十分钟后会报错,跟进去发现就是这个类中显示位图的地方出的错。通常vc里显示位图都需要先创建一个内存设备环境CreateCompatibleDC
,发现就是这个地方失败了,就是返回值是0。这种情况只会在程序运行了较长一段时间才会出现。我觉得可能出现内存泄漏的地方有下面几个:
1、每次CreateCompatibleDC后没用DeleteDC释放,长此反复可能不行。
2、每次SelectObject后返回当前Bitmap的句柄,后来没有SelectObject回去,这里我已经做了修改,正在测试。
  不知道上面的看法对不对。另外我还有两个疑问:
1、每次CreateCompatibleDC是不是一定要用DeleteDC释放?CreateCompatibleDC能不能只做一次,不要每次显示的时候都Create一次
2、GetDC后是不是一定要用ReleaseDC释放?
  请各位说说自己的看法,一并感谢!

解决方案 »

  1.   

    GDI现存泄漏,楼主的做法可行。
      

  2.   

    GDI的内存泄漏可以用什么工具看出来吗?用任务管理器好像不行
      

  3.   

    另外就是每次显示完位图以后一定要DeleteObject吗
      

  4.   

    显存!!!当年我是用ctrl+alt+del看的,很把。
      

  5.   

    你说的都正确,显示完位图就算是不DeleteObject的话,下次使用时也不一定还是这个位图。
      

  6.   

    我用的BoundsChecker来查内存泄露的,可为什么没有ReleaseDC也不会内存泄露的呢?
    奇怪的是:
    HINSTANCE hSkinDll = LoadLibrary(".\\SkinImg.Dll");
    FreeLibrary(hSkinDll);
    这样两句倒会有泄露:
    Resource leak: allocated by LoadLibraryA in dllinit.cpp (505), HANDLE: 0x62170000
    Location of Error
    DllMain dllinit.cpp 505
      

  7.   

    这个类主要是为按钮在平常、按下、鼠标滑过、获得焦点等情况下显示不同的位图,显示的大小就是位图的大小。通常还需要为按钮设一个mask位图,这样就显示的位图就不需要全部都是标准的方块Button的形状了。我想问问你用BoundChecker怎么检测内存泄漏?我以前没用过
      

  8.   

    CxSkinButton 这个类我也使用了,我也发现了这个问题,我已经修正了。
    共享一下。
    这是.h文件
    #if !defined(AFX_MYB_H__3832DDEF_0C12_11D5_B6BE_00E07D8144D0__INCLUDED_)
    #define AFX_MYB_H__3832DDEF_0C12_11D5_B6BE_00E07D8144D0__INCLUDED_#if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // CxSkinButton.h : header file
    /** 15/03/2001 v1.00
     * [email protected]
     ** 29/03/2001 v1.10
     * [email protected]
     * - mouse tracking
     ** 02/04/2001 v1.20
     * [email protected]
     * - new CreateRgnFromBitmap
     ** 14/04/2001 v1.21
     * - OnMouseLeave cast fixed
     * - Over bitmap consistency check
     ** 25/04/2001 v1.30
     * [email protected]
     * - ExtCreateRegion replacement
     *//////////////////////////////////////////////////////////////////////////////
    // CxSkinButton window
    //默认为普通按钮,否则是两种状态的按钮
    enum BUTTONTYPE {NORMAL_BUTTON,SUPER_BUTTON};
    //状态。在SUPER_BUTTON按钮的时候使用
    enum BUTTONSTATE{NORMAL_STATE,PUSHED_STATE};
    class CxSkinButton : public CButton
    {
    // Construction
    public:
    CxSkinButton();// Attributes
    private:// Operations
    public:
    // Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CxSkinButton)
    public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    protected:
    //}}AFX_VIRTUAL
    // Implementation
    public:
    HBITMAP LoadImage(LPCSTR lpStrName);//load file from a file.
    void DeleteObject(HBITMAP hBitmap);//
    void SetToolTipText(CString s);
    COLORREF SetTextColor(COLORREF new_color);
    // void SetSkin(UINT normal,UINT down, UINT over=NULL, UINT disabled=NULL,UINT mask=NULL,
    // short drawmode=1,short border=1,short margin=4);
    void SetSkin(char *NormalName,char *DownName,char *OverName=NULL,char *DisabledName=NULL,char *MaskName=NULL,
    short drawmode=1,short border=1,short margin=4);
    void SetSkin(UINT normal,UINT down,UINT over=NULL,UINT disabled=NULL,UINT mask=NULL,
      short drawmode=1, short border=1, short margin=4);
    //两个状态的按钮 按一下凹下,再按一下弹起   
    BUTTONSTATE m_uState;//0---Normal 1---Down
    void SetSuperButtonState(BUTTONSTATE state);
    BUTTONSTATE GetSuperButtonState();
    BUTTONTYPE m_btType;
    //设置按钮的类型
    void SetType(BUTTONTYPE type);
    BUTTONTYPE GetType();
    virtual ~CxSkinButton();
    // Generated message map functions
    protected:
        bool m_tracking;
        bool m_button_down;
    void RelayEvent(UINT message, WPARAM wParam, LPARAM lParam);
    CToolTipCtrl m_tooltip;
    // CBitmap m_bNormal,m_bDown,m_bDisabled,m_bMask,m_bOver; //skin bitmaps
    HBITMAP m_hNormal,m_hDown,m_hDisabled,m_hMask,m_hOver; //skin bitmaps
    short m_FocusRectMargin; //dotted margin offset
    COLORREF m_TextColor; //button text color
    HRGN hClipRgn; //clipping region
    BOOL m_Border; //0=flat; 1=3D;
    short m_DrawMode; //0=normal; 1=stretch; 2=tiled;
    HRGN CreateRgnFromBitmap(HBITMAP hBmp, COLORREF color);
    void FillWithBitmap(CDC* dc, HBITMAP hbmp, RECT r);
    void DrawBitmap(CDC* dc, HBITMAP hbmp, RECT r, int DrawMode);
    int GetBitmapWidth (HBITMAP hBitmap);
    int GetBitmapHeight (HBITMAP hBitmap); //{{AFX_MSG(CxSkinButton)
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
    afx_msg void OnKillFocus(CWnd* pNewWnd);
    afx_msg BOOL OnClicked();
    afx_msg LRESULT OnMouseLeave(WPARAM, LPARAM);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
    };
    /////////////////////////////////////////////////////////////////////////////
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
    #endif // !defined(AFX_MYB_H__3832DDEF_0C12_11D5_B6BE_00E07D8144D0__INCLUDED_)
      

  9.   

    .cpp 文件太大,告诉我你的mail,发给你。