PDA

View Full Version : Qt + WINAPI + direct painting



JovianGhost
23rd March 2010, 03:11
I'm experimenting with direct painting to device contexts using WINAPI. Here's what my widget's paintEvent function looks like:



void ShotView::paintEvent(QPaintEvent *event)
{
qDebug() << "Start paint function";

HDC hdc = this->getDC();

if (hdc == NULL)
{
qDebug() << "HDC error";
return;
}

qDebug() << "Start painting";

HPEN hPen = CreatePen(PS_SOLID, 4, RGB(0, 255, 0));
if (hPen == NULL)
qDebug() << "CreatePen error";
if (SelectObject(hdc, hPen) == HGDI_ERROR)
qDebug() << "SelectObject error";
if (MoveToEx(hdc, 0, 0, NULL) == 0)
qDebug() << "MoveToEx error";
if (LineTo(hdc, 200, 200) == 0)
qDebug() << "LineTo error";

qDebug() << "End painting";

this->releaseDC(hdc);

qDebug() << "End paint function";
}


When I run the program, I don't see a solid red line appearing as I should. The console output seems correct:



Start paint function
Start painting
End painting
End paint function


so it looks like everything in the function is getting called properly, but I don't see an output. It's been a while since I've done WINAPI stuff, but I think I have it right. Can anyone offer any insight?

minimoog
23rd March 2010, 08:41
What about setting flag Qt::WA_PaintOnScreen?

JovianGhost
24th March 2010, 12:04
What about setting flag Qt::WA_PaintOnScreen?

I read in the docs this attribute is only supported under X11, and I'm running Windows.
Still, I tried it, no effect.

[edit]
I made a discovery. If I inherit from QWidget instead of QGraphicsView, it still doesn't work, but if I rapidly resize the widget I can see the line flickering, until it (presumably) gets painted over.

So what in QWidget is being called after paintEvent that's painting over my line?

minimoog
24th March 2010, 13:03
Set Qt::WA_PaintOnScreen in the QWidget constructor. Reimplement QPaintDevice::paintEngine() to return a null pointer. Just like is written in documentation on Qt::WA_PaintOnScreen.

It should be working.

pherthyl
24th March 2010, 17:03
Why are you using WinAPI to paint? Is there a problem with QPainter?

JovianGhost
25th March 2010, 02:16
I got it working, finally!


Set Qt::WA_PaintOnScreen in the QWidget constructor. Reimplement QPaintDevice::paintEngine() to return a null pointer. Just like is written in documentation on Qt::WA_PaintOnScreen.

It should be working.

That's what I did at first, but it didn't work. After you said this I went back to check it out and noticed something: when overriding paintEngine() I forgot to put the trailing "const" in the declaration and definition, so instead of



QPaintEngine* paintEngine() const { return 0; }


I had



QPaintEngine* paintEngine() { return 0; }


which of course did nothing. So thanks!


Why are you using WinAPI to paint? Is there a problem with QPainter?

To be honest, I never really considered QPainter. I was trying to do this as low-level as possible to reduce the overhead introduced by Qt's painting framework. But it looks like QPainter will do exactly what I need, thanks!

aamer4yu
25th March 2010, 04:05
But it looks like QPainter will do exactly what I need, thanks!
Thats how it is done in Qt.


To be honest, I never really considered QPainter. I was trying to do this as low-level as possible to reduce the overhead introduced by Qt's painting framework.
Then why use Qt... there will be some overhead still :P
juzz kidding.. theres always tradeoff between complexity of code and runtime. And Qt's paint framework is not that slow..also if you use QPainter, your code will be cross platform !

JovianGhost
26th March 2010, 01:05
Well I've been experimenting with QPainter and so far it's working very well!

aamer4yu
26th March 2010, 05:10
Well I've been experimenting with QPainter and so far it's working very well!

Good to know :) ... I guess you had underestimated Qt's performance :P