Record learning to use QWidget class to create desktop wallpaper program

Time:2021-9-27

After learning QT for a short time, I want to make a desktop wallpaper program. Because I have not learned WinAPI programming, I only know QT, so I can only find the handle of the desktop and set the background image of the desktop from the Internet first. Hard work pays off. People still find satisfactory WinAPI code. Then I learned the following from these codes. The following is the code I found on the Internet. I made some comments according to these codes and the information I checked on the Internet. After all, the foundation is not strong, I feel there are a lot of mistakes.

#include 

/**Declare a static variable of a handle class*/
static HWND g_workerw = 0;
/**Implement a callback function used by EnumWindows () to get the handle we want to set the program to the desktop location*/
static BOOL CALLBACK EnumWndCallback(HWND tophandle, LPARAM topparamhandle)
{
    //Function: the window we want to use does not have a window name, but we know that the class name of the window we need is: "workerw",
    //We also know that the class name of the child window of the window we need is "shelldll_defview"
    //We also know that the window style of the sub window of the window we need is the visible window style
    //Therefore, we first find that the window style of a window is the visible window style, and then detect whether there is a window with the class name "shelldll_defview" in the sub window of the window,
    //Then check whether the parent window of the window has a window with the class name of "workerw". If they match, this window is the child window of the window we need,
    //The parent window of the window corresponding to the handle stored in the variable tophandle is the window we need

    //Note: the topparamhandle parameter is not used because the EnumWindows function does not
    //Store the variable or variable pointer to get the handle of the window we want, but pass 0. 0 cannot store data
    //Therefore, the window handle obtained through enumwndcallback() function can only be passed through global variables

    //Getwindowlong() function can obtain information about the specified window,
    //Tophandle the handle of the target window, that is, the handle of all top-level windows on the EnumWindows () enumeration screen
    // GWL_ Style is used to get the window style of the window passed in the window handle
    long wflags = GetWindowLong(tophandle, GWL_STYLE);
    //Judge whether the obtained window style is a visible window style
    //The judgment method is to obtain the window style and the visible window style_ Visible and (&) operation
    //If the 29th bit in the binary of the obtained window style is 1,
    //The value after the operation with (&) is the value corresponding to ws_visible, that is, the value that is not 0
    //If the 29th bit in the binary of the obtained window style is 0,
    //The value after the and (&) operation is 0
    // WS_ Visible (hexadecimal is 10000000, binary is 1 0000 0000 0)
    //Then according to! Operator
    if (!(wflags & WS_VISIBLE))
    {
        //Judge whether the obtained window style is not a visible window style
        //If it is not a visible window style, return true and let the enumwindows() function continue to enumerate new windows
        return TRUE;
    };

    //Tophandle is the handle of all top-level windows on the EnumWindows () enumeration screen
    //Use findwindowex() to find the handle of the parent window. It is the handle stored in the variable tophandle. The class of the child window is the handle of the window of "shelldll_defview"
    //The class name of the window we are looking for is "shelldll_defview"
    HWND p = FindWindowEx(tophandle, 0, L"SHELLDLL_DefView", 0);
    //Determines whether a handle was obtained
    if (p != 0)
    {
        // Gets the WorkerW Window after the current one
        //Using findwindowex() to find the handle of the child window is the handle stored in the variable tophandle. The class of the parent window is the handle of the window of "shelldll_defview"
        //The class name of the window we are looking for is "workerw", and the class name is "workerw", which is the window we want to use
        g_workerw = FindWindowEx(0, tophandle, L"WorkerW", 0);
        //Judgment G_ Is the window enumeration value we want stored in workerw
        if (0 != g_workerw)
        {
            //Passed to enumwindows() function false
            //Stop enumwindows() function enumeration
            return FALSE;
        }
    }
    //Passed to enumwindows() function true
    //Let enumwindows() function continue enumeration
    return TRUE;
}

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    /**Use the findwindow() function to obtain a window handle whose class is "progman" and whose title is "program manager"*/
    HWND hwndPrgam = FindWindow(L"Progman", L"Program Manager");
    //Use the sendmessagetimeout() function to send the specified message 0x052c to the window of the enumeration value stored by hwndprgam
    // SMTO_ Normal: when the calling thread waits for the function to return, it is not prevented from processing other requests. 1000 specifies the duration in milliseconds for the timeout period
    SendMessageTimeout(hwndPrgam, 0x052C, 0,0,SMTO_NORMAL, 1000,0);
    //The above two lines of code have been commented according to the query knowledge, but the function is still unclear. Comment out the above two lines of code
    //You can also set the program on the desktop wallpaper

    //Enumwindows() is used to enumerate all top-level windows on the screen, and the enumerated windows are passed into enumwndcallback() function
    //That is, keep passing the window handle to the enumwndcallback() function until you find the handle of the required window
    //Or after enumerating all the windows, we can't find the window we need
    //The second parameter of enumwindows() function is 0, which means that it cannot be obtained through the second parameter of enumwindows() function
    //For the window handle we want, we can only get the window handle we need found in the enumwndcallback() function through the global variable
    EnumWindows(EnumWndCallback, 0);

    //Determines whether a window handle is obtained
    if (g_workerw == 0)
    {
        //If no handle is obtained, the program ends
        abort();
    }
    else
    {
        //If a window handle is obtained

        //Set the program to the wallpaper layer of the desktop
        SetParent((HWND)this->winId(), g_workerw);
    }

