PDA

View Full Version : Display only PNG image on desktop



durbrak
13th May 2007, 22:39
Hello,

Well, you probably all already heard this question 100x times before and I just finished 3 hours of research for this problem.

All I need right now is a confirmation that I simply cannot display PNG images ontop of my desktop with Qt4/Windows.
I don't mean like display them in a window, I just mean the PNG image with no dialog or window/backgound whatsoever.

I know I can display a simple png image on my desktop (assuming the image is rectangular with no transparent pixels),
and I know I can display some an image with completely transparent pixels using setMask(),
and I know I can display the whole image transparent (setWindowOpacity())...

...but what I can't seem to be able to do (under Windows!) is to display an image which has some opaque and some 20% transparent pixels and some 50% transparent pixels and so on.

So assuming I have this image (as you can see the shadow around the egg is transparent):

http://img255.imageshack.us/img255/9053/imagejr5.jpg

And I want it do be display on my desktop:

http://img386.imageshack.us/img386/9567/windowedau5.jpg

So I've seen all kinds of solutions with setMask() and whatever but all I need is a confirmation that under Windows I simply cannot use Qt to achieve this effect.

So can anyone confirm that this is not possible with Qt (yet) so that I can stop searching for a solution?
Thanks!

wysota
13th May 2007, 22:51
I'm sorry but I can't confirm that. I think it should be possible to achieve :) Try setting the Qt::WA_NoSystemBackground attribute for your frameless window.

