たとえば、HKEY_CLASSES_ROOT\SystemFileAssociations.jpg\Shell\setdesktopwallpaper\Command を見ると、
DelegateExecute メンバー セットがあることがわかります。これは、Windows が指定された DLL で IExecuteCommand インターフェイスを使用しようとすることを意味します。それがMSDNで何をするかを読んで、エクスプローラーをエミュレートしようとして、私はこれを思いつきました。
なぜその Sleep() が必要なのかはわかりませんが、誰かがそれについて詳しく説明していただければ幸いです。
void SetWallpaper(LPCWSTR path)
{
const GUID CLSID_SetWallpaper = { 0xFF609CC7, 0xD34D, 0x4049, { 0xA1, 0xAA, 0x22, 0x93, 0x51, 0x7F, 0xFC, 0xC6 } };
HRESULT hr;
IExecuteCommand *executeCommand = nullptr;
IObjectWithSelection *objectWithSelection = nullptr;
IShellItemArray *shellItemArray = nullptr;
IShellFolder *rootFolder = nullptr;
LPITEMIDLIST idlist = nullptr;
// Initalize COM, probably shouldn't be done in this function
hr = CoInitialize(nullptr);
if (SUCCEEDED(hr))
{
// Get the IExecuteCommand interface of the DLL
hr = CoCreateInstance(CLSID_SetWallpaper, nullptr, CLSCTX_INPROC_SERVER, IID_IExecuteCommand, reinterpret_cast<LPVOID*>(&executeCommand));
// Get the IObjectWithSelection interface
if (SUCCEEDED(hr))
{
hr = executeCommand->QueryInterface(IID_IObjectWithSelection, reinterpret_cast<LPVOID*>(&objectWithSelection));
}
//
if (SUCCEEDED(hr))
{
hr = SHGetDesktopFolder(&rootFolder);
}
if (SUCCEEDED(hr))
{
hr = rootFolder->ParseDisplayName(nullptr, nullptr, (LPWSTR)path, nullptr, &idlist, NULL);
}
if (SUCCEEDED(hr))
{
hr = SHCreateShellItemArrayFromIDLists(1, (LPCITEMIDLIST*)&idlist, &shellItemArray);
}
if (SUCCEEDED(hr))
{
hr = objectWithSelection->SetSelection(shellItemArray);
}
if (SUCCEEDED(hr))
{
hr = executeCommand->Execute();
}
// There is probably some event, or something to wait for here, but we
// need to wait and relinquish control of the CPU, or the wallpaper won't
// change.
Sleep(2000);
// Release interfaces and memory
if (idlist)
{
CoTaskMemFree(idlist);
}
if (executeCommand)
{
executeCommand->Release();
}
if (objectWithSelection)
{
objectWithSelection->Release();
}
if (shellItemArray)
{
shellItemArray->Release();
}
if (rootFolder)
{
rootFolder->Release();
}
CoUninitialize();
}
}
編集:これについてさらに調査を行った後、私自身のために、stobject.dll は実際には IDesktopWallpaper インターフェイスを使用しているだけであることに気付きました。CLSID_DesktopWallpaper の一部です
http://msdn.microsoft.com/en-us/library/windows/desktop/hh706946(v=vs.85).aspx