I'm writing a desktop application on Windows 10 that does something similar to "share your screen/app window", and I've got the classic problem of trying to highlight the region of interest on the screen. So I need to draw a bright and thick rectangle, have the rectangle always be visible and 'on top', and have no interference with user input, mouse movement, etc. (i.e. all pass-through).
I can't make it work properly with Qt v5.7. I either get an opaque window (I can't see what's "below" it) with the right border, or a transparent window with only a black 1-pixel border.
I vaguely know that if I were to use Windows-specific APIs, I could create a window with WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVE
style etc.
(using something like a "chrome window" - example in C# here), but besides the fact that I haven't tried yet (and need to do in C++ and not C#), I'd rather do it with Qt is possible.
Case A I'm still a novice with Qt, but I thought that using a QFrame
was the way to go, so I wrote some code:
//
// A- Displays a completely transparent rectangle with a black 1-pixel border.
//
QFrame *frame = new QFrame();
frame->setFrameStyle(QFrame::Box | QFrame::Plain);
frame->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus | Qt::WindowStaysOnTopHint);
frame->setAttribute(Qt::WA_TranslucentBackground, true);
frame->setGeometry(1000,500,600,300); // Just some fixed values to test
frame->show();
That gives me this, a rectangle with a black 1-pixel thick border:
It's great, in that the rectangle stays on top of everything else, is transparent, pass-through for mouse input etc., cannot get focus, be resized or moved, and doesn't show up on the task bar.
Case B I thought the only problem left was to draw a thick bright border, so I coded this just before the call to frame->show()
:
// Set a solid green thick border.
frame->setObjectName("testframe");
frame->setStyleSheet("#testframe {border: 5px solid green;}");
.. but that gave me exactly, er, nothing. The QFrame
was not showing at all!
Case C So as a test, I removed the setting of Qt::WA_TranslucentBackground
. Here's the code:
//
// C- Displays an opaque pass-through window with a green 5-pixel border.
//
QFrame *frame = new QFrame();
frame->setFrameStyle(QFrame::Box | QFrame::Plain);
frame->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus | Qt::WindowStaysOnTopHint);
// Disabled Qt::WA_TranslucentBackground
//frame->setAttribute(Qt::WA_TranslucentBackground, true);
frame->setGeometry(1000,500,600,300); // Just some fixed values to test
// Set a solid green thick border.
frame->setObjectName("testframe");
frame->setStyleSheet("#testframe {border: 5px solid green;}");
frame->show();
That window is still completely pass-through, stay-on-top, etc. and has the right border, but of course it's opaque.
Now, the fact that:
- with
Qt::WA_TranslucentBackground
set and without changing the style sheet, I get a black 1-pixel border/frame; - with
Qt::WA_TranslucentBackground
set and with changing the style sheet, I don't get a border/frame at all (the window becomes invisible); - without
Qt::WA_TranslucentBackground
set and with changing the style sheet, I get the expected border/frame;
.. seems to imply that there's some style set for getting the black 1-pixel outside border when the window is transparent. When I changed the border style myself, this stays fully inside the window frame, and thus disappears when the window is transparent (case B) - I think.
Does anybody know what the right style sheet settings should be so that I get the window fully transparent with its 5-pixel green border?
Also, I couldn't find any documentation that tells me exactly what styles could apply to what type of widget/window (and QFrame
in particular, for my test case). Does that exist anywhere? It would be handy to know, as I'd also like to use gradient colours for the border, and possibly other effects.