Здравствуйте. Надеюсь на помощь.
Третий день бьюсь с проблемой: не работает двойная буферизация. Думал что разбираюсь в этом аспекте. Необходимо на одном HBITMAP нарисовать другой HBITMAP и выкинуть на экран 1-ый. Особенность в том, что второй HBITMAP меняется со временем, поэтому делаю так: храню в отдельной переменной m_hBackground_src "фон", а на экран выкидываю m_hBackground_tmp. Заливаю m_hBackground_tmp начальным фоном m_hBackground_src, затем на m_hBackground_tmp рисую новый HBITMAP, и затем выкидываю m_hBackground_tmp на экран.
Проблема в том, что m_hBackground_src где-то "портится" и приобретает значение m_hBackground_tmp при каждой прорисовки m_hBackground_tmp. Т.е. получается, что фон m_hBackground_src — это уже не тот первоначальный фон, а "куча" всех наложений битмэпа который должен меняться, получается помойка. Как будто где-то стоит строка m_hBackground_src = m_hBackground_tmp. Но фон m_hBackground_src меняться нигде не должен.
Где ошибка — до сих пор не понял, перекопал каждую строчку. Вот код:
// готовим контекст: рисовать на m_hBackground_tmp
Если память не изменяет, комбинация CreateCompatibleDC() и SelectObject(хдц, битмап) именно и приводит к тому, что вопреки ожиданиям в битмапе оказывается текущее содержимое экрана. Обойти можно 2-мя путями:
1. Src не заливать в Tmp ч-з битблит, т.е. не делать и SelectObject(src), а как-то перерисовыть src в tmp ручками. Попиксельно, переливая память и т.д.;
2. грубо хранить в памяти не битмап с чистым, незапятнанным фоном, а и контекст dcSrc и битмап bmSrc. В самом начале создать отдельный статический compatible dcSrc и статический же compatible bmSrc. В bmSrc при старте положить все, что хочешь, можно и экран битблитом (как Вы это скорее всего и делаете). И dcSrc и bmSrc хранить статически, не уничтожать, не делать с ними ничего, а покадрово или как у Вас там прямо из dcSrc плюхать в Tmp. Что-то вроде тройной буферизации. Да и побыстрее видимо будет.
Попробуйте. Я просто плохо воспринимаю Ваш код из-за смеси API и MFC (моя проблема) и форматирования здесь, в форуме (для ввода кода здесь есть внизу спецкнопки). Мог упустить что-то.
2-й способ врядли будет работать в win16 и не 100% надежно под win95 . А NT и дальше — ок.
G>Если память не изменяет, комбинация CreateCompatibleDC() и SelectObject(хдц, битмап) именно и приводит к тому, что вопреки ожиданиям в битмапе оказывается текущее содержимое экрана. Обойти можно 2-мя путями:
Память вам изменяет.
G>1. Src не заливать в Tmp ч-з битблит, т.е. не делать и SelectObject(src), а как-то перерисовыть src в tmp ручками. Попиксельно, переливая память и т.д.;
Вот тут — запомнить, HBITMAP hMemDCOldBitmap = SelectObject(hMemDC, m_hBackground_src);
K> BitBlt(dc.m_hDC, 0, 0, -1, -1, hMemDC, -1, -1, SRCCOPY);
K> SelectObject(hMemDC, hSecondHand_bitmap); K> BitBlt(dc.m_hDC, 100, 100, -1, -1, hMemDC, -1, -1, SRCCOPY);
K>// вроде все отрисовали, сохраняем отрисованный битмэп в m_hBackground_tmp и восстанавливаем в контекст первоначальный битмэп hbmMemOldBitmap
K> m_hBackground_tmp = (HBITMAP) dc.SelectObject(hbmMemOldBitmap);
Вот это непонятно. Вместо этого должно быть просто dc.SelectObject(hbmMemOldBitmap), зачем ты присваиваешь m_hBackground_tmp опять?
K> DeleteObject(hbmMemOldBitmap);
Тут надо SelectObject(hMemDC, hMemDCOldBitmap)
K> DeleteDC(hMemDC);
K>// сразу перерисовываем окно
K> RedrawWindow();
Обычно либо Invalidate делают, либо рисуют напрямую на DC окна.
K>/////////////////////////////////////////////////////////////////////////////////////////////////////////////
K>Отрисовка на экран:
K>void CMyProgDlg::OnPaint() K>{ K> CPaintDC dc(this);
K> CRect rect; K> GetClientRect(rect);
K> HDC hMemDC = ::CreateCompatibleDC(NULL); K> SelectObject(hMemDC, m_hBackground_tmp);
Тут надо запомнить old bitmap
K> ::BitBlt(dc.m_hDC, 0, 0, rect.Width(), rect.Height(), hMemDC, 0, 0, SRCCOPY);
Тут — SelectObject old bitmap обратно.
K> DeleteDC(hMemDC); K>}
K>Как я уже писал: в итоге получается что фон m_hBackground_src где-то "перетирается" и он сохраняет все предыдущие наложения битмэпов.
K>Где ошибка в коде?
Здравствуйте, Andrew S, Вы писали:
G>>Если память не изменяет, комбинация CreateCompatibleDC() и SelectObject(хдц, битмап) именно и приводит к тому, что вопреки ожиданиям в битмапе оказывается текущее содержимое экрана. Обойти можно 2-мя путями:
AS>Память вам изменяет.
Да, память изменяет. Бывает. Хотя я бы проверил практически насчет SelectObject. Только ведь никто не проверит, а автор ветки куда-то делся.
G>>1. Src не заливать в Tmp ч-з битблит, т.е. не делать и SelectObject(src), а как-то перерисовыть src в tmp ручками. Попиксельно, переливая память и т.д.;
Да, я бы сам так скорее всего делать не стал (п.1), но п.2 со статическим DC будет прекрасно работать.
AS>В общем, все остальное тоже сомнительно
G>>>Если память не изменяет, комбинация CreateCompatibleDC() и SelectObject(хдц, битмап) именно и приводит к тому, что вопреки ожиданиям в битмапе оказывается текущее содержимое экрана. Обойти можно 2-мя путями:
AS>>Память вам изменяет.
G>Да, память изменяет. Бывает. Хотя я бы проверил практически насчет SelectObject. Только ведь никто не проверит, а автор ветки куда-то делся.
Нет, не бывает, а изменяет, причем именно сейчас. И проверять там нечего, ваше утверждение неверно. Точка.
Здравствуйте, Andrew S, Вы писали:
G>>>>Если память не изменяет, комбинация CreateCompatibleDC() и SelectObject(хдц, битмап) именно и приводит к тому, что вопреки ожиданиям в битмапе оказывается текущее содержимое экрана. Обойти можно 2-мя путями:
AS>>>Память вам изменяет.
G>>Да, память изменяет. Бывает. Хотя я бы проверил практически насчет SelectObject. Только ведь никто не проверит, а автор ветки куда-то делся.
AS>Нет, не бывает, а изменяет, причем именно сейчас. И проверять там нечего, ваше утверждение неверно. Точка.