如何在C++中使用Windows API隐藏桌面图标



我找到的答案链接到fHideIcon,但我在Microsoft的页面上看到了404错误。

我也试过:

SHELLSTATE ss;
SecureZeroMemory(&ss, sizeof(ss));
SHGetSetSettings(&ss, SSF_HIDEICONS, TRUE);

但这并没有奏效
有人知道怎么做吗?

以下使用官方shell API的方法有点涉及,但即使在Windows 10下也能工作。

步骤:

  1. 获取桌面的IFolderView2接口(从Windows Vista开始支持(
  2. 对于dwMaskdwFlags参数,使用FWF_NOICONS调用IFolderView2::SetCurrentFolderFlags()

标志的效果立即可见。无需重新启动计算机或"explorer.exe"。注销或重新启动后,该标志也会持续存在。

棘手的是步骤1(。Raymond Chen在他的文章"操纵桌面图标的位置"中,特别是在他的FindDesktopFolderView()函数中展示了这方面的C++代码。

以下是控制台应用程序形式的完整示例。它是基于陈的代码。程序每次运行时都会切换桌面图标的可见性。

该代码已在Windows 10版本1803下进行了测试。

"库"代码:

#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
{
    CComInit() { ThrowIfFailed( ::CoInitialize( nullptr ), "CoInitialize failed" ); }
    ~CComInit() { ::CoUninitialize(); }
    CComInit( CComInit const& ) = delete;
    CComInit& operator=( CComInit const& ) = delete;
};
// 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 );
}

使用上述代码切换桌面图标的示例:

void ToggleDesktopIcons()
{
    CComPtr<IFolderView2> spView;
    FindDesktopFolderView( IID_PPV_ARGS(&spView), "IFolderView2" );
    DWORD flags = 0;
    ThrowIfFailed( 
        spView->GetCurrentFolderFlags( &flags ), 
        "GetCurrentFolderFlags failed" );
    ThrowIfFailed( 
        spView->SetCurrentFolderFlags( FWF_NOICONS, flags ^ FWF_NOICONS ),
        "SetCurrentFolderFlags failed" );
}
int wmain(int argc, wchar_t **argv)
{
    try
    {
        CComInit init;
        ToggleDesktopIcons();
        std::cout << "Desktop icons have been toggled.n";
    }
    catch( std::system_error const& e )
    {
        std::cout << "ERROR: " << e.what() << ", error code: " << e.code() << "n";
        return 1;
    }
    return 0;
}

第三个参数不是关于更改设置,而是选择SHGetSetSettings()行为。

FALSE将获得当前设置的值并将其存储在ss中,TRUE将设置的值设置为ss中的值。

所以基本上你必须做ss.fHideIcons = TRUE,然后调用SHGetSetSettings(&ss, SSF_HIDEICONS, TRUE)来设置它

我知道,这很奇怪,但另一方面,它允许您同时更改多个设置,因为SSF_*是一个位掩码。

以下内容似乎有效(改编自https://stackoverflow.com/a/6403014/5743288):

#include <windows.h>
int main ()
{
    HWND hProgman = FindWindowW (L"Progman", L"Program Manager");
    HWND hChild = GetWindow (hProgman, GW_CHILD);
    ShowWindow (hChild, SW_HIDE);
    Sleep (2000);
    ShowWindow (hChild, SW_SHOW);
}

请注意:Microsoft不支持这种方法,并且禁止在桌面上右键单击。

最新更新