PDA

View Full Version : Using StretchDIBits() in QWidget



bear101
4th May 2009, 20:14
Hi

I've subclasses a QWidget because I want to perform my own drawing using Windows' StretchDIBits() function (I'm painting video frames). I've overwritten QWidget::paintEvent() where I'm doing my drawing like this:


void MyWidget::paintEvent(QPaintEvent *p)
{
HWND hWnd = winId();
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hWnd, &ps);
BOOL b = StretchDIBits(hdc, 0, 0, rect().width(), rect().height(), 0, 0,
bmh.biWidth, bmh.biHeight*-1, frm->frame, &bmi,
DIB_RGB_COLORS, SRCCOPY);
EndPaint(hWnd, &ps);
}

'bmh' is a BITMAPINFOHEADER and 'frm' is a byte-array of bitmap data.

When the paintEvent is called nothing is, however, shown. Why is this? When I use the above code in my MFC app it works fine (when I receive WM_PAINT).

-- Bjoern

Lykurg
4th May 2009, 20:22
You joined 2006 and now is your first post :eek: Strange. However, nowadays we have [ CODE ] tags for a good display of code fragments. Pleas use them in further post.

To your question: Don't you have to use the painter of the widget:
QPainter painter(this);?

wysota
4th May 2009, 20:24
WM_PAINT and paintEvent are not equivalent. I don't know if this will work but try setting the WA_PaintOnScreen attribute on the widget and do the other things mentioned in the attribute's docs.

bear101
4th May 2009, 20:37
Hi

Thanks for the quick replies. Actually I'm trying to make a DLL which receives a HWND and then paints a bitmap in the window. I thought I could do this in paintEvent() by providing my DLL function with the window's HWND. Can't this work with QWidget?

Btw, yes, it's been three years since I last used Qt. Trolltech changed their license model so it suddenly became interesting to try out in my new company.

I've also tried the following which also doesn't work (and probably for the same reason):



void MyWidget::paintEvent(QPaintEvent *p)
{
HWND hWnd = winId();
HDC hdc;
hdc = ::GetDC(hWnd);
RECT r;
r.left = this->rect().left()+50;
r.top = this->rect().top()+50;
r.right = this->rect().right();
r.bottom = this->rect().bottom();
int xx = ::DrawText(hdc, L"FOOOOOOOOOO", 5, &r, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
ReleaseDC(hWnd, hdc);
}


-- Bjoern

bear101
5th May 2009, 00:06
Ah, I found the solution on page 417 in the QT book. It will work using something like this:


void MyWidget::paintEvent(QPaintEvent *p)
{
QPainter painter(this);
HWND hWnd = winId();
HDC hdc = painter.paintEngine()->getDC();
RECT r;
r.left = this->rect().left()+50;
r.top = this->rect().top()+50;
r.right = this->rect().right();
r.bottom = this->rect().bottom();
int xx = ::DrawText(hdc, L"FOOOOOOOOOO", 5, &r, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
painter.paintEngine()->releaseDC(hdc);
}

wysota
5th May 2009, 00:37
Be aware this is not safe without proper preparations. Your paintEvent will be called to draw something to the backing store so you have to prevent that by using PaintOnScreen. And your application will behave slower, by the way but if you really need a DC context then there is no way to avoid that. You can obtain the same effect using Qt only calls without any downsides.