Change Desktop Wallpaper



  • Hi,

    i'm looking for a way to change the Background of the desktop via prgm.
    I read something about
    SystemParametersInfo but this doesn't work for me beacuse there is a problem with the path. And if i take an example code where you drag the img on the exe it works, but the screen becomes only black.

    Also i read something about IActiveDesktop, but i all the headers needed don't work for me.

    So what is the easier way? ActiveDesktop or SystemParametersInfo?? And how can i do it??

    The idea is simple i have a image called myWallaper, or what ever, and put it in the same directory with the exe. and than the .exe will be startet and i get the new Wallpaper.

    Thank you for your help



  • Ok i got a prgm working for setting wallpaper

    @#include <iostream>
    #include <windows.h>
    #include <QString>

    using namespace std;

    int main()
    {
    QString filepath = "C:\Path\to\Image\Image.jpg";
    char path[150];
    strcpy(path, filepath.toStdString().c_str());
    char *pathp;
    pathp = path;

    cout << path;

    int result;
    result = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, pathp, SPIF_UPDATEINIFILE);

    if (result)
    {
    cout << "Wallpaper set";
    }
    else
    {
    cout << "Wallpaper not set";
    cout << "SPI returned" << result;
    }

    return 0;
    }@

    I also read that there's a problem with jpg and that only bmp works, but also if i take a bmp it doesn't work. maybe someone has an idea.

    a yes the problem is that the screen just becomes black



  • You need to use Windows API interfaces (IDesktopWallpaper to be precise) to do this in newer versions of Windows such as 8 and 10.
    Checkout this post for more info.



  • I tried the code, but i get some errors. I hope you understand them. I fixed some of them by using NULL instead of nullptr.

    #include "shobjidl.h"
    #include <QDebug>
    
    int main(int argc, char *argv[])
    {
    
    	HRESULT hr = CoInitialize(NULL);
    	IDesktopWallpaper *pDesktopWallpaper = NULL;
    	hr = CoCreateInstance(__uuidof(DesktopWallpaper), NULL, CLSCTX_ALL, IID_PPV_ARGS(&pDesktopWallpaper));
    	if (FAILED(hr))
    	{
    		qDebug() << "error";
    	}
    	else
    	{
    		pDesktopWallpaper->SetWallpaper(NULL, QString("C:\\Users\\Amin\\Desktop\\test.jpg").toStdWString().c_str());
    	}
    
    	return 0;
    }
    
    QT += core
    QT -= gui
    
    TARGET = WallpaperChanger
    #CONFIG += console
    CONFIG -= app_bundle
    LIBS += -lOle32
    
    TEMPLATE = app
    
    SOURCES += main.cpp
    
    
    
    • D:\workspaces\Qt_default\WallpaperChanger\main.cpp:17: Fehler: invalid use of incomplete type 'IDesktopWallpaper {aka struct IDesktopWallpaper}'
      pDesktopWallpaper->SetWallpaper(NULL, QString("C:\Users\Amin\Desktop\test.jpg").toStdWString().c_str());
      ^

    • C:\Qt\Qt5.5.1\Tools\mingw492_32\i686-w64-mingw32\include\shobjidl.h:987: Fehler: forward declaration of 'IDesktopWallpaper {aka struct IDesktopWallpaper}'
      typedef interface IDesktopWallpaper IDesktopWallpaper;
      ^

    • C:\Qt\Qt5.5.1\Tools\mingw492_32\i686-w64-mingw32\include\combaseapi.h:79: Fehler: invalid static_cast from type 'IDesktopWallpaper*' to type 'IUnknown*'
      static_cast<IUnknown *> (*pp);
      ^



  • First of all, please try the same thing with a Widgets application. And create it by selecting new project, the Widgets Application. Do NOT use console project to try it! (Your project does not seem to be even Console anyway!)
    Next, you seem to be using MingW compiler, not sure but you may be facing the problem because of that. The interface mentioned here belongs to recent SDKs of Windows and therefore it might not work correctly (link correctly) with a MingW compiler.
    I would suggest using a recent MSVC compiler.



  • OK, i changed it to widgets application. And yes i'm using MinGW.
    I tried to config MSVC for my Qt Creator, but i wasn't successfull:

    • :-1: Warnung: LNK4044: Nicht erkannte Option /lshell32; wird ignoriert.

    • :-1: Warnung: LNK4044: Nicht erkannte Option /LC:\Qt\Qt5.5.1\5.5\mingw492_32\lib; wird ignoriert.

    • :-1: Warnung: LNK4044: Nicht erkannte Option /lQt5Cored; wird ignoriert.

    • :-1: Fehler: LNK1104: Datei "C:\Qt\Qt5.5.1\5.5\mingw492_32\lib\qtmaind.lib" kann nicht geöffnet werden.

    I'm sure i need the libs for msvc, but i couldn't find them. Are there the libs pre compiled? Or do i need to take the qt-everywhere-opensource-src-5.5.1.zip and build the source with my compiler on my own??
    (I have Visual Studio Enterprise 2015 installed)



  • Unfortunately pre-compiled Libs for Qt are not provided with the official release (not yet!) but you can try building from source yourself.
    I would suggest installing a lower version of MSVC compiler such as MSVC2013 (Community Edition is free btw) and using pre-compiled libraries if you are not comfortable with building sources yourself, or if you would prefer official builds.



  • Ok i'll try to build the source. I did it a while ago with MinGW for static linking. So i hope it will be similar to this.
    What's the difference between qt-everywhere-opensource-src-5.5.1 http://download.qt.io/archive/qt/5.5/5.5.1/single/ and qt5-opensource-src-5.5.1 http://download.qt.io/archive/qt/5.5/5.5.1/submodules/

    Why should i use a lower version of MSVC?? I recently updated from VS 2013 Ultimate to VS 2015. So i'd prefer the newer one. But if this is a problem I can install VS2013 again.



  • @QT-static-prgm
    Single is like an All-In-One package of modules but submodules version offers all modules separately.
    Most probably you need Single version.
    I'll suggest taking a look at this page and also this post

    You need to use the lower version if you want the official build. If not, you can build yourself.
    Good luck



  • Thank you very much. Your tutorial is great. But i have some problems again:

    + cd qtbase
    + C:\Qt\5.5.1\qt-everywhere-opensource-src-5.5.1\qtbase\configure.bat -top-level -static -debug-and-release -prefix "C:\Qt\5.5.1\msvc2015_static" -platform win32-msvc2015 -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -opengl desktop -qt-sql-sqlite -qt-sql-odbc -no-openssl -opensource -confirm-license -make libs -nomake tools -nomake examples -nomake tests
    
    This is the Qt for Windows Open Source Edition.
    
    You have already accepted the terms of the license.
    
    Creating qmake...
    execute: File or path is not found (nmake)
    execute: File or path is not found (nmake)
    Cleaning qmake failed, return code -1
    

    btw what are all these options good for??

    did i take the wrong cmd?? I used "MSBuild Befehlszeile für VS2015". There some more in my Start->All Programms->Visual Studio list:
    Developer-Eingabeaufforderung für VS2015,
    VS2015 x64 ARM Cross Tools-Eingabeaufforderung,
    VS2015 x64 Native Tools-Eingabeaufforderung,
    VS2015 x64 x86 Cross Tools-Eingabeaufforderung,
    VS2015 x86 ARM Cross Tools-Eingabeaufforderung,
    VS2015 x86 Native Tools-Eingabeaufforderung,
    VS2015 x86 x64 Cross Tools-Eingabeaufforderung

    Which one is the right one??



  • You should have "Developer Command Prompt for VS2015"
    You are using German version so "Developer-Eingabeaufforderung für VS2015" is correct!



  • It works :D Thank you very much.
    ähm ok i just wanted to press send and checked my cmd output and it "finished". But it says:

    jom: C:\Qt\5.5.1\qt-everywhere-opensource-src-5.5.1\qtdeclarative\src\qml\Makefile.Debug [.generated\debug\RegExpJitTables.h] Error 1
    jom: C:\Qt\5.5.1\qt-everywhere-opensource-src-5.5.1\qtdeclarative\src\qml\Makefile [debug-all] Error 2
    jom: C:\Qt\5.5.1\qt-everywhere-opensource-src-5.5.1\qtdeclarative\src\Makefile [sub-qml-make_first-ordered] Error 2
    jom: C:\Qt\5.5.1\qt-everywhere-opensource-src-5.5.1\qtdeclarative\Makefile [sub-src-make_first] Error 2
    jom: C:\Qt\5.5.1\qt-everywhere-opensource-src-5.5.1\Makefile [module-qtdeclarative-make_first] Error 2



  • @QT-static-prgm check your build folder. Most probably you already have most of the libraries built. Continue with "jom install" command.
    But you can also check for dependencies and/or remove the module causing the problem, in this case it is qtdeclarative, and then rebuild.



  • -nomake qtdeclarative doesn't work :/

    • cd qtbase
    • C:\Qt\5.5.1\qt-everywhere-opensource-src-5.5.1\qtbase\configure.bat -top-level -static -debug-and-release -prefix "C:\Qt\5.5.1\msvc2015_static" -platform win32-msvc2015 -c++11 -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -opengl desktop -qt-sql-sqlite -qt-sql-odbc -no-openssl -opensource -confirm-license -make libs -nomake tools -nomake examples -nomake tests -nomake qtdeclarative
      Unknown part qtdeclarative passed to -nomake.


  • @QT-static-prgm It won't. You have to carefully read configure options. I suggest taking a look at this old post of mine about configure options. If I am not mistaken, you need to use "skip" instead of "nomake"



  • And again, thank you so much. What is qtdeclarative good for??



  • @QT-static-prgm it is related to QML. I usually can live without it :)



  • Next error:

    Error: dependent 'C:\Qt\5.5.1\qt-everywhere-opensource-src-5.5.1\qtdeclarative\lib\Qt5Qmld.lib' does not exist.
    jom: C:\Qt\5.5.1\qt-everywhere-opensource-src-5.5.1\qtwebchannel\src\webchannel\Makefile [debug-all] Error 2
    jom: C:\Qt\5.5.1\qt-everywhere-opensource-src-5.5.1\qtwebchannel\src\Makefile [sub-webchannel-make_first] Error 2
    jom: C:\Qt\5.5.1\qt-everywhere-opensource-src-5.5.1\qtwebchannel\Makefile [sub-src-make_first] Error 2
    jom: C:\Qt\5.5.1\qt-everywhere-opensource-src-5.5.1\Makefile [module-qtwebchannel-make_first] Error 2

    I think it's a kind of Windows 10 problem: https://forum.qt.io/topic/58056/compilation-failure-with-vs2015/3


  • Qt Champions 2016

    @QT-static-prgm
    HI just a side note:
    I used this on Win 7 to change wallpaper.
    (with mingw compiler)
    Never tested on window 10, so might not work.

    #include "mainwindow.h"
    #include <QApplication>
    #include <qDebug>
    
    #include <Windows.h>
    int setwallpaper (QString filePath ) {
      bool ret = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID)filePath.utf16(), SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
      return ret;
    }
    
    int main(int argc, char* argv[]) {
      QApplication a(argc, argv);
      MainWindow w;
      w.show();
      setwallpaper("c:/test.jpg"); // adjust
      return a.exec();
    }
    
    


  • Your code looks easy. I'll try it. But for now my program shown above is working with the VS compiler.

    Thank you all :D

    Ok next i'll try to manipulate the image to show the date and clock in the lower right corner. (my university killed the windows clock. That's why i need this ;))


  • Qt Champions 2016

    @QT-static-prgm
    hehe so you switch compiler and
    compiled all of Qt so you can change
    the wallpaper each minute and that way
    get a clock ???
    :))
    That is the spirit if I ever saw one :))

    but are you sure they allow to change the wallpaper?



  • @mrjj
    That's the aim :D

    btw your code works fine as well. It is only faster then the other one. This:

    #include "mainwindow.h"
    #include <QApplication>
    #include <QDebug>
    #include "shobjidl.h"
    #include <Windows.h>
    
    
    int setwallpaper (QString filePath ) {
      bool ret = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID)filePath.utf16(), SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
      return ret;
    }
    
    
    int main(int argc, char *argv[])
    {
    	HRESULT hr = CoInitialize(NULL);
    	IDesktopWallpaper *pDesktopWallpaper = NULL;
    	hr = CoCreateInstance(__uuidof(DesktopWallpaper), NULL, CLSCTX_ALL, IID_PPV_ARGS(&pDesktopWallpaper));
    	if (FAILED(hr))
    	{
    		qDebug() << "error";
    	}
    	else
    	{
    		pDesktopWallpaper->SetWallpaper(NULL, QString("D:\\Bilder\\BMW\\3er nachher.jpg").toStdWString().c_str());
    	}
    
    	qDebug() << setwallpaper("D:\\Bilder\\BMW\\f22-wallpaper-1920x1600-16.jpg");
    
    	return 0;
    }
    

    causes in first shown the f22-wallpaper-1920x1600-16.jpg image and then 3er nachher. So maybe your code is better and that way there was no need to compile qt for vs.

    But ok now i understand building qt a bit better XD


  • Qt Champions 2016

    Ok. good to know,

    Next its to create a timer object
    http://www.bogotobogo.com/Qt/Qt5_QTimer.php
    and then ( code not syntax checked)

    // draw time on image
    QPixmap pix("D:\\Bilder\\BMW\\3er nachher.jpg");
    QPainter paint(pix);
    QTime time = QTime::currentTime();
    QString text = time.toString("hh:mm");
    paint.drawText(pix.width()-100,pix.height()-20,text);
    

    and off u go :)



  • @mrjj You saved my time. Thanks for the commands. I hope there are not too much questions tomorrow than i find some time to implement it in the cip-pool :D


  • Qt Champions 2016

    @QT-static-prgm
    Well its a good cause :)
    Repel against the clock-less desktops!!
    I think it would be the easiest to move all code to the timer object.
    and let it draw on image then set it.
    over and over :)



  • I'm glad the problem's solved. What @mrjj just mentioned is definitely much easier. My way was more like an example of using interfaces in Qt. They are of course more complicated but Windows API is changing so I guess you won't lose anything by seeing an interface example!
    Good luck both


  • Qt Champions 2016

    @QT-static-prgm said:
    Yes, the use of interfaces is much more future
    proof and also interesting to see used,
    I also tried in mingw and it seems to think
    IDesktopWallpaper was iUnknow no matter what i did.
    So I guess Visual Studio is indeed better for win development.



  • I tried the code yesterday. Nothing changed. It seams to be a problem of SystemParametersInfo. The function is too powerfull and was blocked. It returns always 0. :( will try the alternative version next


  • Qt Champions 2016

    @QT-static-prgm
    hi have you tried to manually set desktop wallpaper.
    If they removed the watch, they have might have
    taken right to set wallpaper also ?



  • @mrjj I can manual change the wallpaper. That's no problem. They removed the clock because the Microsoft right handle doesn't work for them, so everyone who can see the clock and change it, too. Some students did that and that way the whole account synchronisation was broken. Since that the clock was removed.

    I tried to write the clock on the image at my home computer, but i get some errors for this step, too:
    QPixmap: Must construct a QGuiApplication before a QPixmap


  • Qt Champions 2016

    @QT-static-prgm said:

    Must construct a QGuiApplication

    If you do have
    QApplication app( argc, argv );

    then you must likely have constructed the Pixmap as global before main.

    and hence its created before "app"



  • @mrjj It works now :D (on my home pc)

    #pragma warning(disable: 4100)
    #include <QGuiApplication>
    #include <QString>
    #include <QDebug>
    #include <QPixmap>
    #include <QTime>
    #include <QPainter>
    #include <Windows.h>
    #include "shobjidl.h"
    
    inline int setwallpaper(QString filePath)
    {
    	return SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID)filePath.utf16(), SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
    }
    
    
    void setWallpaperAdvanced(QString filePath)
    {
    	HRESULT hr = CoInitialize(NULL);
    	IDesktopWallpaper *pDesktopWallpaper = NULL;
    	hr = CoCreateInstance(__uuidof(DesktopWallpaper), NULL, CLSCTX_ALL, IID_PPV_ARGS(&pDesktopWallpaper));
    	if (FAILED(hr))
    	{
    		qDebug() << "error";
    	}
    	else
    	{
    		pDesktopWallpaper->SetWallpaper(NULL, filePath.toStdWString().c_str());
    	}
    }
    
    void drawTime(QPixmap &image, int posX, int posY, QColor color)
    {
    	QPainter painter(&image);
    	painter.setPen(color);
    	QFont font;
    	font.setBold(true);
    	painter.setFont(font);
    	QTime time = QTime::currentTime();
    	QDate date = QDate::currentDate();
    	QString timeText = time.toString("hh:mm");
    	QString dateText = date.toString(Qt::DefaultLocaleShortDate);
    
    	painter.drawText(posX+15,posY,timeText);
    	painter.drawText(posX,posY+15,dateText);
    }
    
    
    int main(int argc, char **argv)
    {
    
    	QGuiApplication a(argc, argv);
    	QString originalFilePath("D:\\workspaces\\Qt_default\\WallpaperApp\\wallpaper.jpg");
    	QString manipulatedFilePath("D:\\workspaces\\Qt_default\\WallpaperApp\\wallpaper_temp.jpg");
    
    	QTime time;
    
    	while(true)
    	{
    		time = QTime::currentTime();
    
    		if(time.second() == 0)
    		{
    			QPixmap image(originalFilePath);
    			drawTime(image, image.width()-75, image.height()-150, Qt::white);
    			image.save(manipulatedFilePath);
    			setWallpaperAdvanced(manipulatedFilePath);
    			qDebug() << "changed";
    		}
    		Sleep(800);
    	}
    
    	return 0;
    }
    
    

    I was just wondering if there is a good way to stop the program. Maybe a tray icon that has an close option. Any ideas??



  • @QT-static-prgm I have tried your code but I got error.
    error: C2065: 'IDesktopWallpaper' : undeclared identifier
    error: C2065: 'DesktopWallpaper' : undeclared identifier
    error: C2065: 'pDesktopWallpaper' : undeclared identifier
    error: C2660: 'CoCreateInstance' : function does not take 3 arguments

    beside these I have a question.
    What is the file shobjidl.h that you have included?


  • Qt Champions 2016

    @mKing142 said in Change Desktop Wallpaper:

    shobjidl.h

    This a native win SDK include
    https://msdn.microsoft.com/en-us/library/windows/desktop/dd391719(v=vs.85).aspx
    Its needed to know some of the types.

    Note that with the mingw compiler it would not compile but with visual studio it did.

    Note2:
    You might need
    LIBS += -lOle32
    LIBS += User32.lib
    LIBS += Ole32.lib

    in the .pro file.



  • @mrjj Thanks for your quick reply.
    Now am able to understand about shobjidl.h file.

    I am using MSVC 2013 compiler.

    I have added
    LIBS += Ole32.lib
    in .pro file but still I am getting the error. But if I comment this by pragma i.e. #pragma comment( lib, "Ole32.lib" ) then its compiling. So I just want to know that do I need to add this file somewhere in project settings also.



  • Hi, try:

    LIBS += -lOle32
    

  • Qt Champions 2016

    @mKing142 said in Change Desktop Wallpaper:

    #pragma comment( lib, "Ole32.lib" )

    No that should be enough.
    as far as i know its the same as
    Configuration Properties -> Linker -> Input -> Additional Dependencies.
    (and add the dll/lib there)

    Basically we the linker where all the code that goes with the shobjidl.h are.
    Normally you would have a cpp file ( the h file just declare ) but in this case its
    inside a windows DLL ( ole32 it seems) so if it links, then nothing more is needed.


  • Qt Champions 2016

    Thanks @hskoglund
    I always fiddle around with the syntax. :)



  • @mrjj Yeah me too (have to look at some of my programs every time to remember it :-)



  • @mrjj Thanks for your comment. I have added the Olib32 in Lib section and tried it. Now the code is building.
    But am getting error in CoCreateInstance. The hex code returned by CoCreateInstance is 0x80040154. I have googled this and came to know that the error is "Class not registered". Now am confused.
    Do you have any idea regarding this error?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.