C/C++ Windows API——将文件图标保存为PNG

来源:互联网 发布:华为 mac过滤 编辑:程序博客网 时间:2024/05/16 11:41
// FileInfoDemo.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <windows.h>#include <shellapi.h>//SHGetFileInfo#include <ShObjIdl.h>//IShellFolder::GetAttributesOf#include <gdiplus.h>#pragma comment(lib, "gdiplus.lib")int GetEncoderClsid(const WCHAR* format, CLSID* pClsid){    UINT num = 0, size = 0;    Gdiplus::GetImageEncodersSize(&num, &size);    if (size == 0)        return -1;  // Failure    Gdiplus::ImageCodecInfo* pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));    Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);    bool found = false;    for (UINT ix = 0; !found && ix < num; ++ix)    {        if (_wcsicmp(pImageCodecInfo[ix].MimeType, format) == 0)        {            *pClsid = pImageCodecInfo[ix].Clsid;            found = true;            break;        }    }    free(pImageCodecInfo);    return found;}//根据图标HICON保存图片为Png图片bool SaveHIconToPngFile(HICON hIcon, LPCTSTR lpszPicFileName){    if (hIcon == NULL)    {        return false;    }    ICONINFO icInfo = { 0 };    if (!::GetIconInfo(hIcon, &icInfo))    {        return false;    }    BITMAP bitmap;    GetObject(icInfo.hbmColor, sizeof(BITMAP), &bitmap);    Gdiplus::Bitmap* pBitmap = NULL;    Gdiplus::Bitmap* pWrapBitmap = NULL;    do    {        if (bitmap.bmBitsPixel != 32)        {            pBitmap = Gdiplus::Bitmap::FromHICON(hIcon);        }        else        {            pWrapBitmap = Gdiplus::Bitmap::FromHBITMAP(icInfo.hbmColor, NULL);            if (!pWrapBitmap)                break;            Gdiplus::BitmapData bitmapData;            Gdiplus::Rect rcImage(0, 0, pWrapBitmap->GetWidth(), pWrapBitmap->GetHeight());            pWrapBitmap->LockBits(&rcImage, Gdiplus::ImageLockModeRead, pWrapBitmap->GetPixelFormat(), &bitmapData);            pBitmap = new (Gdiplus::Bitmap)(bitmapData.Width, bitmapData.Height, bitmapData.Stride, PixelFormat32bppARGB, (BYTE*)bitmapData.Scan0);            pWrapBitmap->UnlockBits(&bitmapData);        }        CLSID encoderCLSID;        GetEncoderClsid(_T("image/png"), &encoderCLSID);        Gdiplus::Status st = pBitmap->Save(lpszPicFileName, &encoderCLSID, NULL);        if (st != Gdiplus::Ok)            break;    } while (false);    delete pBitmap;    if (pWrapBitmap)        delete pWrapBitmap;    DeleteObject(icInfo.hbmColor);    DeleteObject(icInfo.hbmMask);    return true;}int main(){    TCHAR *filePath = L"C:\\Users\\chenjia2014\\Desktop\\ReplDemo2.exe";    TCHAR *imagePath = L"C:\\Users\\chenjia2014\\Desktop\\test_img.png";    SHFILEINFO shFileInfo = { 0 };    BOOL ret;    CoInitialize(NULL);    /*    WINSHELLAPI DWORD WINAPI SHGetFileInfo (        LPCWSTR pszPath,        //指定文件名,当uFlags的取值中不包含 SHGFI_PIDL时,可直接指定;当uFlags的取值中包含 SHGFI_PIDL时pszPath要通过计算获得,不能直接指定;        DWORD dwFileAttributes, //文件属性,仅当uFlags的取值中包含SHGFI_USEFILEATTRIBUTES时有效,一般不用此参数;        SHFILEINFOW *psfi,      //返回获得的文件信息,是一个记录类型        UINT cbFileInfo,        //psfi的比特值        UINT uFlags             //指明需要返回的文件信息标识符    );    函数SHGetFileInfo()的返回值也随uFlags的取值变化而有所不同。SHGetFileInfo()不能获得“我的电脑”等虚似文件夹的信息。    在调用SHGetFileInfo()之前,必须使用 CoInitialize 或者OleInitialize 初始化COM,否则表面上能够使用,但是会造成不安全或者丧失部分功能。    typedef struct _SHFILEINFOW {        HICON       hIcon;                      // out: icon        int         iIcon;                      // out: icon index        DWORD       dwAttributes;               // out: SFGAO_ flags        WCHAR       szDisplayName[MAX_PATH];    // out: display name (or path)        WCHAR       szTypeName[80];             // out: type name    } SHFILEINFOW;    #define SHGFI_ICON              0x000000100     // get icon    #define SHGFI_DISPLAYNAME       0x000000200     // get display name    #define SHGFI_TYPENAME          0x000000400     // get type name    #define SHGFI_ATTRIBUTES        0x000000800     // get attributes    #define SHGFI_ICONLOCATION      0x000001000     // get icon location    #define SHGFI_EXETYPE           0x000002000     // return exe type    #define SHGFI_SYSICONINDEX      0x000004000     // get system icon index    #define SHGFI_LINKOVERLAY       0x000008000     // put a link overlay on icon    #define SHGFI_SELECTED          0x000010000     // show icon in selected state    #if (NTDDI_VERSION >= NTDDI_WIN2K)    #define SHGFI_ATTR_SPECIFIED    0x000020000     // get only specified attributes    #endif // (NTDDI_VERSION >= NTDDI_WIN2K)    #define SHGFI_LARGEICON         0x000000000     // get large icon    #define SHGFI_SMALLICON         0x000000001     // get small icon    #define SHGFI_OPENICON          0x000000002     // get open icon    #define SHGFI_SHELLICONSIZE     0x000000004     // get shell size icon    #define SHGFI_PIDL              0x000000008     // pszPath is a pidl    #define SHGFI_USEFILEATTRIBUTES 0x000000010     // use passed dwFileAttribute    #define SHGFI_ADDOVERLAYS       0x000000020     // apply the appropriate overlays    #define SHGFI_OVERLAYINDEX      0x000000040     // Get the index of the overlay    // in the upper 8 bits of the iIcon    */    ret = SHGetFileInfo(filePath, 0, &shFileInfo, sizeof(shFileInfo), SHGFI_DISPLAYNAME | SHGFI_TYPENAME | SHGFI_ATTRIBUTES);    printf("SHGetFileInfo -> %d\n", ret);    printf("szDisplayName = %ls, szTypeName = %ls\n", shFileInfo.szDisplayName, shFileInfo.szTypeName);    printf("attribute = %d\n", shFileInfo.dwAttributes);    ret = SHGetFileInfo(filePath, 0, &shFileInfo, sizeof(shFileInfo),  SHGFI_ICON | SHGFI_SYSICONINDEX);    printf("SHGetFileInfo -> %d\n", ret);    printf("shFileInfo.hIcon = 0x%x, shFileInfo.iIcon = %d\n", shFileInfo.hIcon, shFileInfo.iIcon);    Gdiplus::GdiplusStartupInput gdiplusStartupInput;    ULONG_PTR gdiplusToken;    /*    初始化GDI+函数库,否则无法生成图片    extern "C" Status WINAPI GdiplusStartup(        OUT ULONG_PTR *token,               //用于接受GDI+的TOKEN.TOKEN可以暂时理解成一个句柄,就像窗口的句柄类似。        const GdiplusStartupInput *input,        OUT GdiplusStartupOutput *output    );    struct GdiplusStartupInput {        UINT32 GdiplusVersion;             // Must be 1  (or 2 for the Ex version)        DebugEventProc DebugEventCallback; // Ignored on free builds        BOOL SuppressBackgroundThread;     // FALSE unless you're prepared to call        // the hook/unhook functions properly        BOOL SuppressExternalCodecs;       // FALSE unless you want GDI+ only to use        // its internal image codecs.        GdiplusStartupInput(            DebugEventProc debugEventCallback = NULL,            BOOL suppressBackgroundThread = FALSE,            BOOL suppressExternalCodecs = FALSE)        {            GdiplusVersion = 1;            DebugEventCallback = debugEventCallback;            SuppressBackgroundThread = suppressBackgroundThread;            SuppressExternalCodecs = suppressExternalCodecs;        }    };    */    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);    ret = SaveHIconToPngFile(shFileInfo.hIcon, imagePath);    printf("SaveHIconToPngFile -> %d\n", ret);    //这个函数在结束GDI+编程后调用,起作用是释放GDI+的资源    Gdiplus::GdiplusShutdown(gdiplusToken);    //销毁一个图标并且释放该图标所占用的内存    DestroyIcon(shFileInfo.hIcon);    CoUninitialize();    system("pause");    return 0;}
1 0