- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在使用 IShellItemImageFactory 来提取文件的图标。我能够成功提取它并在对话框中使用SendDlgItemMessage(hDlg,IDC_STATIC2, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hicon);
查看输出:click here
问题是当我使用 GDI+ 将其保存为文件(PNG 格式)时,渐变不保留校正。在下面找到我正在使用的代码。
GdiplusStartupInput gdiplusStartupInput;ULONG_PTR gdiplusToken;GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);Bitmap *h = new Bitmap(256, 256, PixelFormat32bppARGB);Graphics* g = Graphics::FromImage(copy);HDC copyHdc = g->GetHDC();DrawIconEx(copyHdc, 0, 0, hicon, 256, 256, 0, NULL, DI_NORMAL);g->ReleaseHDC(copyHdc);;CLSID encoderClsid;GetEncoderClsid(L"image/png", &encoderClsid);h->Save(L"D:\\mynew.png", &encoderClsid, NULL);GdiplusShutdown(gdiplusToken);
提取文本文件后得到的输出:click here
谁能帮我解决这个问题?
问候,马诺杰
最佳答案
这个主题比较老,但我遇到了同样的问题,并且花了很多时间来寻找一种可以保留 PNG 文件透明度的解决方案。
既然问题可以用Java轻松解决...
sun.awt.shell.ShellFolder sf = sun.awt.shell.ShellFolder.getShellFolder(file);
ImageIcon icon = new ImageIcon(sf.getIcon(true));
FileOutputStream bos = new FileOutputStream("d:\\icons\\icon.png");
ImageIO.write((BufferedImage)icon.getImage(), "PNG", bos);
... 我看了一下JDK源代码。在函数“Java_sun_awt_shell_Win32ShellFolder2_getIconBits”的文件“\jdk\src\windows\native\sun\windows\ShellFolder2.cpp”中,我找到了我需要的有值(value)的提示。
此函数从 HICON 中检索颜色位图并调用 GetDIBits 获取图像数据。绘制图标不是必需的 - 无论如何透明度都会丢失。
非常感谢 JDK 开发人员。
这是我最终得到的代码:
static CLSID g_pngClsid = GUID_NULL;
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms533843(v=vs.85).aspx
extern int GetEncoderClsid(const WCHAR* format, CLSID* pClsid);
static HICON getShellIconByIndex(int shilsize, int iImage)
{
IImageListPtr spiml;
SHGetImageList(shilsize, IID_PPV_ARGS(&spiml));
HICON hico;
spiml->GetIcon(iImage, ILD_TRANSPARENT, &hico);
return hico;
}
static HICON getShellIcon(int shilsize, const std::wstring& fname) {
UINT flags = SHGFI_SYSICONINDEX;
SHFILEINFO fi = {0};
HICON hIcon = NULL;
if (SHGetFileInfo(fname.c_str(), 0, &fi, sizeof(fi), flags) != 0) {
hIcon = getShellIconByIndex(shilsize, fi.iIcon);
}
return hIcon;
}
struct BITMAP_AND_BYTES {
Gdiplus::Bitmap* bmp;
int32_t* bytes;
};
static BITMAP_AND_BYTES createAlphaChannelBitmapFromIcon(HICON hIcon) {
// Get the icon info
ICONINFO iconInfo = {0};
GetIconInfo(hIcon, &iconInfo);
// Get the screen DC
HDC dc = GetDC(NULL);
// Get icon size info
BITMAP bm = {0};
GetObject( iconInfo.hbmColor, sizeof( BITMAP ), &bm );
// Set up BITMAPINFO
BITMAPINFO bmi = {0};
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = bm.bmWidth;
bmi.bmiHeader.biHeight = -bm.bmHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
// Extract the color bitmap
int nBits = bm.bmWidth * bm.bmHeight;
int32_t* colorBits = new int32_t[nBits];
GetDIBits(dc, iconInfo.hbmColor, 0, bm.bmHeight, colorBits, &bmi, DIB_RGB_COLORS);
// Check whether the color bitmap has an alpha channel.
// (On my Windows 7, all file icons I tried have an alpha channel.)
BOOL hasAlpha = FALSE;
for (int i = 0; i < nBits; i++) {
if ((colorBits[i] & 0xff000000) != 0) {
hasAlpha = TRUE;
break;
}
}
// If no alpha values available, apply the mask bitmap
if (!hasAlpha) {
// Extract the mask bitmap
int32_t* maskBits = new int32_t[nBits];
GetDIBits(dc, iconInfo.hbmMask, 0, bm.bmHeight, maskBits, &bmi, DIB_RGB_COLORS);
// Copy the mask alphas into the color bits
for (int i = 0; i < nBits; i++) {
if (maskBits[i] == 0) {
colorBits[i] |= 0xff000000;
}
}
delete[] maskBits;
}
// Release DC and GDI bitmaps
ReleaseDC(NULL, dc);
::DeleteObject(iconInfo.hbmColor);
::DeleteObject(iconInfo.hbmMask);
// Create GDI+ Bitmap
Gdiplus::Bitmap* bmp = new Gdiplus::Bitmap(bm.bmWidth, bm.bmHeight, bm.bmWidth*4, PixelFormat32bppARGB, (BYTE*)colorBits);
BITMAP_AND_BYTES ret = {bmp, colorBits};
return ret;
}
static void saveFileIconAsPng(int shilsize, const std::wstring& fname, const std::wstring& pngFile) {
HICON hIcon = getShellIcon(shilsize, fname);
BITMAP_AND_BYTES bbs = createAlphaChannelBitmapFromIcon(hIcon);
IStream* fstrm = NULL;
SHCreateStreamOnFile(pngFile.c_str(), STGM_WRITE|STGM_CREATE, &fstrm);
bbs.bmp->Save(fstrm, &g_pngClsid, NULL);
fstrm->Release();
delete bbs.bmp;
delete[] bbs.bytes;
DestroyIcon(hIcon);
}
调用示例:
GdiplusStartup(...);
GetEncoderClsid(L"image/png", &g_pngClsid);
wstring fname = L"d:\\index.html";
wstring pngFile = L"d:\\icons\\index.html.png";
saveFileIconAsPng(SHIL_JUMBO, fname, pngFile);
GdiplusShutdown(...);
关于c++ - 将 HICON 另存为 png,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1818990/
作为一个更大项目的一部分,我试图从现有的 HICON 创建一个 HICON,首先将该图标绘制到 HBITMAP,然后将其转换回 HICON。 (这将允许我修改图标,例如,通过在其上绘制文本。) 不幸的
我想在系统托盘中显示一个图标。 看起来应该这么简单,但我不知道如何创建一个 HICON 并绘制它!所有“兼容位图”、“兼容 DC”等东西让我很困惑。 如何绘制图标? 最佳答案 无需过多介绍,您可以使用
我正在尝试为任何文件获取一个图标(如 HICON),以与资源管理器完全相同的方式绘制它。这意味着如果我有一个 exe 文件的路径,我应该绘制它的默认图标。如果我有一个链接 (.lnk) 文件,我必须绘
我有一个由 HICON 标识的图标我想以自定义控件为中心绘制的句柄。 如何确定图标的大小以便计算正确的绘图位置? 最佳答案 这是一个 C++ 版本的代码: struct MYICON_INFO {
我有一个 HICON,我想将其用作另一个 HICON 的叠加层,以创建结果 HICON。结果 HICON 然后将用于“所有者绘制”控件(注意:它不使用图像列表)。覆盖图标具有透明颜色 RGB(0, 2
我使用 minGW 和 eclipse。我用这种方式制作了 HICON: case WM_CREATE: { ... hIcon = (HICON)LoadImage(NULL, "icon.ico"
我正在使用不支持 DPI 的按钮。我在我的代码中到处都在使用它,所以理想情况下我想在该按钮的 SetIcon 中添加几行。 SetIcon 方法(不出所料)将 HICON 作为参数 - 我想根据 DP
我在内存中有一个 .ico 文件的内容作为 const char*,我希望从中创建一个 HICON数据。我目前的做法是将数据写入一个临时文件,然后使用LoadImage。是否可以直接从内存中创建图标?
我们有什么方法可以将 HICON 或 HCURSOR 转换为字节数组,我用谷歌搜索了所有方法我没有找到一个通用的解决方案,下面我尝试转换HICON 颜色和掩码 BITMAP 到字节数组并通过套接字发送
我想定义 Win32 窗口的应用程序图标,例如通过使用 GCL_HICON 调用 SetClassLong 并将句柄传递给图标(参见 MSDN 上的 SetClassLong Function)。 这
我在内存中有一个 PNG 编码的图标作为字节数组。从这个字节数组创建 HICON 对象的推荐方法是什么? 假想的加分,如果你知道没有 ATL 或 GDI+ 的解决方案...:) 最佳答案 HGLOBA
我正在使用 IShellItemImageFactory 来提取文件的图标。我能够成功提取它并在对话框中使用SendDlgItemMessage(hDlg,IDC_STATIC2, STM_SETIM
我的最终目标是在JNA库的帮助下获得Java中HWND的图标。一切工作正常,除了一件重要的事情:我需要图标的大小以便在 Java 中进行进一步的处理步骤。 看来我无法要求尺寸。我总是得到大小 0x0。
我正在尝试从系统中获取图标。通过使用 SHGetFileInfo 我得到了 HICON, 我用下面的代码测试了这个 HICON: SHFILEINFO info; //For getting i
我正在从 .exe/.dll 中提取一个图标,并想将其保存在一个 .ico 文件中。执行此操作的最佳方法是什么? 我尝试使用 ::OleCreatePictureIndirect(),然后使用 IPi
对于 x64 目标构建,从“OLE_HANDLE”转换为“HICON”的正确方法是什么? 特别是对于普通的 C 风格转换,我在使用 x64 配置编译时收到此警告: 警告 C4312:“类型转换”:从“
我知道已经有一个 question like this .但它的解决方案不适合我,因为使用 Sehellfolder Methode 你只能得到 16x16 和 32x32 大小的图标。我提取了一个大
如何在VC++中将HICON转成HBITMAP? 我知道这是一个常见问题解答,但我在 Google 上找到的所有解决方案都不起作用。我需要的是一个接受参数 HICON 并返回 HBITMAP 的函数。
我正在开发一个 C/S 应用程序,C++ 中的服务器和 C# 中的客户端,我需要发送一些有关当前正在运行的进程和相关图标的信息。感谢 EnumWindows 我得到了图标文件,回调中有这段代码...
我正在尝试将一些 PNG 图像加载到 WinAPI ImageList 中,作为要在 ListView 中显示的元素的图标。我用 Gdiplus 做这个,我遇到的问题是质量很差。就像颜色深度减少了之类
我是一名优秀的程序员,十分优秀!