// 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;
}
C/C++ Windows API——将文件图标保存为PNG
最新推荐文章于 2023-03-16 14:30:13 发布