Форум программистов, компьютерный форум, киберфорум
Visual C++
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/46: Рейтинг темы: голосов - 46, средняя оценка - 4.91
0 / 0 / 0
Регистрация: 22.09.2007
Сообщений: 314
1

Двойная буферизация под Win на VC++ (MFC)

25.11.2011, 00:15. Показов 8291. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Двойная буферизация под Win на VC++(MFC) - кто-нибудь знает - это вообще возможно??
Или по-другому: можно-ли создать в MFC SDI копию объекта вида(View) и рисовать в него, а потом подменивать на ту, которая на экране? Или такой ход прокатит только на MDI?? Если только на MDI, то как?
Проблема известная: при редактировании изображения остаются артефакты, изображение перерисовывается некорректно. Пробовал различные ухищрения через режим инверсии - получается какая-то кустарщина. Хочется похоронить проблемы с перерисовкой объекта вида разом и навсегда. Если кто сталкивался с проблемой(и успешно решил)помогите плиз...
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.11.2011, 00:15
Ответы с готовыми решениями:

Двойная буферизация
Собственно, не работает ни при DoubleBuffered = true;, ни при...

Двойная буферизация на С++
Можно её реализовать для консоли, а то больно уж сильно экран мигает. Если можно то подскажите как...

двойная буферизация
Здравствуйте. Ребят не сочтите за труд, помогите разобраться. Проблема собственно вот в чём: Пишу...

Двойная буферизация
Добрый день. Программа должна принимать текст с клавиатуры, выводить его на экран и реагировать на...

7
7 / 7 / 12
Регистрация: 13.02.2007
Сообщений: 1,255
25.11.2011, 01:58 2
Посмотри вот эту статью, по-моему, это как раз то, что ты ищешь:
http://www.codeproject.com/gdi/flickerfree.asp

Удачи,
Владимир
0
0 / 0 / 0
Регистрация: 22.09.2007
Сообщений: 314
26.11.2011, 11:58  [ТС] 3
Вроде и оно, и не оно. Там используется в качестве буфера bitmap, и вообще я не до конца понял как оно там работает. У меня рисование происходит в ф-ии OnMouseMovie на обычный контекст устройства pDC, старые линии я стираю с помощью режима инверсии(сначала рисую по старой линии инверсным цветом - и тем самым стираю ее, а потом рисую новую)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void CBezieView::OnMouseMove(UINT nFlags, CPoint point) 
{
    CBezieDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
 
        pDC->SetROP2(R2_NOT);
        
    pDC->Polyline(pDoc->m_BasePointsArray.GetData(), 
            pDoc->m_BasePointsArray.GetSize());
        
    pDoc->m_BasePointsArray.SetAt(number, point);
 
    pDC->Polyline(pDoc->m_BasePointsArray.GetData(), 
            pDoc->m_BasePointsArray.GetSize());
 
    OldPoint = point;
    CView::OnMouseMove(nFlags, point);
}
хочется понять, как рисовать не на настоящий экран, а на виртуальный, и потом его за одну операцию выводить.
Вроде класс CBitmap позволяет создать виртуальный bitmap, но непонятно как в объект типа CBitmap рисовать, и как его выводить на экран.
0
7 / 7 / 12
Регистрация: 13.02.2007
Сообщений: 1,255
26.11.2011, 15:34 4
Хех, за отрисовку на OnMouseMove я бы кое кому по башке на стучал есть такая вещь как OnDraw/OnPaint и Invalidate весь мир использует этот подход.

Но даже и в твоем примере можно использовать класс описанный в вышеуказанной статье для создания Double Buffer. Начиная с того момента, где ты первый раз прикасаешься к pDC, оберни его классом CMemDC и будет создан тот самый виртуальный буфер. Дальше рисуй (Polyline) используя вновь созданный объект CMemDC, а при выходе из процедуры деструктор объекта CMemDC сам скопирует все на реальный pDC. Вот и все.

