MFC, рисование в CStatic через CDC
Создал диалоговое окно. В него добавил элемент управления типа Bitmap, унаследовал его от класса CStatic, переопределил функцию OnPaint. Рядом с Bitmap разместил кнопку.
Теперь хочу по нажатии этой кнопки рисовать что-нибудь в этом Bitmap. Для этого создал функцию, которая рисует, вызываю её в OnPaint и OnButton1. Сделал, вроде рисует. НО. В debug версии постоянно выскакивают ASSERT после рисования. А в Release версии при завершении работы диалога - General Error.
Я делаю так (стилизовано).
void RePaint()
{
CDC *dc=GetDC();
dc->Rectangle(0,0,10,10);
}
void OnPaint()
{
RePaint();
}
void OnButton1()
{
RePaint();
}
Объясните, что за глюки? Чё я не так делаю?
Я добавил ReleaseDC:
void RePaint()
{
CDC *dc=GetDC();
dc->Rectangle(0,0,10,10);
ReleaseDC(dc); // вот здесь изменение
}
Жду мнений
Немножко подправил - Assert стал некритичным, то есть его можно пропустить, всё прорисовывается и продолжает работу. Но по окончании - всё равно General Error.
Я добавил ReleaseDC:
void RePaint()
{
CDC *dc=GetDC();
dc->Rectangle(0,0,10,10);
ReleaseDC(dc); // вот здесь изменение
}
Жду мнений
Не знаю поможет ли, но поправить стоит:
void Repaint(CDC *pdc)
{
dc->Rectangle(...);
}
void OnPaint()
{
CPaintDC dc(this);
Repaint(&dc);
}
void OnButton()
{
CDC *pdc = GetDC();
Repaint(pdc);
ReleaseDC(pdc);
}
Не знаю поможет ли, но поправить стоит:
void Repaint(CDC *pdc)
{
dc->Rectangle(...);
}
void OnPaint()
{
CPaintDC dc(this);
Repaint(&dc);
}
void OnButton()
{
CDC *pdc = GetDC();
Repaint(pdc);
ReleaseDC(pdc);
}
Я бы всё-таки создание контекста устройства и его удаление. Доверил бы конструктору и деструктору, соответственно. Во первых можно создать единожды, а во вторых не беспокоится о коректном удалении (Его уничтожит деструктор при выходе за пределы видимости).
Что то типа...
конструктор(...)
{
/*CDC*/ *m_dc=NULL
}
`деструктор
{
if(m_dc!=NULL)dc.Release();
}
Инициализация класса
{
dc = GetDC();
}
2 pavor
Переделал по твоему совету. Согласен, выглядит более корректно, но работает абсолютно так же. То есть, assert по-прежнему появляется, но не является критичным. Продолжаю поиски решения проблемы. Но чисто из интереса, потому что в сборке Release никаких Assert нет :) Всё работает отлично.
2 alibabaich
Дело в том, что я получаю контекст как раз между конструктором и деструктором. И не один раз. То, что ты описал, происходит и так на автомате. Проблема возникает в том случае, если я получаю из объекта его CDC *GetDC() и пытаюсь в нём рисовать. Сборка Debug тут же реагирует на такую попытку Assert'ом, но всё равно рисует. Мне не понятно такое поведение.
2 Toyo
Мой мэйл [email]tos@sinn.ru[/email], высылай.
void CPPGraphics::OnPaint()
{
CPaintDC dc( this );
CPaintDC DC( GetDlgItem( IDC_ST_SAMPLE ) );
DC.FillSolidRect( &m_rcClt, crBackGround );
int X0 = m_rcClt.left + 4,
X1 = m_rcClt.right - 4, Y;
for ( int i = 0; i < 8; i++ )
{
LOGBRUSH lbBrh = { BS_SOLID, m_dwLevCol, 0 };
CPen Pen( PS_GEOMETRIC | PS_ENDCAP_FLAT, m_dwWidC, &lbBrh, 0, NULL ),
*pPenOld = DC.SelectObject( &Pen );
Y = (i+1) * m_rcClt.Height() / 9;
DC.MoveTo( X0, Y ); DC.LineTo( X1, Y );
DC.SelectObject( pPenOld );
}
}
только я работаю напрямую со статиком (IDC_ST_SAMPLE) -- не делаю нового класса. посмотри может что подскажет.
Дело в том, что я получаю контекст как раз между конструктором и деструктором. И не один раз. То, что ты описал, происходит и так на автомате. Проблема возникает в том случае, если я получаю из объекта его CDC *GetDC() и пытаюсь в нём рисовать. Сборка Debug тут же реагирует на такую попытку Assert'ом, но всё равно рисует. Мне не понятно такое поведение.
2 Toyo
Мой мэйл [email]tos@sinn.ru[/email], высылай.
Release освобождает память если на объект больше нет ни одной ссылки. А Инициализация(присваевание Указателю адреса контекста устройства) происходи как раз между(InitDialog()). Я в статику объект DirectX выводил тем же образом. Может и путаю сейчас чего.
Ты создаёшь кажется ссылку но не присваеваешь ей адрес объекта. А так как Контекст у тебя один, Зачем его столько раз создавать. Тем более Если он и так уже есть... Тебе лишь требуется на него сослаться...
Мой мэйл [email]tos@sinn.ru[/email], высылай.
Выслал. Если будут вопросы - пиши