我正在使用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)
我找到了我之前发布的问题的解决方案.
首先,可以通过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下是否存在问题.
这一切都有点痛苦.希望我没有错过任何明显的东西......
我认为您看到的阴影与您正在使用的 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 上。