我花了大约两天的时间才能达到目标,但是我没有做我需要做的事情。我的目标是从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);
}
关于获取图标的第二种方式(从XGetWMHints
结构获取像素图),我发现icon_pixmap
字段定义为XID
,即unsigned long
,但我没有查找如何从此icon_pixmap
获取XPM数据。
那么您能否解释一下我在代码中做错了什么,或者如何从XWMHints
结构的“ icon_pixmap”字段获取图标?
谢谢。
答案 0 :(得分:0)
以防万一其他人需要解决方案:
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上可以运行