是否有任何WinAPI功能来修改桌面图标大小?

时间:2017-09-02 18:09:31

标签: winapi

也许我没有做好搜索,但找不到任何WinAPI功能来修改桌面图标大小。如果没有,你能建议一种方法来实现吗?

1 个答案:

答案 0 :(得分:5)

获取桌面的IFolderView2界面并调用其SetViewModeAndIconSize()方法更改图标大小。

困难的是如何获取桌面的IFolderView2界面。幸运的是,Raymond Chen来救援。他有一篇关于manipulating the positions of desktop icons的文章,我们只需要FindDesktopFolderView()函数的代码。

我已经修改了他的代码并增加了错误处理。虽然这个问题被标记为" C"我使用C ++来回答它,因为C ++对于COM编程更实用。

首先是必需的包含和一些帮助函数。

#include <ShlObj.h>     // Shell API
#include <atlcomcli.h>  // CComPtr & Co.
#include <string> 
#include <iostream> 
#include <system_error>

// Throw a std::system_error if the HRESULT indicates failure.
template< typename T >
void ThrowIfFailed( HRESULT hr, T&& msg )
{
    if( FAILED( hr ) )
        throw std::system_error{ hr, std::system_category(), std::forward<T>( msg ) };
}

// RAII wrapper to initialize/uninitialize COM
struct CComInit
{
    HRESULT hr = ::CoInitialize( nullptr );
    CComInit() { ThrowIfFailed( hr, "CoInitialize failed" ); }
    ~CComInit() { ::CoUninitialize(); }
};

现在归结为细节, FindDesktopFolderView()

// Query an interface from the desktop shell view.
void FindDesktopFolderView( REFIID riid, void **ppv, std::string const& interfaceName )
{
    CComPtr<IShellWindows> spShellWindows;
    ThrowIfFailed( 
        spShellWindows.CoCreateInstance( CLSID_ShellWindows ),
        "Failed to create IShellWindows instance" );

    CComVariant vtLoc( CSIDL_DESKTOP );
    CComVariant vtEmpty;
    long lhwnd;
    CComPtr<IDispatch> spdisp;
    ThrowIfFailed( 
        spShellWindows->FindWindowSW(
            &vtLoc, &vtEmpty, SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp ),
        "Failed to find desktop window" );

    CComQIPtr<IServiceProvider> spProv( spdisp );
    if( ! spProv )
        ThrowIfFailed( E_NOINTERFACE, "Failed to get IServiceProvider interface for desktop" );

    CComPtr<IShellBrowser> spBrowser;
    ThrowIfFailed( 
        spProv->QueryService( SID_STopLevelBrowser, IID_PPV_ARGS( &spBrowser ) ),
        "Failed to get IShellBrowser for desktop" );

    CComPtr<IShellView> spView;
    ThrowIfFailed( 
        spBrowser->QueryActiveShellView( &spView ),
        "Failed to query IShellView for desktop" );

    ThrowIfFailed( 
        spView->QueryInterface( riid, ppv ),
        "Could not query desktop IShellView for interface " + interfaceName );
}

用法示例:

以下示例将桌面图标大小设置为16,甚至小于通过桌面上下文菜单可以实现的大小。

你也可以享受一些乐趣并将viewMode设置为其他内容,比如FVM_DETAILS,它会将桌面切换到详细信息视图。通过常规用户界面甚至无法做到这一点。

int main()
{
    try
    {
        CComInit coInit;

        CComPtr<IFolderView2> spView;
        FindDesktopFolderView( IID_PPV_ARGS( &spView ), "IFolderView2" );

        FOLDERVIEWMODE viewMode = FVM_AUTO;
        int iconSize = 0;
        ThrowIfFailed( 
            spView->GetViewModeAndIconSize( &viewMode, &iconSize ),
            "GetViewModeAndIconSize failed" );
        std::cout << "Current view mode: " << viewMode << ", icon size: " << iconSize << '\n';

        ThrowIfFailed( 
            spView->SetViewModeAndIconSize( viewMode, 16 ),
            "SetViewModeAndIconSize failed" );

        return 0;
    }
    catch( std::system_error const& e )
    {
        std::cout << "ERROR: " << e.what() << ", error code: " << e.code() << "\n";
        return 1;
    }
}