|
|
#include "precomp.h"
#include "shutil.h"
HRESULT GetFileInfoByHandle(LPCTSTR pszFile, BY_HANDLE_FILE_INFORMATION *pInfo) { HRESULT hr; HANDLE hFile = CreateFile(pszFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE != hFile) { if (GetFileInformationByHandle(hFile, pInfo)) { hr = S_OK; } else { hr = HRESULT_FROM_WIN32(GetLastError()); } CloseHandle(hFile); } else { hr = HRESULT_FROM_WIN32(GetLastError()); } return hr; }
// S_OK -> YES, S_FALSE -> NO, FAILED(hr) otherwise
STDAPI IsSameFile(LPCTSTR pszFile1, LPCTSTR pszFile2) { HRESULT hr; // use CRT str cmp semantics as localized strcmp should not be used for the file system
if (0 == StrCmpIC(pszFile1, pszFile2)) { hr = S_OK; // test the names
} else { // very clever here... we can test for alias names that map to the same
// file. for example the short name vs long name of the same file
// the UNC name vs drive letter version of the name
BY_HANDLE_FILE_INFORMATION hfi1; hr = GetFileInfoByHandle(pszFile1, &hfi1); if (SUCCEEDED(hr)) { BY_HANDLE_FILE_INFORMATION hfi2; hr = GetFileInfoByHandle(pszFile2, &hfi2); if (SUCCEEDED(hr)) { if (hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber && hfi1.nFileIndexHigh == hfi2.nFileIndexHigh && hfi1.nFileIndexLow == hfi2.nFileIndexLow) { hr = S_OK; // same!
} else { hr = S_FALSE; // different
} } } } return hr; }
UINT FindInDecoderList(ImageCodecInfo *pici, UINT cDecoders, LPCTSTR pszFile) { LPCTSTR pszExt = PathFindExtension(pszFile); // speed up PathMatchSpec calls
// look at the list of decoders to see if this format is there
for (UINT i = 0; i < cDecoders; i++) { if (PathMatchSpec(pszExt, pici[i].FilenameExtension)) return i; } return (UINT)-1; // not found!
}
HRESULT GetUIObjectFromPath(LPCTSTR pszFile, REFIID riid, void **ppv) { *ppv = NULL; LPITEMIDLIST pidl; HRESULT hr = SHILCreateFromPath(pszFile, &pidl, NULL); if (SUCCEEDED(hr)) { hr = SHGetUIObjectFromFullPIDL(pidl, NULL, riid, ppv); ILFree(pidl); } return hr; }
BOOL FmtSupportsMultiPage(IShellImageData *pData, GUID *pguidFmt) { BOOL bRet = FALSE;
EncoderParameters *pencParams; if (SUCCEEDED(pData->GetEncoderParams(pguidFmt, &pencParams))) { for (UINT i=0;!bRet && i<pencParams->Count;i++) { if (EncoderSaveFlag == pencParams->Parameter[i].Guid) { if (EncoderValueMultiFrame == *((ULONG*)pencParams->Parameter[i].Value)) { bRet = TRUE; } } } CoTaskMemFree(pencParams); } return bRet; }
HRESULT SetWallpaperHelper(LPCWSTR pszPath) { IActiveDesktop* pad; HRESULT hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC, IID_PPV_ARG(IActiveDesktop, &pad)); if (SUCCEEDED(hr)) { IShellImageDataFactory* pidf; hr = CoCreateInstance(CLSID_ShellImageDataFactory, NULL, CLSCTX_INPROC, IID_PPV_ARG(IShellImageDataFactory, &pidf)); if (SUCCEEDED(hr)) { IShellImageData* pid; hr = pidf->CreateImageFromFile(pszPath, &pid); if (SUCCEEDED(hr)) { hr = pid->Decode(SHIMGDEC_DEFAULT, 0,0); if (SUCCEEDED(hr)) { // we are basing this on a best fit to the primary screen
ULONG cxScreen = GetSystemMetrics(SM_CXSCREEN); ULONG cyScreen = GetSystemMetrics(SM_CYSCREEN);
SIZE szImg; pid->GetSize(&szImg);
hr = pad->SetWallpaper(pszPath, 0); if (SUCCEEDED(hr)) { WALLPAPEROPT wpo; wpo.dwSize = sizeof(wpo); wpo.dwStyle = WPSTYLE_CENTER;
// if the image is small on either axis then tile
if (((ULONG)szImg.cx*2 < cxScreen) || ((ULONG)szImg.cy*2 < cyScreen)) { wpo.dwStyle = WPSTYLE_TILE; } // if the image is larger than the screen then stretch
else if ((ULONG)szImg.cx > cxScreen && (ULONG)szImg.cy > cyScreen) { wpo.dwStyle = WPSTYLE_STRETCH; } else { // If the aspect ratio matches the screen then stretch.
// I'm checking is the aspect ratios are *close* to matching.
// Here's the logic behind this:
//
// a / b == c / d
// a * d == c * b
// (a * d) / (c * b) == 1
// 0.75 <= (a * d) / (c * b) < 1.25 <-- our *close* factor
// 3 <= 4 * (a * d) / (c * b) < 5
//
// We do an integer division which will floor the result meaning
// that if the result is 3 or 4 we are inside the rang we want.
DWORD dwRes = (4 * (ULONG)szImg.cx * cyScreen) / (cxScreen * (ULONG)szImg.cy); if (dwRes == 4 || dwRes == 3) wpo.dwStyle = WPSTYLE_STRETCH; } hr = pad->SetWallpaperOptions(&wpo, 0); if (SUCCEEDED(hr)) { hr = pad->ApplyChanges(AD_APPLY_ALL | AD_APPLY_DYNAMICREFRESH); } } } pid->Release(); } pidf->Release(); } pad->Release(); } return hr; }
|