I can put the program on the desktop wallpaper by using the code found above and combining my own QT knowledge. However, when the program is closed, the desktop wallpaper is still a picture on the program. I use Spy + + to view the handle of the program

No more. I went to windows10 personalization to set the wallpaper from below. I found that the desktop wallpaper is no longer a picture on the program. So I considered whether I can set the system wallpaper with code. So I found it on the InternetThe following code, and made some comments according to the online knowledge.

//Get the registry of "hkey_current_user \ \ control panel \ \ desktop" of windows10 system through setting
    QSettings setting("HKEY_CURRENT_USER\\Control Panel\\Desktop", QSettings::NativeFormat);
    //Get the value with the name "wallpaper" on the registry address, that is, the name of windows 10 system
    //The path of the current desktop wallpaper
    QString src = setting.value("WallPaper",true).toString();
    //It is important to convert the path of desktop wallpaper into wide bytes, otherwise the picture will not be displayed
    TCHAR *ptch = (TCHAR *)src.toStdWString().c_str();
    //Show desktop wallpaper SPI_ Setdeskwallpaper indicates that the desktop wallpaper is to be set, and bmpfile is the path of the picture to be set
    // SPIF_ Updateinifile: write the settings of new system parameters into the user profile
    SystemParametersInfo(SPI_SETDESKWALLPAPER, 0,ptch, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE );

Using the above code, you can take out the picture path of desktop wallpaper from the system registry and set the desktop wallpaper again.

Combined with the above codes at both ends, even if the core of the wallpaper is set, the rest can be written in QT.

In order to verify the success of your code, you added some QT code and wrote the QT window class written below. After all, it’s just verification. The following code still needs to be improved.

Header file:

#ifndef WIDGET_H
#define WIDGET_H

#include 

#Include // painter class of QT
#Include // pixmap class of QT

#Include // windows. H is the most important header file. It contains other windows header files
#Include // the qssettings class provides persistent platform independent application settings.

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

public slots:
    /**Slot function to receive the transmitted picture path*/
    void gengGaiTuPian(QString path);
    /**Slot function to receive the transmitted picture path*/
    void guanBiChuangKou();

private:

    /**Picture path*/
    QString tuPianLuJiang = "";

protected:
    /**Override drawing event*/
    void paintEvent(QPaintEvent *event);

};
#endif // WIDGET_H

Source file:

#include "widget.h"