Код примерно будет выглядеть следующим образом:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void CBezieView::OnMouseMove(UINT nFlags, CPoint point) 
{
    CBezieDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    
    CMemDC memDC(pDC);
    memDC->SetROP2(R2_NOT);
    
    memDC->Polyline(pDoc->m_BasePointsArray.GetData(),
        pDoc->m_BasePointsArray.GetSize());
    
    pDoc->m_BasePointsArray.SetAt(number, point);
    
    memDC->Polyline(pDoc->m_BasePointsArray.GetData(),
        pDoc->m_BasePointsArray.GetSize());
    
    OldPoint = point;
    CView::OnMouseMove(nFlags, point);
}
Можно использовать как memDC->SetROP2, так и memDC.SetROP2, класс CMemDC разрешает оба подхода.

Советую все-таки разобраться, для чего существует метод OnDraw и команда Invalidate. Простой пример, сверни свою программу по кнопке minimize, а потом разверни таким образом, чтобы не создавать движения мышкой по окну, например при помощи Alt+Tab.

С уважением,
Владимир
0
7 / 7 / 12
Регистрация: 13.02.2007
Сообщений: 1,255
26.11.2011, 15:42 5
P.S. только сейчас посмотрел, что ты делаешь при отрисовке. В случае с CMemDC операции:
C++
1
2
3
memDC->SetROP2(R2_NOT);
memDC->Polyline(pDoc->m_BasePointsArray.GetData(),
              pDoc->m_BasePointsArray.GetSize());
можно заменить заливкой цветом фона:
C++
1
memDC->FillRect(...);
и последующей отрисовкой линии без всякого XOR, это намного быстрее чем инверсная отрисовка полигона с целью стереть уже отрисованное.
0
0 / 0 / 0
Регистрация: 22.09.2007
Сообщений: 314
26.11.2011, 16:29  [ТС] 6
Цитата Сообщение от boombastik
Хех, за отрисовку на OnMouseMove я бы кое кому по башке на стучал есть такая вещь как OnDraw/OnPaint и Invalidate весь мир использует этот подход.
Дело в том что я редактирую кривую Безье за базовые точки (узлы) "в реальном времени", как в редакторах векторной графики типа Corel или FreeHand. Насколько я знаю, во время движения мышью по экрану отрабатывается только OnMouseMove.

Цитата Сообщение от boombastik
Начиная с того момента, где ты первый раз прикасаешься к pDC, оберни его классом CMemDC и будет создан тот самый виртуальный буфер.
что значит "обернуть"? Что означает следующая запись?
Код
CMemDC memDC(pDC);
Цитата Сообщение от boombastik
Советую все-таки разобраться, для чего существует метод OnDraw и команда Invalidate. Простой пример, сверни свою программу по кнопке minimize, а потом разверни таким образом, чтобы не создавать движения мышкой по окну, например при помощи Alt+Tab.
И когда же отрабатывается OnDraw? Например при максимизации срабатывает? Где можно почитать про OnDraw? (Желательно по русски, но если популярно - то можно и по-английски) OnDraw? В книгах про него сказано в двух словах, не до конца ясен механизм.

PS: Большое спасибо, [bold]boombastik, [/bold] наконец я что-то начинаю понимать.
0
7 / 7 / 12
Регистрация: 13.02.2007
Сообщений: 1,255
26.11.2011, 17:39 7
Когда я говорил про "OnDraw/Invalidate" я имел ввиду подход, который размещения отрисовки изображения окна в одном месте (одном методе). Обычно обработчик события отрисовки называется OnDraw (иногда OnPaint).

Это делается для того, чтобы не разбрасывать кусочки кода по отрисовке в разных местах, что усложняет поддержку в будущем такого приложения. Попробуй потом найди, где ты разместил отрисовку таймера в углу окна, на какое событие отрисовываются кривые и где отрисовывается заливка контура. Вместо этого, отрисовка экрана размещена в одном единственном месте: обработчике OnDraw.

Этим подходом пользуется архитектура Win32 приложений, он же поддерживается библиотеками MFC.

Да, OnDraw будет вызван автоматически после изменений размеров окна, на события maximize и restore, а также после того как другое окно, закрывающее твое будет отодвинуто в сторону и освободит часть пространства, которое должно быть перерисовано.

Нет, OnDraw не будет вызван автоматически после того как пользователь передвинешь мышку, так же не сработает, после отсчета очередной секунды таймера (если, например, приложение изображает часы в углу). Для этих целей существует метод Invalidate, который который генерирует событие отрисовки окна, после чего автоматически вызывается обработчик OnDraw.

Итак, каждый раз, когда тебе требуется отрисовать изображение по новой, просто вызывай метод Invalidate.

