在Qt中创建一个没有阴影的弹出窗口

在Qt中创建一个没有阴影的弹出窗口,qt,popup,popupwindow,Qt,Popup,Popupwindow,我正在使用Qt4.5开发一个应用程序(在WindowsVista下,但希望它是跨平台的)。我用的是C++ 我想创建一个包含QLineEdit小部件的弹出窗口,当用户与QLineEdit小部件交互时,弹出窗口不会被激活(主应用程序窗口保持活动状态) 创建一个带有Qt::Popup | Qt::window标志的窗口(widget)可以提供我想要的东西,但我不想要它提供的3D阴影边框效果。我想要一扇没有边界的窗户。请注意,Qt::FramelessWindowHint标志没有实现这一点 有人找到线索

我正在使用Qt4.5开发一个应用程序(在WindowsVista下,但希望它是跨平台的)。我用的是C++

我想创建一个包含QLineEdit小部件的弹出窗口,当用户与QLineEdit小部件交互时,弹出窗口不会被激活(主应用程序窗口保持活动状态)

创建一个带有Qt::Popup | Qt::window标志的窗口(widget)可以提供我想要的东西,但我不想要它提供的3D阴影边框效果。我想要一扇没有边界的窗户。请注意,Qt::FramelessWindowHint标志没有实现这一点

有人找到线索了吗

进一步澄清:下面是一个简单测试应用程序的剪贴画,它创建了一个带有按钮的窗口。按下按钮时,将显示一个弹出窗口,用户可以在QLine编辑框中键入内容。当用户执行此操作时,主窗口将保持激活状态:

但是,请注意弹出窗口上的阴影边框(我一直无法摆脱)

相比之下,在注释行中创建窗口允许在没有阴影的情况下创建弹出式窗口,但是当用户单击弹出窗口中的QLineEdit时,主窗口不再处于活动状态。因为主窗口上的阴影已经改变,所以您可以分辨出来

我真的想要一个弹出窗口,它的行为就像它是主窗口的一部分。作为一个旁注,弹出窗口消失时,点击它的外面,但这几乎是我想要的行为,我可以用这个和抓取鼠标等来做我想要的。。。只要我能摆脱阴影

PopupTest::PopupTest(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags)
{
    QPushButton* pb = new QPushButton("test button");
    setCentralWidget(pb);
    QObject::connect(pb, SIGNAL(clicked()), this, SLOT(handleClick()));
}

void PopupTest::handleClick()
{
    //QFrame* popup1 = new QFrame(this, Qt::Tool | Qt::Window | Qt::FramelessWindowHint);
    QFrame* popup1 = new QFrame(this, Qt::Popup | Qt::Window );
    popup1->resize(150,100);
    QLineEdit *tmpE = new QLineEdit( popup1 );
    connect( tmpE, SIGNAL( returnPressed() ), popup1, SLOT( hide() ) );
    tmpE->setGeometry(10,10, 130, 30);
    tmpE->setFocus();
    popup1->show();
}

PopupTest::~PopupTest()
{

}

我认为您看到的阴影与您正在使用的Windows主题有关。我在这里使用的是Windows经典主题,没有看到任何阴影:)

无论如何,如果将QLineEdit的textChanged()信号连接到一个自定义操作中,以恢复主窗口的焦点,该怎么办? 比如:

void PopupTest::handleClick()
{
   QFrame* popup1 = new QFrame(this, Qt::Tool | Qt::Window | Qt::FramelessWindowHint);
   popup1->resize(150,100);
   QLineEdit *tmpE = new QLineEdit( popup1 );
   connect( tmpE, SIGNAL( returnPressed() ), popup1, SLOT( hide() ) );
   connect( tmpE, SIGNAL( textChanged(const QString&)), this, SLOT( setActive() ) );
   tmpE->setGeometry(10,10, 130, 30);
   tmpE->setFocus();
   popup1->show();
}

void MainWindow::setActive()
{
   this->activateWindow();
}
tmpE->setFocus();
您必须创建一个名为setActive()的插槽,并且还应将QLineEdit放入类头中,以便通过setActive()函数执行以下操作:

void PopupTest::handleClick()
{
   QFrame* popup1 = new QFrame(this, Qt::Tool | Qt::Window | Qt::FramelessWindowHint);
   popup1->resize(150,100);
   QLineEdit *tmpE = new QLineEdit( popup1 );
   connect( tmpE, SIGNAL( returnPressed() ), popup1, SLOT( hide() ) );
   connect( tmpE, SIGNAL( textChanged(const QString&)), this, SLOT( setActive() ) );
   tmpE->setGeometry(10,10, 130, 30);
   tmpE->setFocus();
   popup1->show();
}

void MainWindow::setActive()
{
   this->activateWindow();
}
tmpE->setFocus();

恢复对QLineEdit的关注。

我为之前发布的问题找到了解决方案

首先,可以通过使用标志
Qt::Window | Qt::FramelessWindowHint
QWidget
派生来创建弹出窗口小部件。实际上,我入侵了
qwidget_win.cpp
,以确保我的窗口具有与WPF提供的弹出控件相同的样式和扩展样式(分别为0x96000000和0x0800088),这是使用Spy++确定的,但我认为这不重要

设置窗口样式并不能解决窗口激活问题。执行此操作的关键是拦截通知主窗口其非客户端区域应更新的windows消息(
WM\u NCACTIVATE
message)。这可以通过提供
QApplication::winEventFilter(MSG*MSG,long*result)
的自定义实现来实现

不幸的是,仅仅吃灭活
WM_u-ACTIVATE
消息是不够的,因为它似乎会阻止
WM_u-ACTIVATE
和其他生成的消息被发送到弹出窗口。为了解决这个问题,我做了一个概念验证,在捕获了一条适当的
WM\u NCACTIVATE
消息后,在
winEventFilter
中生成所需的windows消息

从这里开始,有一些细节需要处理,以确保它的健壮性(截取
WM_ACTIVATEAPP
浮现在脑海中),然后将它包装成一个好的、可重用的东西

所有这些都是特定于windows的。当然,看看Linux下是否存在问题会很有趣


这一切都有点痛苦。希望我没有错过一些明显的东西…

试试下面这个奇怪的代码(在Qt v5上测试。*):

仅适用于此序列方法调用。如果做些改变,我们会用阴影弹出。(魔法:))

编辑 我在enum
Qt::WindowFlags
(Qt v5.3)中找到此标志。 它出现在Qt v5的一个版本中。*。 使用上面的这个标志,代码必须看起来像这样

//BasePopup.cpp
#include "BasePopup.h"

BasePopup::BasePopup(QWidget *parent)
    : QFrame(parent, Qt::Popup | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint)
{
    //---------------------- 
    //yours code here 
    //----------------------
}

我还没有测试过,但我认为它一定能工作。

一个屏幕截图会对你有帮助。一个顶级的小部件阴影是Windows根据主题绘制的。这里没有Qt特定的内容。问题是文本框会失去焦点,因此用户无法在不重新激活弹出窗口的情况下输入更多文本。。我认为你说的阴影是windows主题的一部分是对的。