/**Declare a static variable of a handle class*/
static HWND g_workerw = 0;
/**Implement a callback function used by EnumWindows () to get the handle we want to set the program to the desktop location*/
static BOOL CALLBACK EnumWndCallback(HWND tophandle, LPARAM topparamhandle)
{
    //Function: the window we want to use does not have a window name, but we know that the class name of the window we need is: "workerw",
    //We also know that the class name of the child window of the window we need is "shelldll_defview"
    //We also know that the window style of the sub window of the window we need is the visible window style
    //Therefore, we first find that the window style of a window is the visible window style, and then detect whether there is a window with the class name "shelldll_defview" in the sub window of the window,
    //Then check whether the parent window of the window has a window with the class name of "workerw". If they match, this window is the child window of the window we need,
    //The parent window of the window corresponding to the handle stored in the variable tophandle is the window we need

    //Note: the topparamhandle parameter is not used because the EnumWindows function does not
    //Store the variable or variable pointer to get the handle of the window we want, but pass 0. 0 cannot store data
    //Therefore, the window handle obtained through enumwndcallback() function can only be passed through global variables

    //Getwindowlong() function can obtain information about the specified window,
    //Tophandle the handle of the target window, that is, the handle of all top-level windows on the EnumWindows () enumeration screen
    // GWL_ Style is used to get the window style of the window passed in the window handle
    long wflags = GetWindowLong(tophandle, GWL_STYLE);
    //Judge whether the obtained window style is a visible window style
    //The judgment method is to obtain the window style and the visible window style_ Visible and (&) operation
    //If the 29th bit in the binary of the obtained window style is 1,
    //The value after the operation with (&) is the value corresponding to ws_visible, that is, the value that is not 0
    //If the 29th bit in the binary of the obtained window style is 0,
    //The value after the and (&) operation is 0
    // WS_ Visible (hexadecimal is 10000000, binary is 1 0000 0000 0)
    //Then according to! Operator
    if (!(wflags & WS_VISIBLE))
    {
        //Judge whether the obtained window style is not a visible window style
        //If it is not a visible window style, return true and let the enumwindows() function continue to enumerate new windows
        return TRUE;
    };

    //Tophandle is the handle of all top-level windows on the EnumWindows () enumeration screen
    //Use findwindowex() to find the handle of the parent window. It is the handle stored in the variable tophandle. The class of the child window is the handle of the window of "shelldll_defview"
    //The class name of the window we are looking for is "shelldll_defview"
    HWND p = FindWindowEx(tophandle, 0, L"SHELLDLL_DefView", 0);
    //Determines whether a handle was obtained
    if (p != 0)
    {
        // Gets the WorkerW Window after the current one
        //Using findwindowex() to find the handle of the child window is the handle stored in the variable tophandle. The class of the parent window is the handle of the window of "shelldll_defview"
        //The class name of the window we are looking for is "workerw", and the class name is "workerw", which is the window we want to use
        g_workerw = FindWindowEx(0, tophandle, L"WorkerW", 0);
        //Judgment G_ Is the window enumeration value we want stored in workerw
        if (0 != g_workerw)
        {
            //Passed to enumwindows() function false
            //Stop enumwindows() function enumeration
            return FALSE;
        }
    }
    //Passed to enumwindows() function true
    //Let enumwindows() function continue enumeration
    return TRUE;
}

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    /**Use the findwindow() function to obtain a window handle whose class is "progman" and whose title is "program manager"*/
    HWND hwndPrgam = FindWindow(L"Progman", L"Program Manager");
    //Use the sendmessagetimeout() function to send the specified message 0x052c to the window of the enumeration value stored by hwndprgam
    // SMTO_ Normal: when the calling thread waits for the function to return, it is not prevented from processing other requests. 1000 specifies the duration in milliseconds for the timeout period
    SendMessageTimeout(hwndPrgam, 0x052C, 0,0,SMTO_NORMAL, 1000,0);
    //The above two lines of code have been commented according to the query knowledge, but the function is still unclear. Comment out the above two lines of code
    //You can also set the program on the desktop wallpaper

    //Enumwindows() is used to enumerate all top-level windows on the screen, and the enumerated windows are passed into enumwndcallback() function
    //That is, keep passing the window handle to the enumwndcallback() function until you find the handle of the required window
    //Or after enumerating all the windows, we can't find the window we need
    //The second parameter of enumwindows() function is 0, which means that it cannot be obtained through the second parameter of enumwindows() function
    //For the window handle we want, we can only get the window handle we need found in the enumwndcallback() function through the global variable
    EnumWindows(EnumWndCallback, 0);

    //Determines whether a window handle is obtained
    if (g_workerw == 0)
    {
        //If no handle is obtained, the program ends
        abort();
    }
    else
    {
        //If a window handle is obtained

        //Set the program to the wallpaper layer of the desktop
        SetParent((HWND)this->winId(), g_workerw);
    }

    //Remove the border from the window
    this-> setWindowFlags(Qt::FramelessWindowHint | windowFlags() );
    //Setting window full screen display
    this->showFullScreen();
    //Assign a value to tupianlujiang
    tuPianLuJiang = "://BeiJing.jpg";
}

Widget::~Widget()
{
}

void Widget::gengGaiTuPian(QString path)
{
    //Determine whether the path is not empty
    if (!path.isEmpty())
    {
        tuPianLuJiang = path;
        //Call the drawing event through the update() function
        this->update();
    }
}

void Widget::guanBiChuangKou()
{
    //Hide this window
    this->hide();
    //Get the registry of "hkey_current_user \ \ control panel \ \ desktop" of windows system through setting
    QSettings setting("HKEY_CURRENT_USER\\Control Panel\\Desktop", QSettings::NativeFormat);
    //Get the value with the name "wallpaper" on the registry address, that is, the name of windows 10 system
    //The path of the current desktop wallpaper
    QString src = setting.value("WallPaper",true).toString();
    //It is important to convert the path of desktop wallpaper into wide bytes, otherwise the picture will not be displayed
    TCHAR *ptch = (TCHAR *)src.toStdWString().c_str();
    //Show desktop wallpaper SPI_ Setdeskwallpaper indicates that the desktop wallpaper is to be set, and bmpfile is the path of the picture to be set
    // SPIF_ Updateinifile: write the settings of new system parameters into the user profile
    SystemParametersInfo(SPI_SETDESKWALLPAPER, 0,ptch, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE );
    //Delete this class
    //After the class is used, the handle will disappear after deleting the class. When it is the main window, delete is not required
    delete this;
}

void Widget::paintEvent(QPaintEvent *event)
{
    //Instantiate the artist's object
    //You need to add #include header files first
    //This is to set where to draw. It is to specify the drawing device, not to set the parent class
    QPainter painter(this);

    //Instantiate a qpixmap and pass in a local picture
    QPixmap pixmap(tuPianLuJiang);
    //The picture is drawn on the window through an instance of the painter class
    painter.drawPixmap(0, 0, this->width(), this->height(), pixmap);
}

Because of the love of programming, I learned programming for a period of time. Although the learning time is not short, the foundation is too weak. The first time I wrote a blog, this blog is a summary of my learning other knowledge. Improve this program before learning otherQT knowledge.

Recommended Today

Seven Python code review tools recommended

althoughPythonLanguage is one of the most flexible development languages at present, but developers often abuse its flexibility and even violate relevant standards. So PythoncodeThe following common quality problems often occur: Some unused modules have been imported Function is missing arguments in various calls The appropriate format indentation is missing Missing appropriate spaces before and after […]