Getting a list of window WIds in QT

2019-02-26 06:27发布

问题:

I'm writing a library in QT which will take screenshots of arbitrary external windows. I know how to take the screenshot using QScreen::grabWindow(), but this takes as an argument a WId, and I would like to know if there is a way to get a list of WIds for all windows on the screen and/or desktop (or something similar, such as getting a WId for a specific window using a title name), via QT. I am aware that I can do this in a platform dependent way, such as EnumWindows in Windows, but I was hoping to keep it cross-platform within QT if possible.

回答1:

This isn't possible with Qt. If you want your library to be platform independent, you need to write a code for each platform you want to support.

To make this platform independent, you have to write a (public) function in which you test for the platform using preprocessor #if:

#ifdef __unix__
    // call unix specific code
#elseif ...
    // other platforms
#else
#error Platform not supported!
#endif

For the unix specific code, you need to use xlib, which manages the windows in a tree. From the following code, you will get ALL windows, and in X11 there are a lot of invisible windows and windows which you don't think that they are separate windows. So you definitely have to filter the results, but this depends on which window types you want to have.

Take this code as a start:

#include <X11/Xlib.h>

// Window is a type in Xlib.h
QList<Window> listXWindowsRecursive(Display *disp, Window w)
{
    Window root;
    Window parent;
    Window *children;
    unsigned int childrenCount;

    QList<Window> windows;
    if(XQueryTree(disp, w, &root, &parent, &children, &childrenCount))
    {
        for(unsigned int i = 0; i < childrenCount; ++i)
        {
            windows << children[i];
            windows << listXWindowsRecursive(disp, children[i]);
        }
        XFree(children);
    }
    return windows;
}

Display *disp = XOpenDisplay(":0.0");
Window rootWin = XDefaultRootWindow(disp);
QList<Window> windows = listXWindowsRecursive(disp, rootWin);

foreach(Window win, windows)
{
    // Enumerate through all windows
}