Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблемы с двойной буферизацией 
V
    Опции темы
InvalidProperty
Дата 25.5.2009, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: 1
Всего: 9



Проблема следующего рода:
для вывода jpg на контекст использую IImgCtx. Главное окно имеет вертикальный скролл. Хочу, чтобы при его прокручивании, изображение перемещалось, но не мерцало. Испольую двойную буферизацию. На WM_PAINT повешен следующий код:
Код

case WM_PAINT:
  {
   tagRECT        rect;
   int            scroll_pos = GetScrollPos(hwnd,SB_VERT);

   hdc = BeginPaint(hwnd, &ps);

   HDC hdcMem = CreateCompatibleDC(hdc);
   HBITMAP hOldBitmap = CreateCompatibleBitmap(hdcMem, g_iCXScreen, g_iCYScreen);
   HBRUSH brush = (HBRUSH)GetStockObject(WHITE_BRUSH);
   SelectObject(hdcMem, hOldBitmap);
   SelectObject(hdcMem, brush);
   PatBlt(hdcMem, 0, 0, g_iCXScreen, g_iCYScreen, PATCOPY);

   rect.top = 700 - scroll_pos*10;
   rect.bottom = img_size.cy + rect.top;
   rect.left = 0;
   rect.right = img_size.cx;
   m_pImage->Draw(hdcMem, &rect);

   BitBlt( hdc, 0, 0, g_iCXScreen, g_iCYScreen, hdcMem, 0, 0, SRCCOPY );

   SelectObject( hdcMem, hOldBitmap );
   SelectObject(hdcMem, brush);
   
   DeleteDC(hdcMem);

   EndPaint(hwnd, &ps);
  }
   return 0;


проблема в том, что вместо jpg картинки отображается черный квадрат, хотя и не мерцает, но от этого не легче. Если же написать так:

Код

m_pImage->Draw(hdc, &rect);


то картинка будет нормально выводиться на контекст. Вопрос: почему картинка не выводится на контекст в памяти, а на контекст устройства выводится нормально?


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
Andrey44
Дата 25.5.2009, 10:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 8
Всего: 26



Код

   HDC hdcMem = CreateCompatibleDC(hdc);
   HBRUSH oldBrush;
   HBITMAP hOldBitmap;
   HBITMAP hMemBitmap = CreateCompatibleBitmap(hdc, g_iCXScreen, g_iCYScreen);
   HBRUSH brush = (HBRUSH)GetStockObject(WHITE_BRUSH);
   hOldBitmap = (HBITMAP)SelectObject(hdcMem, hMemBitmap);
   oldBrush = (HBRUSH)SelectObject(hdcMem, brush);
   PatBlt(hdcMem, 0, 0, g_iCXScreen, g_iCYScreen, PATCOPY);
//.......................................

   SelectObject( hdcMem, hOldBitmap );
   SelectObject(hdcMem, oldBrush);



--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
InvalidProperty
Дата 25.5.2009, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: 1
Всего: 9



Andrey44, спасибо!

Я пытался найти информацию по гуглу и на форуме, но, к сожалению, видимо, плохо искал, так что прошу за вопрос палкой по пятке не бить.

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

hOldBitmap = (HBITMAP)SelectObject(hdcMem, hMemBitmap);
hOldBrush = (HBRUSH)SelectObject(hdcMem, brush);

и после копирования контекста еще и выбираем обратно эти объекты
Код

SelectObject(hdcMem, hOldBitmap);
SelectObject(hdcMem, hOldBrush);

Далее происходит удаление контекста устройства
Код

DeleteDC(hdcMem);

но ведь нужно еще и объекты удалить функцией DeleteObject.

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


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
GremlinProg
Дата 25.5.2009, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



классически, двойной буфер выглядит вообще-то примерно так:
Код

        case WM_PAINT:{
            PAINTSTRUCT ps;
            HDC hdc;
            HGDIOBJ hBitmap;
            int x,y,cx,cy;
            //
            ::BeginPaint(hWnd,&ps);
            x        = ps.rcPaint.left;
            y        = ps.rcPaint.top;
            cx        = ps.rcPaint.right - ps.rcPaint.left;
            cy        = ps.rcPaint.bottom - ps.rcPaint.top;
            hdc        = ::CreateCompatibleDC(ps.hdc);
            hBitmap    = ::CreateCompatibleBitmap(ps.hdc,cx,cy);
            hBitmap    = ::SelectObject(hdc,hBitmap);
            ::SetWindowOrgEx(hdc,x,y,NULL);
            //
            //  ... рисуем на hdc - двойном буфере ...
            //
            ::BitBlt(ps.hdc,x,y,cx,cy,hdc,x,y,SRCCOPY);
            //
            hBitmap    = ::SelectObject(hdc,hBitmap);
            ::DeleteObject(hBitmap);
            ::DeleteDC(hdc);
            ::EndPaint(hWnd,&ps);
            break;
        }