durbrak
13th May 2007, 23:09
Yeah, I already tried that and stuff like Qt::WA_OpaquePaintEvent and Qt::WA_PaintOnScreen and yes, it gives a transparent window background, but as soon as I try to paint on it or just put a QLabel in it, the background is black with my QLabel ontop :(

Maybe this is supposed to work on Windows but no one at TT noticed yet that it doesn't work very well on Windows Vista? :)

I actually also thought that this would be a simple thing to achieve and I was pretty surprised that it wasn't that easy after all.

I also looked into that:
http://labs.trolltech.com/page/Graphics/Examples/Examples1 (first example - "ARGB")
And according to its source code even TT needed to use X11 calls (which I obviously don't have on Windows :P) to display that bird.
I downloaded it and removed the X11 calls from the int main() function - the bird has a gray and black background in its window (gray with no attributes and black with the aforementioned attributes).

wysota
13th May 2007, 23:55
Native X11 calls are needed on X11, because by default the visuals returned by X11 don't have the alpha component and you have to ask for it specifically. This shouldn't be the issue on Windows.

Of course you can always "emulate" the correct behaviour with setMask(), moveEvent(), QImage, QDesktopWidget and QWidget::grabWindow(). But I still think it should be possible to do it on Windows without special tricks provided that your screen is 32bits deep and supports compositions.

marcel
14th May 2007, 05:45
Yes you can.
First fill your widget with a transparent pixmap ( filled with Qt::transparent ), and then draw your argb png.

Tested (:))

Regards

pakulo
14th May 2007, 11:46
Can you show example?
I can't understand how i can fill the widget with Qt::transperent.

marcel
14th May 2007, 11:59
In the widget's paint event.
Something like this:



void MyWidget::paintEvent( QPaintEvent* )
{
QPainter painter( this );
QPixmap pix( size() );
pix.fill( Qt::transparent );
painter.drawPixmap( 0, 0, pix );
//Now the widget is completely transparent
//You can draw now your png
}
Also, once you make sure the code works, you might want to optimize it a bit by creating the transparent pixmap only once.

regards

durbrak
14th May 2007, 12:54
Did you really try that? Because I already did try it and just tried it again but it won't work.

With no special attributes I still have the usual gray Windows background and with the Qt::WA_OpaquePaintEvent / Qt::WA_NoSystemBackground attribute I get a black background as soon as I start painting anything on the widget.

I'm starting to think that this is a regression from Qt on Windows Vista.
Marcel, did you try it on Windows Vista or XP and what additional attributes did you use?

wysota
14th May 2007, 13:10
Maybe your desktop doesn't support compositions?

marcel
14th May 2007, 13:15
No, only on XP.

pakulo
14th May 2007, 13:27
Me too, black background.

durbrak
14th May 2007, 13:51
Pakulo, do you also use Vista?

Wysota, I don't know but I think my system is pretty much up to date :)

So it seems that this is a regression of Qt on Vista. You guys think I should submit this to TT's bug tracker as a suggestion/bug?

pakulo
14th May 2007, 14:16
I am use Window XP

durbrak
14th May 2007, 14:18
Are you sure you did the right thing, pakulo? Because Marcel says it works for him on Windows XP.
Please show us some code (paintEvent and maybe hwo your constructor looks like with the appropriate attribute calls).

wysota
14th May 2007, 14:30
Wysota, I don't know but I think my system is pretty much up to date :)
That doesn't mean anything. The particular feature may be disabled on unsupported on your version/installation of the system.


So it seems that this is a regression of Qt on Vista. You guys think I should submit this to TT's bug tracker as a suggestion/bug?

You can, but I'd first verify this is not caused by your installation. I don't think there should be any regression in this matter.

durbrak
14th May 2007, 15:05
Yeah well, I didn't turn any features in my OS off or something like that (at least not that I'm aware of). Besides, I have dozens of applications who can do this on my rig (Windows Sidebar, Trillian Astra, CD Art Display, ...) :(

It just seems weird that on Pakulo's WinXP it doesn't seem to work either even though it does work for Marcel...

wysota
15th May 2007, 10:28
It just seems weird that on Pakulo's WinXP it doesn't seem to work either even though it does work for Marcel...

Which also suggests it's a configuration issue. Maybe his video card supports 32b visuals and yours doesn't. I guess that the same effect may be obtained in different ways, so I'm not convinced by an argument that other applications are able to achieve an effect that looks the same. Have you seen their sources? :)

durbrak
15th May 2007, 14:23
Well, still the other applications achieve somehow this affect...

Anyway, the funny thing is: I was just about to go to the TT Task Tracker to submit this as a suggestion and guess what? I looked through the newest submissions and someone already suggested this 2.5 hours ago :eek:

http://www.trolltech.com/developer/task-tracker/index_html?method=entry&id=162697

I wonder who that was :rolleyes:

kernel_panic
13th August 2007, 12:35
search google for "UpdateLayeredWindow". Then you'll find many solutions. just port it to qt and everything is ok.

giotto
20th December 2007, 01:43
Is there any solution for mac?

mchara
20th December 2007, 07:56
HI,
note QPixmap::grabWindow
and ScreenShot Example,
u may cheat to have the same effect by grabbing desktop under your window and paint your png on background, that is copy of desktop.
Many applications do so(especially older) -it can be seen when moving a window or changing something in background because some of applications grabs desktop only once.

i also read posts on this forum, that shows setMask works also for mainWindow's (mainly related to rounded corners of communicators).
almost forgot, did you checked autoFillBackground property of your window?

there's also Shaped Clock example in qt manual that does exactly what you need...

marcel
20th December 2007, 08:04
I must say, that approach is the worst there can be... From the performance point of view and architecture,in general.

The best solution that was implemented so far is kernel_panic's QSkinWindows classes. You can find them in the Qt Software section.

wysota
20th December 2007, 10:41
The best would be to use ARGB windows, but I don't know if Mac supports such things. It'd probably require diving into cocoa or carbon.

THRESHE
14th March 2008, 19:02
I've read the thread but I didn't understand is it possible to draw semi transparent shadow on a desktop with Qt ?

The Storm
15th March 2008, 14:57
Before 2-3 years when I was tring differend cross-platform GUI libraries I saw a module to wxWidgets library that make this thing damn easy. You just choose an png image and set it to specific class offered by that module and you get just the image without anything else, the cool here is that if the image have transparent part inside him you will see the desktop behind and if you righ click on this transparent space inside the image you will get the windows desktop menu(refresh, properties, etc) so basicly on that part there in no anything at all, the guy that created that module showed some pictures - on Windows XP, Linux/X11 and Mac OS X, it was working in the very same way. So I think that this is possible to be done and in Qt. :) Here is the webpage with screen shots - http://www.upcase.de/wxSkin.html
Look at the the 4 screenshot, on the head of the buddy there is empty space inside the image and there you can get the OS right click menu. And don't think that thats are just screenshot to WMP, the guy just is using their images, I can confirm it because the examples from witch are taken the screenshots comes with the module, so you can compile and see them for yourself. :)

wysota
15th March 2008, 15:27
To me it seems it is using masking. See QWidget::setMask(). How did you say that? "Damn easy"... so damn easy it is and without any extensions.

The Storm
15th March 2008, 15:48
I know that without this module it will be hard but it seems that if the TT guys want, they can make it too. :)

wysota
15th March 2008, 16:15
but it seems that if the TT guys want, they can make it too. :)

What do you mean?

The Storm
15th March 2008, 17:39
I meant that maybe TT(TrollTech) can make something like function in to the QWidget maybe to set image to be the only showed thing, and the other parts to be transparent so the effect will be more easy reached, without playing with setMask(). :)

jpn
15th March 2008, 17:53
Does it really need to be easier than


label->setPixmap(pixmap);
label->setMask(pixmap.mask());

? :)

The Storm
15th March 2008, 18:07
Then what is the problem of the whole topic huh? Maybe I missed something again... :}

jpn
15th March 2008, 18:39
Well, there's a significant difference between masks and ARGB windows. Masking makes completely transparent parts being treated as "holes" whereas ARGB windows can have semi-transparent areas where the desktop shines through. The wxSkin stuff seems to use this masking technique.

The Storm
15th March 2008, 22:55
Thanks now I understand the problem of the topic. :)