Нужно ли повторно выбирать предыдущее перо в DC, перед тем как его отпустить?

У меня есть следующий класс диалогового окна:

class CInputDlg : public CDialog
{
public:
    CInputDlg(CWnd* pParent = NULL);
    virtual ~CInputDlg();

DECLARE_MESSAGE_MAP();

protected:
    afx_msg BOOL OnInitDialog();
    afx_msg void OnCancel();
    afx_msg void OnPaint();

private:
    CPen m_Pen;
};

Вот реализация подпрограмм обратного вызова:

BOOL CInputDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    m_Pen.CreatePen(...);
    return TRUE;
}

void CInputDlg::OnCancel()
{
    m_Pen.DeleteObject();
    CDialog::OnCancel();
}

void CInputDlg::OnPaint()
{
    CPaintDC dc(this);
    CDC* pDC = GetDC();
    pDC->SelectObject(m_Pen);
    ...
    ReleaseDC(pDC);
}

Как вы можете видеть, в OnPaint Как правило, я не выбираю предыдущую ручку в DC.

Я делаю это в предположении, что в этом нет необходимости, так как я все равно освобождаю DC.

Наконец, в OnCancel Как правило, я удаляю ручку (которая, возможно, выбрана в каком-то DC).

Я ошибаюсь, или мое предположение выше верно?

MSDN не очень ясно, когда я могу или должен удалить объекты.

Я думаю, что этот вопрос связан с моим плохим пониманием ДК.

Спасибо.

1 ответ

Решение

Ошибка освобождения контекста устройства без восстановления его исходного состояния. В любой момент времени контекст устройства хранит ссылку на объект 7 типов графических объектов. Эти объекты принадлежат контексту устройства и должны быть очищены, когда контекст устройства уничтожен.

SelectObject

выбирает объект в указанный контекст устройства (DC). Новый объект заменяет предыдущий объект того же типа.

Поэтому, не восстанавливая контекст устройства, он оставляет ссылку на объект, который ему не принадлежит. Когда приходит время его разрушать, случаются плохие вещи 1.

Правила просты: всегда восстанавливайте контроллер домена, прежде чем возвращать его владельцу (вызывающему или системному). Если отслеживание каждого графического объекта слишком утомительно или практически невозможно, вы можете использовать SaveDC при входе и RestoreDC при выходе.

Бонусное чтение:


+1 В любом случае в теории. Поскольку существует так много плохого кода, система реализовала достаточную устойчивость к ошибочному управлению ресурсами GDI.

Другие вопросы по тегам