c++ - 使用 Xlib 获取应用程序的图标?

标签 c++ wxwidgets xlib

我花了大约两天的时间来达到目标​​,但是我没有做到我需要的。我的目标是从我的 C++ 应用程序的应用程序窗口中获取图标并将其保存到 wxIcon 中。 (或 wxImage 或 wxBitmap - 无关紧要)对象。 正如我在 Internet 上发现的那样,有两种方法可以检索图标:使用 _NET_WM_ICON 窗口属性和使用 XGetWMHints(通过从 XWMHints 结构获取像素图).

这就是我尝试实现第一种方法的方式:

void ApplicationHelper::GetIcon(SRunningWindow* pDesc, void* pDisplay, 
TWindow iWindow, unsigned long uiIconAtom)
{
    unsigned long nitems, bytesafter;
    unsigned char *ret;
    int format;
    Atom type;
    XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 0, 1, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
    int width = *(int*)ret;
    XFree(ret);
    XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 1, 1, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
    int height = *(int*)ret;
    XFree(ret);
    int size = width * height;
    XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 2, size, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
    unsigned char* imgData = new unsigned char[width * height * 3]; // RGB data
    unsigned char* alphaData = new unsigned char[width * height]; // alpha chanel
    int offset = sizeof(long) == 8 ? 8 : 4; // for 64bit systems data represented in order: blue, green, red, alpha, followed by 4 zeros

    int imgIdx = 0;
    int alphaIdx = 0;
    for (int i=0; i < nitems; i += offset)
    {
        imgData[imgIdx] = ret[i + 2]; // R
        imgData[imgIdx + 1] = ret[i + 1]; // G
        imgData[imgIdx + 2] = ret[i]; // B
        alphaData[alphaIdx++] = ret[i + 3]; // A
        imgIdx += 3;
    }
    XFree(ret);
    wxImage img(width, height, imgData, alphaData);
    img.Rescale(16, 16);
    wxBitmap bmp(img);
    pDesc->icon.CopyFromBitmap(bmp);
}

但是我用这段代码得到的图标与应用程序的图标不一样: Icons I get with this code

关于获取图标的第二种变体(从 XGetWMHints 结构获取像素图)我发现,icon_pixmap 字段被定义为 XID ,它是 unsigned long 并且我没有找到如何从此 icon_pixmap 获取 XPM 数据。

那么您能否解释一下我的代码中做错了什么,或者如何从 XWMHints 结构的“icon_pixmap”字段中获取图标? 谢谢。

最佳答案

以防万一其他人需要解决方案:

void ApplicationHelper::GetIcon(SRunningWindow* pDesc, void* pDisplay, TWindow iWindow, unsigned long uiIconAtom)
{
    unsigned long nitems, bytesafter;
    unsigned char *ret;
    int format;
    Atom type;
    XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 0, 1, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
    int width = *(int*)ret;
    XFree(ret);
    XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 1, 1, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
    int height = *(int*)ret;
    XFree(ret);
    int size = width * height;
    XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 2, size, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
    unsigned int* imgData = new unsigned int[size];
    unsigned long* ul = (unsigned long*)ret;
    for (int i=0; i < nitems; ++i)
    {
        imgData[i] = (unsigned int)ul[i];
    }
    XFree(ret);
    wxImage img(width, height);
    img.InitAlpha();
    unsigned char* argb = (unsigned char*)imgData;
    for(int y = 0; y < height; y++)
    {
        for(int x = 0; x < width; x++)
        {
            unsigned char a = argb[3];
            unsigned char r = argb[2] * a / 255;
            unsigned char g = argb[1] * a / 255;
            unsigned char b = argb[0] * a / 255;
            img.SetRGB(x, y, r, g, b);
            img.SetAlpha(x, y, a);
            argb += 4;
        }
    }
    img.Rescale(32, 32);
    wxBitmap bmp(img);
    delete[]imgData;
    pDesc->icon.CopyFromBitmap(bmp);
}

这个想法只是从“原始”数据创建 wxImage。在 x64 Ubuntu 16.04 上运行

关于c++ - 使用 Xlib 获取应用程序的图标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55413341/

相关文章:

c++ - 如何在运行时查看 C 程序的内存布局?

c++ - C++ 上的哈希聚合

wxwidgets - 将鼠标悬停在 gnuradio 中的 FFT 接收器上时缺少弹出窗口

c++ - 如何使用 xlib 识别顶级 X11 窗口?

Python:如何使用 Xlib 在工作区之间切换?

C++ typeid 是否返回字符串类型?

c++ - 编译器不推导出模板参数(map std::vector -> std::vector)

c++ - 屏幕阅读器无法访问 wxWidgets 中的 wxGrid

c++ - 你如何在 WxWidgets 中显示方程式的答案?

c - 输入密码字段时如何检测