Windows下C++三种方法获取文件缩略图并保存为图片

1. 简介

在Windows文件夹中,不需要打开文件,即可以通过大图标、平铺等方面查看到不同文件的缩略图。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201222204635330.png

2. 方法一

缩略图信息文件夹的,在文件夹中显示。所以Windows提供了文件夹相关组件来获取缩略图信息。因为IShellFolder组件的方法只能用宽字符,所以接口需要使用宽字符符。此方法兼容XP系统及之后的操作系统。

HBITMAP GetThumbnail(const std::wstring& _strFilePath)
{
	std::wstring strDir;
	std::wstring strFileName;
	int nPos = _strFilePath.find_last_of(L"\\");
	strDir = _strFilePath.substr(0,nPos);
	strFileName = _strFilePath.substr(nPos+1);

	CComPtr<IShellFolder> pDesktop = NULL;
	HRESULT hr = SHGetDesktopFolder(&pDesktop);
	if(FAILED(hr)) 
		return NULL;

	LPITEMIDLIST pidl = NULL;
	hr = pDesktop->ParseDisplayName(NULL, NULL, (LPWSTR)strDir.c_str(), NULL, &pidl, NULL);
	if(FAILED(hr)) 
		return NULL;

	CComPtr<IShellFolder> pSub = NULL;
	hr = pDesktop->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&pSub);
	if(FAILED(hr)) 
		return NULL;

	hr = pSub->ParseDisplayName(NULL, NULL, (LPWSTR)strFileName.c_str(), NULL, &pidl, NULL);
	if(FAILED(hr))
		return NULL;

	CComPtr<IExtractImage> pIExtract = NULL;
	hr = pSub ->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST *)&pidl, IID_IExtractImage, NULL, (void**)& pIExtract);
	if(FAILED(hr)) 
		return NULL;

	SIZE size = {64, 128}; // 请求获取的图片大小
	DWORD dwFlags = IEIFLAG_ORIGSIZE | IEIFLAG_QUALITY;
	OLECHAR pathBuffer[MAX_PATH] = {0};
	// 24为颜色深度,缩略图一般是24位颜色
	hr = pIExtract->GetLocation(pathBuffer, MAX_PATH, NULL, &size, 24, &dwFlags);
	if(FAILED(hr)) 
		return NULL;

	// Get the image
	HBITMAP hThumbnail = NULL;
	hr = pIExtract ->Extract(&hThumbnail);
	if(FAILED(hr)) 
		return NULL;

	return hThumbnail;
}

3. 方法二

随着Windows的升级,Windows针对缩略图,还提供了专组件接口,更加方便。但是只支持Win7及之后的系统。


HBITMAP GetThumbnailEx(WCHAR* path)
{
	HRESULT hr = CoInitialize(nullptr);

	// Get the thumbnail
	IShellItem* item = nullptr;
	hr = SHCreateItemFromParsingName(path, nullptr, IID_PPV_ARGS(&item));

	IThumbnailCache* cache = nullptr;
	hr = CoCreateInstance(
		CLSID_LocalThumbnailCache,
		nullptr,
		CLSCTX_INPROC,
		IID_PPV_ARGS(&cache));

	ISharedBitmap* shared_bitmap;
	hr = cache->GetThumbnail(
		item,
		48*64,
		WTS_EXTRACT,
		&shared_bitmap,
		nullptr,
		nullptr);

	// Retrieve thumbnail HBITMAP
	HBITMAP hbitmap = NULL;
	hr = shared_bitmap->GetSharedBitmap(&hbitmap);
	CoUninitialize();

	return hbitmap;
}

3. 方法三

有时自定义的文档,也想让系统显示相应的缩略图,怎么办呢?Windows提供了COM组件接口,只需要实际相应的接口处理自己定义的文件,然后完成相应文档缩略图的定义即可。
更多详细信息参考官方资料:C++ Windows Shell thumbnail handler

4. 其他

4.1. 保存图片


