Russian Qt Forum
Ноябрь 25, 2024, 10:40 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Qt 4.1.4 - баг в getDC() / ReleaseDC() ?  (Прочитано 7658 раз)
ElderOrb
Гость
« : Август 29, 2006, 14:54 »

для вывода изображения с камеры использую QWidget с paintEngine = 0, упакованный в QScrollArea (пробовал выводить просто в QWidget - наблюдал неприятные мерцания и т.п. при скроллинге и ресайзе не зависимо от состояния оконных флагов!!!) Т.к. paintEngine = 0, отрисовать что-то поверх изображения с камеры с помощью QPainter-а нереально. А надо. Приходится отрисовывать через winAPI, для функций которого нужен HDC. Если получать hdc через QWidget::getDC() / releaseDC() то при скроллинге отрисовка производится не полностью а иногда не производится вовсе!.. если же через апишные - GetDC() / ReleaseDC() - почти ок. Баг? Вот код, иллюстрирующий вышесказанное:

bool mvsstand::eventFilter(QObject *o, QEvent *e)
{
   if(o == w) {
      if(e->type() == QEvent::Paint) {

         QWidget *that_widget = w;
         w = 0;
         QApplication::sendEvent(o, e);
         w = that_widget;

         // такой способ работает
         HDC dc = GetDC(w->winId());

         // а такой - нет !
         //HDC dc = w->getDC();

         HPEN pen = CreatePen(PS_SOLID, 1, RGB(0,0xFF,0xFF));
         SelectObject(dc, pen);
         SetTextColor(dc, RGB(0xFF,0,0));
         LineTo(dc, 100, 100);

         qDebug("paint event, %d", QTime::currentTime());
         /*
         QPainter p(w);
         p.fillRect(0, 0, 100, 100, Qt::green);
         */
         DeleteObject(pen);

         //w->releaseDC(dc);
         ReleaseDC(w->winId(), dc);

         return true;
      }      
   }   

   return QMainWindow::eventFilter(o, e);
}
Записан
Admin
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1988



Просмотр профиля
« Ответ #1 : Август 29, 2006, 21:25 »

я свой код публиковал мерцаний нет

еще раз маленький исходник

#include "ibrs.h"

CFastImage::CFastImage(QWidget* parent)
 : QWidget(parent)
{
    m_data=NULL;
     setAttribute( Qt::WA_PaintOnScreen, true);
}

CFastImage::~CFastImage()
{
   if(m_data!=NULL) delete[] m_data;
}

void CFastImage::paintEvent(QPaintEvent* p)
{
    // just for illustration purposes. You get the same effect if you leave the paint event completely empty, too.
    QWidget::paintEvent(p);

   BITMAPINFO   BMP;
   BMP.bmiHeader.biWidth=width;
   BMP.bmiHeader.biHeight=height;
   BMP.bmiHeader.biBitCount=24;

   BMP.bmiHeader.biSize      = sizeof (BITMAPINFOHEADER);
   BMP.bmiHeader.biPlanes      = 1;
   BMP.bmiHeader.biCompression   = BI_RGB;
   BMP.bmiHeader.biSizeImage = ( ( BMP.bmiHeader.biWidth * ( BMP.bmiHeader.biBitCount >> 3 ) + 3 ) & - 4 ) * BMP.bmiHeader.biHeight;

   HDC hdc = GetDC(winId());

    SetStretchBltMode( hdc, COLORONCOLOR );
   
   StretchDIBits ( hdc , 0 , 0 , width , height , 0 , 0 , width , height , m_data , &BMP , DIB_RGB_COLORS , SRCCOPY );

    ReleaseDC(winId(), hdc);
}

QPaintEngine* CFastImage::paintEngine() const
{
     return 0;
}
Записан
ElderOrb
Гость
« Ответ #2 : Август 29, 2006, 22:02 »

Спасибо за пример, но у меня похоже несколько иная ситуация. Библиотека распознавания сама пишет захваченные кадры в окно (там создаётся объект которому нужен hwnd окна и он занимается всем).
Мне же надо поверх выводить свою графику. Если я правильно понял, я смогу частично использовать вышеизложенный подход для вывода своей информации, для чего надо делать как-то так: писать всё что я хочу отрисовать в QImage, в paintEvent-е заполнять структуру BITMAPINFO и через StretchDIBits отрисовывать на экран используя в качестве данных QImage::bits() ? Если это заработает (а это я проверю завтра) будет отлично!.. Хотя в идеале хотелось бы сохранить Qt-шную paintEngine-у для большего удобства рисования.  

В ходе экспериментов с оконными флагами возник ещё вопрос, почему так странно работает нижиприведённый код. Странности следующие:
1. независимо от того, что написано в paintEvent-е ни на что не влияют оконные флаги, (т.е при рисовании через QPainter всё ок, через gdi - непрорисовывает вообще или прорисовывает частично и со страшным мерцанием).

