2

我正在编写一个小程序,只需单击一两次鼠标即可更改桌面背景..

我知道我可以右键单击任何图像文件并将其设置为桌面背景..

问题正是从那里开始的。我无法在任何 dll 中找到正确的条目,该条目具有“设置为桌面背景”甚至“新桌面背景”条目。

我知道如何在注册表中创建它们,但我不想为此编辑注册表,而是希望在我的小程序中正确设置它,这样只需单击两次,我就可以控制计算机上的所有图像文件将它们显示为桌面背景。这来自任何文件夹甚至任何连接的驱动器,而无需返回个性化菜单。

如果你们中的任何人知道我在哪里可以找到上述上下文菜单字符串的条目,那么我将非常感激。

仅供个人使用,不得出售或赠送。

谢谢克里斯

PS 请原谅我的英语不好,我来自一个非英语的欧洲国家。

4

1 回答 1

0

例如,如果您查看 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

于 2013-08-05T21:28:09.800 回答