2014-01-21 85 views
0

我在我们庞大的应用软件中发现了GDI泄漏。GDI资源泄漏

下面是一个简单的程序来测试这个问题。 想法是主对话框打开另一个对话框(对话框A)。 如果对话框A包含CStatic控件的位图函数,则它将创建GDI泄漏。

即使当我使用“DeleteObject(位图)”。

我做错了什么? 你有什么想法吗?

谢谢。

// Resource File 
... 

DIALOG_BOXA DIALOGEX 0, 0, 219, 142 
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_BORDER 
EXSTYLE WS_EX_STATICEDGE 
FONT 8, "MS Shell Dlg", 400, 0, 0x1 
BEGIN 
    DEFPUSHBUTTON "OK",IDOK,46,121,50,14 
    PUSHBUTTON  "Cancel",IDCANCEL,119,121,50,14 
    CONTROL   131,RED_LIGHT0,"Static",SS_BITMAP,7,17,80,37 
    PUSHBUTTON  "",RED_LIGHT1,7,60,80,37,BS_BITMAP | NOT WS_TABSTOP 
END 

// head file 
DialogBoxA: public CDialog 
{ 
    ... 

    CStatic m_static; 
    CButton m_button ; 

    ... 
} 


///////////////////////////////////////////////////////// 

void DialogBoxA::DoDataExchange(CDataExchange* pDX) 
{ 
    CDialog::DoDataExchange(pDX); 
    DDX_Control(pDX, RED_LIGHT0, m_static); 
    DDX_Control(pDX, RED_LIGHT1, m_button); 
} 

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

    HBITMAP bitmap ; 

    // This will create GDI leak !!! 
    bitmap = LoadBitmap (AfxGetApp()->m_hInstance,BEACON_BIG_RED_ON) ; 
    m_static.SetBitmap (bitmap); 
    DeleteObject(bitmap); 


    // This is OK !!! 
    bitmap = LoadBitmap (AfxGetApp()->m_hInstance,BEACON_BIG_RED_ON) ; 
    m_button.SetBitmap (bitmap); 
    DeleteObject(bitmap); 

    return TRUE; // return TRUE unless you set the focus to a control 
       // EXCEPTION: OCX Property Pages should return FALSE 
} 
+0

您是如何建立泄漏的? – noelicus

+0

此外,MSDN指出你应该使用LoadImage而不是LoadBitmap ......你有没有试过改变它? – noelicus

+0

谢谢你的回复。是的,我使用“GDIView”和“Windows任务管理器”来监视这个,我发现打开“DialogBoxA”后增加了“GDI对象”。 – ybc45

回答

0

很复杂。首先,让我们看看你的代码

bitmap = LoadBitmap (AfxGetApp()->m_hInstance,BEACON_BIG_RED_ON) ; 
m_static.SetBitmap (bitmap); 
DeleteObject(bitmap); 

你应该删除您刚才告诉静态控件使用位图仔细看看。它仍在使用它!它将继续使用它,直到您将位图设置为其他内容。

因此,不要试图在对话框初始化期间删除位图,而应该等到对话框被销毁。此时,您必须告诉静态控件停止使用位图,只有这样您才能删除位图对象。

二,静态控制有时复制你的位图。它是否进行复制取决于一系列事情,包括位图是否具有非零的Alpha通道。它也成为你的问题销毁这个副本。 (这可能是为什么你的一个你的案例工作,而另一个没有。)

你基本上必须跟踪你认为你设置的位图,直到清理时间。然后你必须将静态控制中的实际内容与你认为你给的内容进行比较。如果它们不同,那么你就会销毁它们(你的位图和静态控件副本)。如果它们是相同的,那么静态控制就不会复制,而且你必须摧毁你制造的一个(一次!)。