使用 Qt creator 编写屏幕保护程序 - 在屏幕保护程序设置中显示预览
Posted
技术标签:
【中文标题】使用 Qt creator 编写屏幕保护程序 - 在屏幕保护程序设置中显示预览【英文标题】:Writing a screensaver with Qt creator - showing a preview in Screen Saver Settings 【发布时间】:2015-08-29 07:36:20 【问题描述】:一开始我想为我的英语道歉。现在让我们来解决我的问题。
我尝试使用 Qt Creator (v5.0.1) 编写屏幕保护程序。现在我有一个配置窗口(使用“/c”参数运行应用程序),全屏窗口(使用“/s”参数运行应用程序),我没有预览窗口(使用“/p”和“运行应用程序” 1234567" 参数,其中 1234567 是一个句柄,它可以是任何数字。我在正确使用这个句柄时遇到了问题。我发现的例子很少,但都不起作用。下面是一个例子: Creating a Screen Saver for Windows。我试图复制这段代码并让它在我的机器上运行,但出现了一些问题。其中一些我解决了,但一个我不能。以下是部分代码:
QApplication app(argc, argv);
QStringList arguments = app.arguments();
/* parse the commandline:
* "[-/][Cc]" or no arguments for configuration mode
* "[-/][Ss]", for fullscreen mode
* "[-/][Pp][ :][0-9]+" for preview mode
*/
Mode mode = ConfigurationMode;
WId parent = 0;
bool OK = arguments.size()<=1;
for(int i=1;i<arguments.size();i++)
if(arguments[i].size()<2)
break;
switch(arguments[i][1].toLatin1())
case 'c': case 'C':
mode = ConfigurationMode;
OK = true;
break;
case 's': case 'S':
mode = FullScreenMode;
OK = true;
break;
case 'p': case 'P':
if(arguments[i].size()>=4 && arguments[i][2]==':')
parent = (WId)arguments[i].mid(3).toUInt(&OK);
else if(arguments.size()>i)
parent = (WId)arguments[i+1].toUInt(&OK);
mode = PreviewMode;
break;
接下来是代码的第二部分:
ScreenSaverWidget* widget = new ScreenSaverWidget;
widget->setAttribute(Qt::WA_DeleteOnClose);
QObject::connect(widget, SIGNAL(destroyed()), &app, SLOT(quit()));
switch(mode)
case ConfigurationMode:
QSettings settings("QT", "Screen Saver");
int animationSpeed = settings.value("animationSpeed", 10).toInt();
//animationSpeed = QInputDialog::getInteger(0, "Configure Screen Saver", "Set Animation speed (0-100%)", animationSpeed, 0, 100);
animationSpeed = QInputDialog::getInt(0, "configure Screen Saver", "Set Animation speed (0-100%)",animationSpeed, 0, 100);
settings.setValue("animationSpeed", animationSpeed);
return 0;
case FullScreenMode:
new ScreenSaverEventFilter(widget);
widget->showFullScreen();
break;
case PreviewMode:
widget->setWindowFlags(Qt::FramelessWindowHint|Qt::SubWindow);
::SetParent(widget->winId(), parent);// <---
RECT parentRect;
::GetClientRect(parent, &parentRect);// <---
widget->move(0,0);
widget->resize(parentRect.right, parentRect.bottom);
widget->show();
return app.exec();
我有三个错误:
从“WId aka unsigned int”到“HWND”的无效转换 [-fpermissive]
在代码的第二部分中标记的两行。 有谁知道如何使它工作?有没有可能用Qt做到这一点? (句柄是由 window.h 中的窗口生成的,我想将其设置为 Qt 小部件的父级,可以吗?)
还有一个想法是让我的屏幕保护程序(在预览模式下)对输入事件做出反应,例如关闭事件(来自屏幕保护程序设置窗口),该怎么做?
编辑 2015.06.14 -------------
好的,我解决了第一个问题,我添加了显式转换:
(...)
::SetParent((HWND)widget->winId(), (HWND)parent);// <---
RECT parentRect;
::GetClientRect((HWND)parent, &parentRect);// <---
(...)
但现在的问题是我的应用程序没有响应来自屏幕保护程序设置窗口的任何信号,例如(这是最重要的)它没有在应该关闭的时候关闭 - 当我选择另一个屏幕保护程序时,或者当我关闭屏幕保护程序设置窗口时(我必须使用任务管理器终止该进程)。有没有人知道并且可以在这里写下如何让我的应用程序从屏幕保护程序设置窗口接收关闭信号?
【问题讨论】:
【参考方案1】:将一个小部件设置为另一个小部件的父级的合法调用:
void QWidget::setParent(QWidget * parent)
当然,这是确保此类嵌套小部件等的正确信号/插槽处理所必需的。我自己宁愿根本不使用 setParent,而是创建带有嵌套子小部件的 QMainWindow 父小部件,该小部件使用 setCentralWidget 调用获取整个父级然后你就不需要对大小等做很多不必要的事情了。但我不知道你程序中的所有细节。
将小部件的父级设置为父级,并重置窗口标志。小部件移动到其新父级中的位置 (0, 0)。 ... 注意:作为更改其父级的一部分,小部件变得不可见,即使它以前是可见的。您必须调用 show() 使小部件再次可见。
关于调整大小和窗口标志。尝试,如果需要调整大小,您可能可以执行小部件->调整大小(父级->大小())。至于标志,首先尝试不指定它们。这种组合是否适用于 parent 中的子小部件存在一些疑问。
在我们的 Windows 应用程序端口中,我经常将 winId() 传递给 HWND,它可以工作,但请注意,这可能会避免 必要的 Qt 框架操作,并始终尝试首先找到正确的 Qt 方式。至于编译器警告,如果是这样,您可以使用 reinterpret_cast(widget->winId())。
【讨论】:
你知道如何使用函数:void QWidget::setParent(QWidget * parent)
和 WId 参数类型吗?我试过了:WId parent = (WId)window_handle.toUInt(); widget.setParent((QWidget *)parent);
并编译了,但是没有用。
widget->setParent(parent) 应该是你想要的。不要忘记在之后调用 widget->show() 和/或 parent->show()。以上是关于使用 Qt creator 编写屏幕保护程序 - 在屏幕保护程序设置中显示预览的主要内容,如果未能解决你的问题,请参考以下文章
用Qt Creator 编写GUI程序, 源代码用UTF-8编码, 如何用qDebug()输出中文?
安装程序在 ubuntu 上安装 qt 和 qt creator 时崩溃