Для твоего примера, код будет выглядеть примерно следующим образом:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void CBezieView::OnDraw(CDC* pDC)
{
    CBezieDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
 
    // Используем CMemDC для отрисовки по принципу Double Buffer
    CMemDC memDC(pDC);
 
    // Заливка белым
    CRect rect;
    GetClientRect(&rect);
    memDC->FillSolidRect(rect, RGB(255, 255, 255));
 
    // Отрисовка полигонов (один раз)
    memDC->Polyline(pDoc->m_BasePointsArray.GetData(),
        pDoc->m_BasePointsArray.GetSize());
}
 
void CBezieView::OnMouseMove(UINT nFlags, CPoint point) 
{
    CBezieDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
 
    // Добавим позицию в массив
    pDoc->m_BasePointsArray.SetAt(number, point);
 
    // Сохраним текущую позицию мышки
    OldPoint = point;
 
    // Вызовем отрисовку экрана (так как изображение изменилось)
    Invalidate();
 
    // Вызовем оригинальный обработчик перемещения мышки
    CView::OnMouseMove(nFlags, point);
}
что значит "обернуть"? Что означает следующая запись?
C++
1
CMemDC memDC(pDC);
Означает, что ты создашь объект класса CMemDC (см. статью, ссылку на которую я давал выше), который возьмет на себя заботу о создании Double Buffer и копировании туда текущего состояния pDC, после этого, ты используешь его, как обычный класс CDC (рисуешь, заливаешь, стираешь), по выходе из функции, все созданные объекты удаляются, точно также будет удален и объект memDC, по-этому сработает его деструктор, в котором произойдет копирование из невидимого буфера на контекст устройства pDC (то есть на экран).

Прочитать про это можно... м... фиг знает опыт, MSDN, codeproject, примеры из Platform SDK, вот, например, запись про Invalidate:
http://msdn.microsoft.com/libr... lidate.asp

там есть ссылка на пример с использованием UpdateWindow, его можно самостоятельно вызывать, но не нужно, он будет вызван автоматически, ну в общем-то там про это и написано.

Посмотри сайт http://www.firststeps.ru/ раздел MFC, там среди первых шагов про CPaintDC.... ой... не, там ерунда, не описывают для чего и почему, а лишь показывают как это сделать.

Хотя вроде есть немного, вот описание CWnd методов на-русском:
http://www.firststeps.ru/mfc/s... help4.html

Вот пример с OnPaint и ф-цией Invalidate:
http://www.firststeps.ru/mfc/steps/r.php?19

Тебе не нужно забо
0
0 / 0 / 0
Регистрация: 22.09.2007
Сообщений: 314
26.11.2011, 18:22  [ТС] 8
Цитата Сообщение от boombastik
Посмотри сайт http://www.firststeps.ru/ раздел MFC, там среди первых шагов про CPaintDC.... ой... не, там ерунда, не описывают для чего и почему, а лишь показывают как это сделать.
вот-вот, большинство источников просто показывают как это делать, вскользь упоминая про принцип работы.
Цитата Сообщение от boombastik
Хи-хи, вот так описывается ф-ция OnDraw по-русски (лично я ничего не понял):
http://www.firststeps.ru/mfc/steps/help/r.php?106
Это вообще халява, переведено из какого-то англоязычного источника программой - переводчиком и немного подправленно *) по стилю текста видно

Спасибо большое, все что узнал - применю на практике и напишу сюда, получилось или нет
0
26.11.2011, 18:22
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.11.2011, 18:22
Помогаю со студенческими работами здесь

Двойная буферизация и др
Всем доброго времени суток! Нужно реализовать отрисовку графики (квадраты, текст, картинки) в...

Двойная Буферизация
Добрый вечер. При создании двойной буферизации при попытке получить графический контекст...

двойная буферизация
Здравствуйте! У меня есть объект Panel с именем infoPanel, рисую я в нём так: private void...

Двойная буферизация
Написал тетрис (но только с палочками (друг попросил сделать =) )) Писал на чистом WinAPI, в...

Двойная буферизация!
Пишу очень облегченное и просто подобие старого Пеинта, но столкнулся с одной проблемой рпи...

Двойная буферизация
Надо включить двойную буферизацию в приложении. на MSDN написано, что это делается так: ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru