Hi, I'm trying to use the dwm api on a Qt application but I don't know how to remove the widget background. There's a way by using setPalette(0, 0, 0, 0); but i't will affect child widget.
I's there an other way?
Hi, I'm trying to use the dwm api on a Qt application but I don't know how to remove the widget background. There's a way by using setPalette(0, 0, 0, 0); but i't will affect child widget.
I's there an other way?
Do you want a child widget to be transparent, or what?
Or do you want the main window to be transparent?
What exactly are you trying to achieve?
If you are using DWM composition, then you don't need to do any hacks to make the window transparent. The window manager does it for you.
Also Qt 4.3 transparently supports some DWM features.
I't ok, I found a way to do it.
But now I got two big problem. When I use QPainter to paint a semi-transparent rectangle on the glass. The widget will repaint over the last rectangle normaly (it will erase the widget and then paint the rectangle) but if I click on an other window (like the taskbar) it will repaint over the last rectangle without erase it.
And the text won't render corectly on glass.
PS : sorry for posting in the installation forum, if some one can move it to the programming forum it will be nice, thanks.
Still not clear
Try explaining what is it you are trying to achieve.
Anyway, there is QWidget::setWindowOpacity. But note this also affects the widget's children.
Regards
I'm trying to make the left side of a widget in glass. And for this, I use the DWM api of Windows Vista. But when I use the api, I still have the background color that cover the glass. To remove it, I used setAttribute(Qt::WA_NoSystemBackground);.
All worked fine until I draw a semi-transparent rectangle with a QPainter over the glass. It will render fine but if the widget get or lose the focus, the widget won't repaint itself corectly. Normaly when the widget repaint itselft, it will clear every object already drawn and then will paint the new one. But when the widget get or lose focus, it won't erase the previous draw. This will cause semi-transparent draw to append them self to the previous draw and they will be less and less transparent.
Here is the code to reproduce the bug
#include<QtGui/QApplication>
#include<QtGUI>
class test :public QMainWindow
{
Q_OBJECT
public:
test();
protected:
void paintEvent(QPaintEvent *event);
};
test::test()
{
setAttribute(Qt::WA_NoSystemBackground);
}
void test::paintEvent(QPaintEvent *)
{
QPainter painter(this);
//Here we set the brush to white with alpha
painter.setBrush(QColor(255, 255, 255, 64));
painter.drawRect(0, 0, 200, 200);
}
int main(int argc, char*argv[])
{
QApplication app(argc, argv);
test win1;
win1.show();
return app.exec();
}
I don't test it but it should show you what I mean. You just have to compile the code, start the application and then click on the taskbar or any other window and then click on the application. You will notice that the color should be more opaque than before and if you resize the widget, the color should return to the good one.
And I'm using Qt 4.2.2
Last edited by kawazoe; 19th May 2007 at 20:20.
WA_NoSystemBackground:
This is your explanation.Indicates that the widget has no background, i.e. when the widget receives paint events, the background is not automatically repainted. Note: Unlike WA_OpaquePaintEvent, newly exposed areas are never filled with the background (e.g after showing a window for the first time the user can see "through" it until the application processes the paint events). Setting this flag implicitly disables double buffering for the widget. This is set/cleared by the widget's author.
I believe you have to update the background manually. In every paint event clear the background and draw it again.
Regards.
Last edited by marcel; 19th May 2007 at 20:25.
I can't use painter.eraseRect(0, 0, width(), height()); because it will erase using the current palette so it will paint the the zone with the color that I remove using setAttribute(Qt::WA_NoSystemBackground);.
Is there an onther way to clear it?
what about:
Qt Code:
pix.fill( Qt::transparent ); painter.drawPixmap( 0, 0, pix );To copy to clipboard, switch view to plain text mode
that, or use QPixmap grabWidget after you first update the widget. Then you can paint this pixmap. But this is useful only if you don't want to paint other things too.
Regards
Hey,
I got the same problem (top level window with WA_NoSystemBackground).
I finally managed to get my window painted but there an slight issue.
Everytime the window receives a new paint event, it just paints the new window content on top of the previously painted content without deleting it first.
The eraseRect() is the same as fill(rect(), background()) so there's no use to call it as it will just paint everything black (filling it with a transparent pixmap or a transparent brush also).
Is there any way to delete the previously drawn stuff? The only workaround I can think of right now is to delete and recreate the window everytime a new paint event comes up, but this is sorta stupid![]()
OK.
Then if you want to paint with a certain transparency, why not use setWindowOpacity?
Holy mother of god... I'm sorry to have to say this, but do you actually only post just to enlarge your posts count?
We just spoke 2 days ago and I told you a couple of times that this is not what I and the thread start want. Also I used the search a few times and every time someone asks about this kind of question, it always seems that your answer is "why not use setWindowOpacity()"...
Man, come on... I think you already know that we want to achieve semi transparent painting on a pixel basis and not stupidly for the whole window but still it seems like you're giving your standard-setWindowOpacity-reply![]()
I know that it is because of WA_NoSystemBackground and the background kinda does get updated but Qt won't clear the widget's content before painting on it again.
Furthermore WA_NoSystemBackground proved to be the only solution (combined with a few dwmapi.dll calls) for now to achieve semi transparent painting on a pixel basis.
I updated my last post, go get a look and you will see the good news.
PS : You should be able to pm me now.
And by the way, yes, durbark have the same problem as me.
Last edited by kawazoe; 19th May 2007 at 23:50.
Oh, I already can paint onto the glass frame (but this is a separate matter because I want to paint on the desktop (well, not really on the desktop, but you know what I mean)).
So kawazoe, I know a solution how you can paint on the glass
Qt Code:
typedef struct { int cxLeftWidth; int cxRightWidth; int cyTopHeight; int cyBottomHeight; } MARGINS; typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *margins); static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0; { pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)QLibrary("dwmapi").resolve("DwmExtendFrameIntoClientArea"); MARGINS margins = {-1}; //setting it to -1 makes the glass available throughout the entire window, // like you have in the Windows Sidebar Add Gadgets dialog pDwmExtendFrameIntoClientArea(this->winId(), &margins); this->setAttribute(Qt::WA_NoSystemBackground); }To copy to clipboard, switch view to plain text mode
Now you're good to go and you can put your widgets and everything as usual in the window. It works for me on Windows Vista with Qt4.3RC1![]()
Last edited by jacek; 20th May 2007 at 17:03. Reason: wrapped too long line
Okay, I found the solution. It's weird though, I though I already tried that...
Anyway, resizing the window erases the content:
Somehow I'm thinking that I overkilled it a little bit with isResizing... am I so tired right now and just can't see a simpler solution to do that resizing thingy?Qt Code:
{ static int isResizing = 0; if(isResizing == 0) { size.setHeight(size.height()+1); isResizing = 1; this->resize(size); size.setHeight(size.height()-1); isResizing = 2; this->resize(size); isResizing = 3; return; } else if(isResizing < 3) { return; } else isResizing = 0; //Now you can start painting }To copy to clipboard, switch view to plain text mode
Last edited by durbrak; 20th May 2007 at 00:22.
I don't have the problem when resizing but when changing the focus. Even resizing seem to restore the corect color.
to durbrak:
Qt Code:
{ setWindowFlags( Qt::FramelessWindowHint ); setFixedSize( 400, 400 ); setMask( mask ); } CTestWidget::~CTestWidget() { } { p.drawPixmap( 0, 0, mPixmap ); }To copy to clipboard, switch view to plain text mode
I knew I did it some time ago.
I attached a screen of how it looks.
The png is just a black ellipse on a white background.
The method is limited because it does not work when the image you want to display contains transparent shadings ( such as shadows ).
However, you can give the whole masked widget a shadow if you set the flags Qt::FramessWindowHint | Qt::Popup.
Although, never tested it on Mac.
regards
Last edited by marcel; 20th May 2007 at 01:07.
kawazoe: No, you missed the point. My solution fixes the problem where the background wasn't erased by Qt (it was just painted over). Now with this solution, everytime the window wants to repaint itself, it will resize itself first (thus erasing the garbage painted before), and then paint the stuff.
marcel: Stuff like shadows is exactly what I'm trying to do the whole timeYou scaled your screenshot a little bit too much and I can't see if your circle is anti aliased or not. But I guess not, since this would be equal to shadows
Anyway, I can finally do that now. But here comes the kinda weird part:
I paint text and circles (anti aliased) in my widget and everything looks smooth. But if I paint a pixmap first and then the text and the circles, the circles are still smooth but now the text is crispy as hell
Weird, I can paint every type of form/shape smooth on my png pixmap window, but not text...
Bookmarks