| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Системное программирование и WinAPI > Двойная буферизация - как правильно? |
| Автор: Arks 17.9.2007, 19:47 | ||||
| В общих словах: Требуется использовать двойную буферизацию. В буфере в памяти надо программно рисовать цветные примитивы (линии, треугольники). Вот таким образом я пытался реализовать двойную буферизацию по примеру с мсднки (с онлайна откуда-то):
Потом нашёл вот эту тему: http://forum.vingrad.ru/forum/topic-117538/unread-1/hl/createdibsection/index.html Попытался реализовать, как написано там. Вот что вышло:
Проблема в том, что CreateDIBSection возвращает NULL, т.е. ничего не создаёт. Надеюсь получить разяснения или хотя бы пример - полноценный рабочий код (ссылку на него) |
| Автор: Arks 18.9.2007, 21:39 | ||||||||
Нет, т.к. это статическая переменная. Впрочем, на всякий пожарный, я изменил код. Смотрите первый листинг.
Так в том то и дело, что CreateDIBSection имеет следующий прототип: HBITMAP CreateDIBSection( HDC hdc, CONST BITMAPINFO *pbmi, UINT iUsage, VOID **ppvBits, HANDLE hSection, DWORD dwOffset); Туда надо передавать void** иначе вообще не компилится. На счёт третьего, спасибо, что указали. Только один вопрос: а если рисуется за областью отсечения? Что будет? Просто не выведет на экран?
Итог: то что рисуется в cdc так и не рисуется. Нашёл странность: bmp= CreateDIBSection( ... ); if(!bmp) { MyGetLastError(hWnd); } if(!SelectObject(cdc,bmp)) { MyGetLastError(hWnd); } Вот здесь обе MyGetLastError выполняются! При этом оба раза GetLastError возвращает 0, т.е. "Операция завершена успешно". MyGetLastError:
|
| Автор: Mihhail 19.9.2007, 07:04 | ||||||
Откуда эти сведения? Привожу выписки из справки о функции CreateDIBSection(перевод Сократа):
VOID *pvBits; тоже в глобальные!
Да, вывод осуществляется только в пределах существующих координат картинки(HBITMAP) контекста(HDC), отсекаются все попытки вывода за их пределами, как в плюс так и в минус, как в буфуре так и на экране. Можно буфер сделать больше нежели окно вывода, тогда можно будет обеспечить прокрутку изображения. Т.е. изменять координаты X и Y и вставляя их в BitBlt(hdc,0,0,width,height,cdc,X,Y,SRCCOPY) |
| Автор: Arks 19.9.2007, 14:40 | ||
| 1ый источник - компилятор, который ваш код не пропускает 2ой - МСДН:
http://msdn2.microsoft.com/en-us/library/ms532292.aspx Читать надо первоисточники. |
| Автор: Earnest 19.9.2007, 17:59 | ||
| 1) ppBits действительно должно быть указателем на LPVOID, т.е. на адрес переменной, куда положат адрес выделенного буфера. 2) Твоя MyCreateDIBSection в любом случае не будет работать (даже если секция внутри создастся).
Причина - ты передаешь возвращаемые параметры по-значению. И как ты собрался ими пользоваться?. Ты бы внимательно пост прочитал. Видмо, если CreateDIBSection возвращает 0, стало быть с параметрами что-то не так. |
| Автор: Arks 19.9.2007, 20:20 | ||
| Ах, и вправду по значению. Правда, я использовал не её, а вызывал саму CreateDIBSection. Но исправил, попробовал через неё запустить. Не заработало. Исправил, т.е. так:
Результат тот же (MyCreateDIBSection вернула 0), ничего не создалось. Меня одно смущает: почему MyGetLastError при коде ошибки 0 выводит "Операция успешно завершена." Она ведь не завершена, или по крайней мере не успешно! Если не сложно, посмотрите мою прогу сами. И не гневайтесь сильно, что туплю... Я в винапи ещё совсем плаваю. Лучше книжечку серьёзную (связанную с интерфейсом и GDI - очень нужно, т.к. весь семестр рисованием разным заниматься буду) посоветуйте. http://slil.ru/24875738 А Михаил и вправду неверные данные дал. Может конечно Сократ их покоцал? Впрочем, извиняюсь, если не очень корректно ответил. |
| Автор: Mihhail 19.9.2007, 23:26 | ||||
Действительно в справке ошибка с указателем, да и по названию переменной ppvBits можно догадаться о типе. Mea culpa! Нашёл я у себя объявление этой функции: WINGDIAPI HBITMAP WINAPI CreateDIBSection( IN HDC, IN CONST BITMAPINFO *, IN UINT, OUT VOID **, IN HANDLE, IN DWORD); Скачал я программку. У меня сначала была такая же ерунда с bmp, помогло изменение типа переменной. Вот ключевые моменты в коде:
Ещё один момент, перед заполнением структуры BITMAPINFO i; должны быть уже известны width и height! Arks у вас в задании сказано что нужна именно CreateDIBSection? А то ведь есть очень простая функция создания картинки: HBITMAP CreateCompatibleBitmap( HDC hdc, int nWidth, int nHeight ); Никаких дополнительных заморочек, только ширина и высота! |
| Автор: Arks 20.9.2007, 07:46 |
| Михаил, у меня в задания в принципе не указано, какими средствами и даже на каком языке я должен это делать. Надо чтобы программа задание выполняла, а остальное мои заботы. Кстати, с CreateCompatibleBitmap я тоже пытался написать. Только что получилось, основная ошибка и там и там, я в другом сообщении заполнял width и height. И при первом вызове WM_PAINT они были не инициализированы. Также здесь я создал VOID **m_pBits; как вы порекомендовали. Заработало. Прикол: Заработал именно вызов CreateDIBSection из WM_PAINT. При использовании же той, не моей функции, которая кучу всего делает при заполнении BITMAPINFO, она выполняется, но когда делаешь SelectObject(cdc,bmp), выкидывается ошибка "Недостаточно памяти". И это при моём гигабайте!!! Ну да ладно, главное разобрался и с CreateDIBSection, и с CreateCompatibleBitmap. Теперь остался только один вопрос: Какая разница между этими двумя функциями. Просто более широкие параметры настройки у первой? И всё? А остальное: читать, писать в созданные области памяти можно абсолютно одинаково. Так? И да, книжку по GDI (ну и ещё чему интересному) не порекомендуете? |
| Автор: Mihhail 20.9.2007, 16:39 | ||
Да, не имеет значения какой функцией создавать область вывода. Просто CreateCompatibleBitmap использует настройки палитры и глубины цвта указанного контекста (в нашем случае экранные). В чём особенность CreateDIBSection - она даёт указатель на начало растровых данных, тот самый ppvBits, т.е. возможно менять значения байтов отдельных пикселей и их составляющих (RGB) непосредственно в памяти, что во много раз быстрее чем при вызове функций рисования, но мение удобно. К тому же с помощью этой функции есть возможность считывать изображения из файла. Моя любимая и единственная книжка по программированию - это справочная система Borland C++Builder 6! Шучу конечно, но так что бы где-то толково и полностью о GDI было написано я лично не встречал таких книг. |
| Автор: Arks 20.9.2007, 22:04 |
| Всё ясно. Спасибо вам за помощь. |