BOOL SaveBitmapToFile(HBITMAP hBitmap, const CString& szfilename)
{          
	//计算位图文件每个像素所占字节数              
	HDC hDC  = CreateDC("DISPLAY", NULL, NULL, NULL);  
	int iBits  = GetDeviceCaps(hDC,   BITSPIXEL)*GetDeviceCaps(hDC,   PLANES);             
	DeleteDC(hDC);       
	//位图中每象素所占字节数
	WORD wBitCount = 0;
	if(iBits <=  1)                                                   
		wBitCount = 1;             
	else  if(iBits <=  4)                               
		wBitCount  = 4;             
	else if(iBits <=  8)                               
		wBitCount  = 8;             
	else                                                                                                                               
		wBitCount  = 24;

	BITMAP Bitmap = {};
	GetObject(hBitmap,   sizeof(Bitmap),   (LPSTR)&Bitmap);      
	BITMAPINFOHEADER bi = {};
	bi.biSize= sizeof(BITMAPINFOHEADER);      
	bi.biWidth = Bitmap.bmWidth;         
	bi.biHeight =  Bitmap.bmHeight;         
	bi.biPlanes =  1;         
	bi.biBitCount = wBitCount;         
	bi.biCompression= BI_RGB;                

	DWORD dwBmBitsSize  = 16*((Bitmap.bmWidth *wBitCount+31) / 32)*4* Bitmap.bmHeight;         

	//为位图内容分配内存              
	DWORD dwPaletteSize = 0;
	HANDLE hDib  = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));             
	LPBITMAPINFOHEADER lpbi  = (LPBITMAPINFOHEADER)GlobalLock(hDib);             
	*lpbi  = bi;             

	// 处理调色板
	HANDLE hOldPal = NULL; 
	HANDLE hPal = GetStockObject(DEFAULT_PALETTE);             
	if (hPal)             
	{             
		hDC  = ::GetDC(NULL);             
		hOldPal = ::SelectPalette(hDC,(HPALETTE)hPal, FALSE);             
		RealizePalette(hDC);             
	}         

	//位图文件大小写入文件字节数              
	DWORD dwDIBSize=0;
	DWORD dwWritten=0;      

	// 获取该调色板下新的像素值              
	GetDIBits(hDC,hBitmap, 0,(UINT)Bitmap.bmHeight,  
		(LPSTR)lpbi+ sizeof(BITMAPINFOHEADER)+dwPaletteSize,   
		(BITMAPINFO *)lpbi, DIB_RGB_COLORS);             

	//恢复调色板                  
	if (hOldPal)             
	{             
		::SelectPalette(hDC,   (HPALETTE)hOldPal,   TRUE);             
		RealizePalette(hDC);             
		::ReleaseDC(NULL,   hDC);             
	}             

	//创建位图文件                  
	HANDLE fh  = CreateFile(szfilename,   GENERIC_WRITE,0,   NULL,   CREATE_ALWAYS,           
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,   NULL);             

	if (fh == INVALID_HANDLE_VALUE)         
		return FALSE;            

	// 设置位图文件头              
	BITMAPFILEHEADER bmfHdr = {};
	bmfHdr.bfType = 0x4D42;     //"BM"              
	dwDIBSize  = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize;                 
	bmfHdr.bfSize = dwDIBSize;                       
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+dwPaletteSize;    

	// 写入位图文件头              
	WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);             
	// 写入位图文件其余内容              
	WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);             
	// 清除                  
	GlobalUnlock(hDib);             
	GlobalFree(hDib);             
	CloseHandle(fh);             

	return TRUE;         
}

4.2. 代码

代码

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C 语言中,获取任意文件缩略图需要使用操作系统提供的 API 函数。以下是 Windows 平台下获取文件缩略图的示例代码: ```c #include <windows.h> #include <shobjidl.h> #include <stdio.h> int main() { HRESULT hr = CoInitialize(NULL); if (SUCCEEDED(hr)) { IShellItemImageFactory* pImageFactory; WCHAR wszFilePath[MAX_PATH] = L"C:\\test.jpg"; // 文件路径 SHCreateItemFromParsingName(wszFilePath, NULL, IID_PPV_ARGS(&pImageFactory)); SIZE size = { 100, 100 }; // 缩略图大小 HBITMAP hBitmap; pImageFactory->GetImage(size, SIIGBF_THUMBNAILONLY, &hBitmap); if (hBitmap) { // 保存缩略图文件 BITMAP bmp; GetObject(hBitmap, sizeof(bmp), &bmp); BITMAPFILEHEADER bfh = { 0 }; bfh.bfType = 0x4d42; // "BM" bfh.bfSize = sizeof(bfh) + sizeof(BITMAPINFOHEADER) + bmp.bmWidthBytes * bmp.bmHeight; bfh.bfOffBits = sizeof(bfh) + sizeof(BITMAPINFOHEADER); BITMAPINFOHEADER bih = { 0 }; bih.biSize = sizeof(bih); bih.biWidth = bmp.bmWidth; bih.biHeight = bmp.bmHeight; bih.biPlanes = 1; bih.biBitCount = 24; FILE* fp; fopen_s(&fp, "thumbnail.bmp", "wb"); fwrite(&bfh, sizeof(bfh), 1, fp); fwrite(&bih, sizeof(bih), 1, fp); BYTE* pBits = new BYTE[bmp.bmWidthBytes * bmp.bmHeight]; GetBitmapBits(hBitmap, bmp.bmWidthBytes * bmp.bmHeight, pBits); fwrite(pBits, bmp.bmWidthBytes * bmp.bmHeight, 1, fp); fclose(fp); delete[] pBits; DeleteObject(hBitmap); } pImageFactory->Release(); CoUninitialize(); } return 0; } ``` 上述代码通过调用 `SHCreateItemFromParsingName` 函数创建一个 `IShellItemImageFactory` 对象,然后调用 `GetImage` 函数获取缩略图,并将缩略图保存文件中。注意,需要链接 `ole32.lib` 和 `windowscodecs.lib` 库文件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值