首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在C++中保留颜色深度的同时提取文件图标并保存为.ico?

如何在C++中保留颜色深度的同时提取文件图标并保存为.ico?
EN

Stack Overflow用户
提问于 2019-08-30 17:04:23
回答 1查看 267关注 0票数 0

我可以提取一个文件的图标,并使用下面的脚本保存它,但脚本将图标保存为灰色(似乎是4位颜色深度)。

如何在保存图标的同时保留其原始颜色深度?

代码语言:javascript
运行
复制
using namespace std;

#include <iostream>
#include <string>
#include <fstream>
#include <windows.h>

#include "commctrl.h"
#pragma comment(lib, "comctl32.lib")

#include <olectl.h>
#pragma comment(lib, "oleaut32.lib")

HRESULT SaveIcon(HICON hIcon, PCTSTR path) {
    // Create the IPicture intrface
    PICTDESC desc = { sizeof(PICTDESC) };
    desc.picType = PICTYPE_ICON;
    desc.icon.hicon = hIcon;
    IPicture* pPicture = 0;
    HRESULT hr = OleCreatePictureIndirect(&desc, IID_IPicture, FALSE, (void**)& pPicture);
    if (FAILED(hr)) return hr;

    // Create a stream and save the image
    IStream* pStream = 0;
    CreateStreamOnHGlobal(0, TRUE, &pStream);
    LONG cbSize = 0;
    hr = pPicture->SaveAsFile(pStream, TRUE, &cbSize);

    // Write the stream content to the file
    if (!FAILED(hr)) {
        HGLOBAL hBuf = 0;
        GetHGlobalFromStream(pStream, &hBuf);
        void* buffer = GlobalLock(hBuf);
        HANDLE hFile = CreateFile(path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
        if (!hFile) hr = HRESULT_FROM_WIN32(GetLastError());
        else {
            DWORD written = 0;
            WriteFile(hFile, buffer, cbSize, &written, 0);
            CloseHandle(hFile);
        }
        GlobalUnlock(buffer);
    }
    // Cleanup
    pStream->Release();
    pPicture->Release();
    return hr;

}

HICON GetIcon(PCTSTR pszFile)
{
    SHFILEINFO sfi;
    HIMAGELIST himl = reinterpret_cast<HIMAGELIST>(
        SHGetFileInfo(pszFile, 0, &sfi, sizeof(sfi),
            SHGFI_SYSICONINDEX));
    if (himl) {
        return ImageList_GetIcon(himl, sfi.iIcon, ILD_NORMAL);
    }
    else {
        return NULL;
    }
}

int main()
{
    string fileBaseName = "appName";
    wstring fileBaseNameWSTRING(fileBaseName.begin(), fileBaseName.end());

    HICON hIcon = GetIcon((fileBaseNameWSTRING + L".lnk").c_str());

    if (hIcon == NULL) {
        cout << "GetIcon failed" << endl;
        return 1;
    }
    else {
        HRESULT hr = SaveIcon(hIcon, (L"temp\\" + fileBaseNameWSTRING + L".ico").c_str());
        return hr;
    }
}

SaveIcon函数取自此页面:How can I save HICON to an .ico file?

EN

回答 1

Stack Overflow用户

发布于 2019-08-30 18:02:07

通常,图标包含多个原始位深度,也包含多个分辨率。返回HICON的API不会这样做,它们会从图标中选择一个图像。

如果你想要完整的文件,把SHGFI_SYSICONINDEX改成SHGFI_ICONLOCATION,你会得到一个带有图标+图标索引的DLL的路径。

加载DLL,最好使用LoadLibraryEx API和LOAD_LIBRARY_AS_DATAFILE选项。

然后调用资源API FindResource / LoadResource / SizeofResource / LockResource,获取图标的源数据。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57723702

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档