Writing a screensaver with Qt creator - showing a preview in Screen Saver Settings

2.5k views Asked by At

At the beginning I want to apologise for my English. Now let's go to my problem.

I try to write a screen saver using Qt Creator (v5.0.1). Now I have a configuration window (running application with "/c" parameter), full screen window (running application with "/s" parameter), and I don't have a preview window (running application with "/p" and "1234567" parameters, where 1234567 is a handle and it can be any number. I have a problem with correct use this handle. There are few examples that I found, but all of them don't work. Here is an example: Creating a Screen Saver for Windows. I was trying to copy this code and make it work on my machine, but there was a few problems. Some of them I solved, but one I can't. Here is a part of the code:

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;
    }
}

And next is the second part of the code:

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

I have three errors:

invalid conversion from 'WId {aka unsigned int}' to 'HWND' [-fpermissive]

in two lines which are marked in second part of the code. Is there anyone who know how to make it work? Is there a possibility to do it with Qt? (handle is generating by window from window.h and I want to set it as a parent of Qt widget, is it possible?)

And one more think to do is to make my screensaver (in preview mode) to react to input events, for example close event (from Screen Saver Settings window), how to do it?

EDIT 2015.06.14 -------------------------

Ok, I solved the first problem, I added explicit conversion:

    (...)
    ::SetParent((HWND)widget->winId(), (HWND)parent);// <---
    RECT parentRect;
    ::GetClientRect((HWND)parent, &parentRect);// <---
    (...)

but now the problem is that my application doesn't respond to any signals from Screen Saver Settings window, for example (and this is the most important) it doesn't close when it should - when I choose another screensaver, or when I close Screen Saver Settings window (I must kill the process with Task Manager). Is there anyone who know and can write here how to make my application picking up the closing signal from Screen Saver Settings window?

1

There are 1 answers

2
Alexander V On

The legal call to set one widget as parent for another:

void QWidget::setParent(QWidget * parent)

Of course that is needed to ensure proper signal/slot processing for such nested widget, etc. I myself would rather not use setParent at all but create the QMainWindow parent widget with nested child widget that takes entire parent using setCentralWidget call and you then don't need to do many unnecessary things with size, etc. But I am unaware of all details in your program.

Sets the parent of the widget to parent, and resets the window flags. The widget is moved to position (0, 0) in its new parent. ... Note: The widget becomes invisible as part of changing its parent, even if it was previously visible. You must call show() to make the widget visible again.

As for resize and window flags. Try and if resize is needed you can probably do widget->resize(parent->size()). As for the flags, first try without specifying them. There is some doubt if this combination applicable to the child widget inside parent.

In our Windows app port I frequently pass winId() for HWND and it works but mind that that may avoid necessary Qt framework actions and always try to find the proper Qt way first. As for compiler warning for that, you can use reinterpret_cast(widget->winId()) if so.