т.е. не нужно всякий раз создавать битмап на весь экран,
область для закраски ведь уже указана, это ps.rcPaint и она не всегда размером с экран
рабочий пример тут: http://forum.vingrad.ru/index.php?showtopi...t&p=1849405
Цитата(InvalidProperty @  25.5.2009,  15:02 Найти цитируемый пост)
но ведь нужно еще и объекты удалить функцией DeleteObject.

это да, обязательно: все, что вдолг взято нужно вернуть
Цитата(InvalidProperty @  25.5.2009,  15:02 Найти цитируемый пост)
Объясните, плиз, кому не сложно, как это все работает, что и для чего нужно вызывать.

каждому конечно не объяснишь, просто напоминаю: http://forum.vingrad.ru/index.php?showtopi...t&p=1808104


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Andrey44
Дата 25.5.2009, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 8
Всего: 26



Цитата(GremlinProg @  25.5.2009,  14:37 Найти цитируемый пост)
Код
hBitmap    = ::SelectObject(hdc,hBitmap);

Не знал что так можно.



--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
GremlinProg
Дата 25.5.2009, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Andrey44 @  25.5.2009,  17:12 Найти цитируемый пост)
Не знал что так можно

конечно можно, это же не HBITMAP:
Код

HGDIOBJ hBitmap;




--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
InvalidProperty
Дата 25.5.2009, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: 1
Всего: 9



GremlinProg, спасибо, но опять не понятно.

Понятно, что нужно перерисовывать только то, что указано в InvalidateRect, но я ведь указываю координаты вывода изображения в координатах окна (прошу прощения за тавтологию). Мне как-то не очень хочется каждый раз высчитывать, что будет перерисовано, а что нет. Может быть есть некие функции в winapi, которые облегчают данную участь? Т.е. вопрос в следующем: я хочу перерисовать только некоторую область, приходящую в paintstruct, но при этом я не хочу заморачиваться, что именно это за область и координаты всех картинок хочу просчитывать в координатах окна, а не области. Как мне это сделать?
Код

   rect.top = 700 - scroll_pos*10;
   rect.bottom = img_size.cy + rect.top;
   rect.left = 0;
   rect.right = img_size.cx;
   m_pImage->Draw(hdcMem, &rect);



--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
GremlinProg
Дата 25.5.2009, 19:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(InvalidProperty @  25.5.2009,  19:08 Найти цитируемый пост)
Мне как-то не очень хочется каждый раз высчитывать, что будет перерисовано, а что нет

тут проблем не должно быть:
буфер распределяется размером с rcPaint  ( CreateCompatibleBitmap(ps.hdc,cx,cy) )
координаты этого буфера автоматически устанавливаются в нужное положение ( SetWindowOrgEx(hdc,x,y,NULL) )
т.е. ничего считать каждый раз не нужно, все функции GDI при работе с hdc автоматически будут рисовать только в пределах этого буфера, все остальное будет отсекаться
Цитата(InvalidProperty @  25.5.2009,  19:08 Найти цитируемый пост)

Код

   rect.top = 700 - scroll_pos*10;
   rect.bottom = img_size.cy + rect.top;
   rect.left = 0;
   rect.right = img_size.cx;
   m_pImage->Draw(hdcMem, &rect);


это уже касается области прокрутки, а не двойной буферизации

я тут ожидал бы непосредственно описание работы со scrollbar'ом:
получение позиции окна - GetScrollPos,
корректную обработку сообщений WM_HSCROLL / WM_VSCROLL
и инициализацию скроллбара (SetScrollInfo)


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
InvalidProperty
Дата 29.5.2009, 09:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: 1
Всего: 9



GremlinProg, 
Andrey44, большое спасибо за содействие


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0517 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.