2. HDC dc = w->getDC(); возвращает 0 !!!

Код:

PaintingTest::PaintingTest(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags)
{
ui.setupUi(this);

//QScrollArea* area = new QScrollArea;
w = new QWidget;
w->resize(1024, 768);
//area->setWidget(w);

//setCentralWidget(area);
setCentralWidget(w);

w->installEventFilter(this);
// w->setAttribute(Qt::WA_OpaquePaintEvent); // фон становится чёрным, перерисовка кривая
// w->setAttribute(Qt::WA_NoSystemBackground); // то же самое
// w->setAttribute(Qt::WA_StaticContents); // фон нормальный, перерисовка кривая
// w->setAttribute(Qt::WA_PaintOnScreen); то же самое
// w->setAutoFillBackground(false); // то же самое.. если true - аналогично
}

PaintingTest::~PaintingTest()
{

}

bool PaintingTest::eventFilter(QObject* o, QEvent* e)
{
if(o == w) {
if(e->type() == QEvent::Paint) {

//паинтер рисует нормально, без мерцаний
//QPainter p(w);
//p.drawLine(0, 0, 400, 400);

//hdc = 0 !!!
//HDC dc = w->getDC();

//dc != 0
HDC hdc = GetDC(w->winId());

HPEN hPen = CreatePen(PS_SOLID, 10, RGB(00,0xff,00));
SelectObject(hdc,hPen);

// рисует при ресайзе и т.п наблюдаются мерцания, не всегда прорисовывается
LineTo(hdc, 100, 100);
DeleteObject(hPen);

ReleaseDC(w->winId(), hdc);

//w->releaseDC(dc);
}
}
return QMainWindow::eventFilter(o, e);
}


p.s. хотел удобства ради запостить весь проект да обнаружил что некак ж). Может быть стоит ввести такую фичу в форум?
Записан
Admin
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1988



Просмотр профиля
« Ответ #3 : Август 30, 2006, 00:40 »

только мысля:

при ресайзе скорее всего приходят 2 типа сообщений
QEvent::Paint и QEvent::Resize
причем как извесно отрисовка это самая низкоприоритетная задача
возможно тут сабака и зарыта

далее нашел в исходниках QPaintDevice

/*! \internal
*/
HDC QPaintDevice::getDC() const
{
    return 0;
}

/*! \internal
*/
void QPaintDevice::releaseDC(HDC) const
{
}

на что то похоже

PS: проект можно упаковать и прилипить на форум в виде zip или rar файла
Записан
ElderOrb
Гость
« Ответ #4 : Август 30, 2006, 10:53 »

Что-то у меня не получается черз битмэп. ж( А ещё я не могу найти где приатачить файл к форуму. Поэтому снова кидаю код сюда. Буду очень благодарен за информацию где же я затупил в этот раз ж) w - потомок QWidget-а с paintEngine = 0 (хотя если она и не ноль - ничего не меняется) на экране - пусто ж(

bool PaintingTest::eventFilter(QObject* o, QEvent* e)
{
   if(o == w) {
      if(e->type() == QEvent::Paint) {

         /*
         QWidget* ww = w;
         w = 0;
         QApplication::sendEvent(o, e);
         w = ww;
         */

         int width = w->width();
         int height = w->height();

         QImage image(width, height, QImage::Format_RGB32);
         QPainter p;
         p.begin(&image);
         p.drawLine(0,0, 100, 100);
         p.fillRect(200, 200, 50, 50, Qt::green);
         p.end();

         BITMAPINFO BMP;
         BMP.bmiHeader.biWidth=width;
         BMP.bmiHeader.biHeight=height;
         BMP.bmiHeader.biBitCount=24;

         BMP.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
         BMP.bmiHeader.biPlanes = 1;
         BMP.bmiHeader.biCompression = BI_RGB;
         BMP.bmiHeader.biSizeImage = ( ( BMP.bmiHeader.biWidth * ( BMP.bmiHeader.biBitCount >> 3 ) + 3 ) & - 4 ) * BMP.bmiHeader.biHeight;

         HDC hdc = GetDC(winId());
         SetStretchBltMode( hdc, COLORONCOLOR );
         StretchDIBits ( hdc , 0 , 0 , width , height , 0 , 0 , width , height , image.bits() , &BMP , DIB_RGB_COLORS , SRCCOPY );
         ReleaseDC(winId(), hdc);

         return false;

      }
   }
   return QMainWindow::eventFilter(o, e);
}
Записан
Admin
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1988



Просмотр профиля
« Ответ #5 : Август 30, 2006, 12:21 »

ну первое что видно

в QImage 32 бита на точку
а в bitmap 24

Image image(width, height, QImage::Format_RGB32);
 BMP.bmiHeader.biBitCount=24;

2 вещь: не забываем что в BMP снизу вверх отчет идет, мак мать его
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.134 секунд. Запросов: 23.