【发布时间】: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 的原因。感谢您对文件的想法。我会尝试保存并调查