Windows资源管理器中自定义文件格式显示缩略图和预览图功能(C++)

您所在的位置:网站首页 在windows的资源管理器中不允许什么文件 Windows资源管理器中自定义文件格式显示缩略图和预览图功能(C++)

Windows资源管理器中自定义文件格式显示缩略图和预览图功能(C++)

2024-07-09 13:13| 来源: 网络整理| 查看: 265

前言

  最近在开发工作中,接到一个需求,要在Windows资源管理器中显示自定义文件格式的缩略图和预览图,由于没有接触过 Shell 加上网上资源较少,经过一番努力终于实现了需要的功能,遂记录一下。

介绍

  根据官方文档介绍,不同的操作系统提供了不同的解决方案。Windows XP 操作系统 通过继承 IExtractImage 或 IExtractImage2 接口实现缩略图功能。Windows Vista 及以上操作系统 ,提供更简单易用的 IThumbnailProivder 接口来代替之前的 IExtractImage 和 IExtractImage2 接口,但后两个接口现在仍然可以使用。   PS:IExtractImage2 继承至 IExtractImage,比后者多了一个 GetDateStamp 方法,通过重写这个方法,允许 Shell 确定缓存的图像是否已经过期。

实现过程 Windows XP

  要实现缩略图功能,必须继承IExtractImage 或 IExtractImage2 接口和下列三个接口中的一个并重写GetLocation、Extract 和 Load 接口:

IPersistStream IPersistFile IPersistStorage 例子 HRESULT CTPeExtract::Load(LPCOLESTR pszFileName, DWORD dwMode) { USES_CONVERSION; _tcscpy_s(m_szFileName, OLE2T((WCHAR*)pszFileName)); return S_OK; };

说明:重写Load函数,在函数中保存自定义文件的路径。

HRESULT CTPeExtract::GetLocation(LPWSTR pszPathBuffer, DWORD cchMax, DWORD *pdwPriority, const SIZE *prgSize, DWORD dwRecClrDepth, DWORD *pdwFlags) { if (*pdwFlags & IEIFLAG_ASYNC) { return E_PENDING; } return NOERROR; }

说明:重写GetLocation函数。

HRESULT CTPeExtract::Extract(HBITMAP* phBmpThumbnail) { /// 解析自定义文件 tinyxml2::XMLDocument doc; doc.LoadFile(m_szFileName); XMLElement *pRoot = doc.RootElement(); const char* cSource = pRoot->FirstChildElement("Attachments") ->FirstChildElement("Picture")->Attribute("source"); /// base64解码 int datalen(0); DWORD dwritelen(0); std::string strdcode = CBase64::Base64Decode(cSource, strlen(cSource), datalen); /// 字符串转换成字节流 int iLength = strdcode.length(); BYTE* pBuffer = new BYTE[iLength + 1]; for (int i = 0; i < iLength; ++i) { pBuffer[i] = strdcode[i]; } /// 字节流转换成HBITMAP *phBmpThumbnail = ConvertDibToHBitmap(pBuffer); delete[] pBuffer; return NOERROR; }

说明:重写Extract函数,在函数中实现自定义文件的解析(主要是解析出自定义文件中缩略图的base64编码),根据缩略图的base64解码构建字节流,然后将字节流转换成HBITMAP。

HRESULT CTPeExtract::GetDateStamp(FILETIME *pDateStamp) { FILETIME ftCreationTime, ftLastAccessTime, ftLastWriteTime; HANDLE hFile = CreateFile(m_szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (!hFile) { return E_FAIL; } GetFileTime(hFile, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime); CloseHandle(hFile); *pDateStamp = ftLastWriteTime; return NOERROR; }

说明:重写GetDateStamp函数。

HBITMAP CTPeExtract::ConvertDibToHBitmap(void* bmpData) { HBITMAP hBitmap = NULL; BOOL success = FALSE; LPBITMAPFILEHEADER bfh = (LPBITMAPFILEHEADER)bmpData; LPBITMAPINFOHEADER bih = (LPBITMAPINFOHEADER)(bfh + 1); void* pixels = (char*)(bih + 1); // NOTE: Assumes no color table (i.e., bpp >= 24) HDC hdc = GetDC(NULL); if (NULL == hdc) { return NULL; } hBitmap = CreateCompatibleBitmap(hdc, bih->biWidth, bih->biHeight); if (NULL == hBitmap) { return NULL; } HDC hdcMem = CreateCompatibleDC(hdc); if (NULL == hdcMem) { return NULL; } HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBitmap); if (StretchDIBits(hdcMem, 0, 0, bih->biWidth, bih->biHeight, 0, 0, bih->biWidth, bih->biHeight, pixels, (LPBITMAPINFO)bih, DIB_RGB_COLORS, SRCCOPY) > 0) { success = TRUE; } SelectObject(hdcMem, hOldBitmap); DeleteDC(hdcMem); ReleaseDC(NULL, hdc); if (!success && hBitmap != NULL) { DeleteObject(hBitmap); hBitmap = NULL; } return hBitmap; }

说明:位图字节流转HBITMAP函数。

Windows Vista 及以上版本

  要实现缩略图功能,必须继承IThumbnailProivder接口和下列三个接口中的一个并重写 Initialize 和 GetThumbnail 接口:

IInitializeWithStream (官方推荐继承这个接口,增强安全性和稳定性) IInitializeWithItem IInitializeWithFile 注意:如果不是继承自 IInitializeWithStream 接口,则必须设置下列的注册表值: HKEY_CLASSES_ROOT CLSID {The CLSID of your thumbnail handler} DisableProcessIsolation = 1 例子(详细例子见参考中的官方例子) class CTestThumbnail : public IInitializeWithStream, public IThumbnailProvider { public: CTestThumbnail() : _cRef(1), _pStream(NULL) { } virtual ~CTestThumbnail() { if (_pStream) { _pStream->Release(); } } // IUnknown IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv) { static const QITAB qit[] = { QITABENT(CTestThumbnail, IInitializeWithStream), QITABENT(CTestThumbnail, IThumbnailProvider), { 0 }, }; return QISearch(this, qit, riid, ppv); } IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&_cRef); } IFACEMETHODIMP_(ULONG) Release() { ULONG cRef = InterlockedDecrement(&_cRef); if (!cRef) { delete this; } return cRef; } // IInitializeWithStream IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode); // IThumbnailProvider IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha); private: HRESULT _LoadXMLDocument(IXMLDOMDocument **ppXMLDoc); HRESULT _GetBase64EncodedImageString(UINT cx, PWSTR *ppszResult); HRESULT _GetStreamFromString(PCWSTR pszImageName, IStream **ppStream); long _cRef; IStream *_pStream; // provided during initialization. };

说明:主要是重写 Initialize 和 GetThumbnail 两个函数,在 Initialize 完成初始化,在 GetThumbnail 完成自定义文件的解析,base64 的解码,HBITMAP 的构建。

参考 微软官方文档 微软官方例子 以缩略图的形式在Windows资源浏览器中显示自定义格式图片 字节流转换HBITMAP


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3