【问题标题】:Get application's icon using Xlib?使用 Xlib 获取应用程序的图标?
【发布时间】:2019-03-29 08:34:57
【问题描述】:

我花了大约两天的时间才达到目标,但是我没有做到我需要的。我的目标是从我的 C++ 应用程序的应用程序窗口中获取图标并将其保存到 wxIcon(或 wxImage 或 wxBitmap - 无关紧要)对象中。 正如我在互联网上发现的,有两种变体可以检索图标:使用_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);
}

但我使用此代码获得的图标与应用程序的图标不同:

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

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

【问题讨论】:

  • This answer 说有 4 个额外的填充字节,您是否尝试过考虑它们?我建议将原始字节保存到文件中,这样可以更轻松地查看它们的格式。
  • 4 个额外字节的填充,据我所知,仅在 x64 系统中。这就是我使用 offset=8 的原因。感谢您对文件的想法。我会尝试保存并调查

标签: c++ wxwidgets xlib


【解决方案1】:

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

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 上它可以工作

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多