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

7 qt popup popupwindow

我正在使用Qt 4.5开发一个应用程序(在Windows Vista下,但希望它是跨平台的).我正在使用C++

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

使用Qt :: Popup创建一个窗口(小部件)Qt :: Window标志给了我我想要的东西,除了我不想要它提供的3D阴影边框效果.我想要一个无边框的窗户.请注意,Qt :: FramelessWindowHint标志不能实现此目的.

有人有任何线索吗?

进一步说明:下面是一个简单的测试应用程序的snippit,它创建一个带有按钮的窗口.按下按钮时,会显示一个弹出窗口,用户可以键入QLineEdit框.当用户执行此操作时,主窗口保持激活状态:

http://howlettresearch.com/popup_img_1.png

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

相比之下,在注释掉的行中创建窗口允许创建一个没有阴影的弹出式窗口,但是当用户在弹出窗口中单击QLineEdit时,主窗口不再处于活动状态.您可以判断,因为主窗口上的阴影已更改.

http://howlettresearch.com/popup_img_2.png

我真的在一个弹出窗口之后,它的行为就好像它是主窗口的一部分.作为旁注,弹出窗口在外面点击时消失了,但这几乎是我想要的行为,我可以使用它和grabMouse等来做我想要的......只要我能摆脱那个阴影!

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()
{

}
Run Code Online (Sandbox Code Playgroud)

Mat*_*ett 6

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

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

设置窗口样式不能解决窗口激活问题.这样做的关键是拦截通知主窗口它的非客户区域的Windows消息应该被更新(WM_NCACTIVATE消息).这可以通过提供自定义实现来完成QApplication::winEventFilter(MSG* msg, long* result).

不幸的是,仅仅吃掉停用WM_ NCACTIVATE消息是不够的,因为它似乎会阻止WM_ACTIVATE和其他消息一起发送到弹出窗口.为了解决这个问题,我有一个概念验证工作,我在winEventFilter捕获了适当的WM_NCACTIVATE消息后生成了所需的Windows 消息.

从这里开始,有一些细节可以确保它是健壮的(拦截WM_ACTIVATEAPP在脑海中浮现),然后将其包装成一些漂亮且可重复使用的东西.

当然,所有这些都是特定于Windows的,有趣的是看看Linux下是否存在问题.

这一切都有点痛苦.希望我没有错过任何明显的东西......


nmu*_*ntz 2

我认为您看到的阴影与您正在使用的 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();
}
Run Code Online (Sandbox Code Playgroud)

您必须创建一个名为 setActive() 的插槽,并且还应该将 QLineEdit 放入类标头中,以便从 setActive() 函数中您可以执行以下操作:

tmpE->setFocus();
Run Code Online (Sandbox Code Playgroud)

也将焦点恢复到 QLineEdit 上。