c++ - 在 Windows 10 上的 Qt5 中围绕屏幕区域绘制高亮边框

标签 c++ qt windows-10-desktop

我正在 Windows 10 上编写一个桌面应用程序,它执行类似于“共享您的屏幕/应用程序窗口”的操作,并且我遇到了试图在屏幕上突出显示感兴趣区域的经典问题。因此,我需要绘制一个亮而粗的矩形,使该矩形始终可见并“位于顶部”,并且不干扰用户输入、鼠标移动等(即所有直通)。

我无法让它与 Qt v5.7 一起正常工作。我得到一个带有右边框的不透明窗口(我看不到它“下方”的内容),或者一个只有黑色 1 像素边框的透明窗口。

我隐约知道,如果我要使用特定于 Windows 的 API,我可以使用 WS_EX_LAYERED | 创建一个窗口WS_EX_TRANSPARENT | WS_EX_NOACTIVE 样式等。 (使用类似于“chrome 窗口”的东西 - C# 中的示例 here ),但除了我还没有尝试过的事实(并且需要在 C++ 而不是 C# 中做),我宁愿用 Qt 做它是可能。

案例 A 我还是 Qt 的新手,但我认为使用 QFrame 是可行的方法,所以我写了一些代码:

//
// 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();

这给了我一个带有黑色 1 像素粗边框的矩形:

很棒,因为矩形位于其他所有内容之上,是透明的,可以传递鼠标输入等,无法获得焦点,无法调整大小或移动,也不会显示在任务栏上。

ChromeWindowCaseA

情况 B 我认为剩下的唯一问题是绘制一个粗的明亮边框,所以我在调用 frame->show() 之前编写了这个代码:

// Set a solid green thick border.
frame->setObjectName("testframe");
frame->setStyleSheet("#testframe {border: 5px solid green;}");

.. 但这并没有给我任何帮助。 QFrame 根本没有显示!

案例 C 因此,作为测试,我删除了 Qt::WA_TranslucentBackground 的设置。这是代码:

//
// 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();

ChromeWindowCaseC

那个窗口仍然是完全直通的,保持在顶部等等,并且有正确的边框,但当然它是不透明的。

现在,事实是:

  • 设置了 Qt::WA_TranslucentBackground 并且没有更改样式表,我得到了一个黑色的 1 像素边框/框架;
  • 设置 Qt::WA_TranslucentBackground更改样式表后,我根本没有边框/框架(窗口变得不可见);<
  • 没有 Qt::WA_TranslucentBackground 设置和更改样式表,我得到了预期的边框/框架;

.. 似乎暗示当窗口透明时,有一些样式设置用于获取黑色 1 像素 outside 边框。当我自己更改边框样式时,它完全位于窗口框架内,因此在窗口透明时消失(情况 B)- 我认为。

有谁知道正确的样式表设置应该是什么,这样我才能使窗口完全透明并带有 5 像素的绿色边框?

此外,我找不到任何文档可以准确地告诉我什么样式可以应用于什么类型的小部件/窗口(特别是 QFrame,对于我的测试用例)。那存在于任何地方吗?知道这一点会很方便,因为我还想为边框使用渐变颜色,可能还有其他效果。

最佳答案

尝试将代码中的 QFrame 替换为...

class rubber_band: public QRubberBand {
  using super = QRubberBand;
public:
  template<typename... Types>
  explicit rubber_band (const Types &... args)
    : super(args...)
    {
      setAttribute(Qt::WA_TranslucentBackground, true);
    }
protected:
  virtual void paintEvent (QPaintEvent *event) override
    {
      QPainter painter(this);
      QPen pen(Qt::green);
      pen.setWidth(10);
      painter.setPen(pen);
      painter.drawLine(rect().topLeft(), rect().topRight());
      painter.drawLine(rect().topRight(), rect().bottomRight());
      painter.drawLine(rect().bottomRight(), rect().bottomLeft());
      painter.drawLine(rect().bottomLeft(), rect().topLeft());
    }
};

上述 rubber_band 类的实例应显示为具有完全透明主体的绿色边框。用作...

rubber_band *frame = new rubber_band(QRubberBand::Rectangle);
frame->setGeometry(1000, 500, 600, 300);
frame->show();

(注意:在使用 X11 的平台上,上述内容需要运行诸如 xcompmgr 之类的复合管理器。这通常不是问题。)

关于c++ - 在 Windows 10 上的 Qt5 中围绕屏幕区域绘制高亮边框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43665345/

相关文章:

c++ - 忽略父 Qt Quick Image 透明区域的 MouseArea onClicked 事件

c++ - 黑莓模拟器 : ViewFinder starting failed 级联相机错误

c# - 如何在 windows 10 应用程序中为 windows 和 windows phone 应用程序编写不同的代码

c# - .NET Framework 从 3.5 升级到 4.6 后 C/C++ DLL 失败

c++ - OSG : Get transform matrix from a node

c++ - 为了实现 5 个并发连接的高性能低级 Linux TCP/IP 套接字客户端,我必须采取哪些可能的选择?

c++ - Xonix游戏: detect the proper area

c++ - 从IP地址查找MAC地址

c++ - Qt - 拆分 QString,使用几种类型的空格作为分隔符

windows - 使用 Powershell 创建的本地用户帐户未显示在设置 "Family & Other people"中