定位MFC程序GDI对象泄漏过程中的一些经验

定位MFC程序GDI对象泄漏过程中的一些经验

之前接触MFC比较少,最近一个程序需要使用MFC写界面。写完之后发现程序运行一段时间后异常卡顿,并且WIN7系统任务栏图标出现一些毛边等异常情况。重新运行程序,打开任务管理器发现GDI对象不断增加,且数量到达9999后程序开始异常。因此判断程序可能存在GDI对象泄漏,即创建的GDI对象没有及时释放。 
鉴于GDI对象不断自动增加,判断GDI泄漏可能位于定时器触发的OnTimer函数中。OnTimer函数调用方法如下:

 LRESULT CVServerView::OnChangeTime(WPARAM wParam, LPARAM lParam)
 {
     CString strText;
     FormatTime((INT)wParam, 30, strText);
     m_editPush.SetWindowText(strText);
     return 0;
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

可以看出函数仅仅是调用了API函数SetWindowText,理论上不应该导致GDI泄漏。但奇怪的是注释掉SetWindowText后程序就正常了。后来发现原因在于程序重写了OnCtlColor函数。

HBRUSH CVServerView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor);

    // TODO:  在此更改 DC 的任何特性
    if (pWnd->GetDlgCtrlID() == IDC_EDIT_PUSH) {
        pDC->SetBkMode(TRANSPARENT);
        pDC->SetTextColor(RGB(255, 255, 255));
        return HBRUSH(CreateSolidBrush(RGB(56, 56, 56)));
    }

    // TODO:  如果默认的不是所需画笔,则返回另一个画笔
    return hbr;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

SetWindowText函数会调用以上OnCtlColor函数。OnCtlColor中CreateSolidBrush创建了GDI对象没有释放导致GDI对象不断增加,这就是问题所在。因此将程序修改为创建一个全局画笔m_brushBack=CreateSolidBrush(RGB(56, 56, 56)),OnDestroy时释放掉。修改代码如下:

HBRUSH CVServerView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor);

    // TODO:  在此更改 DC 的任何特性
    if (pWnd->GetDlgCtrlID() == IDC_EDIT_PUSH) {
        pDC->SetBkMode(TRANSPARENT);
        pDC->SetTextColor(RGB(255, 255, 255));
        return HBRUSH(m_brushBack);
    }

    // TODO:  如果默认的不是所需画笔,则返回另一个画笔
    return hbr;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

回头再看,问题很简单并且出现在细节地方,主要原因在于自己对GDI对象管理了解太少,随意创建GDI对象不及时释放。以此提醒自己需要牢记GDI对象创建及释放问题。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值