简体   繁体   English

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

[英]How to hide Desktop icons with Windows API in C++?

The answers I've found link to fHideIcon , but I get a 404 error on Microsoft's page for those links.我找到了指向fHideIcon链接,但我在 Microsoft 的页面上收到了这些链接的 404 错误。

I've also tried:我也试过:

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

But that didn't work.但这没有用。
Does anyone know how to do this?有谁知道如何做到这一点?

The following approach which uses the official shell API is a little bit involved, but works even under Windows 10.以下使用官方 shell API 的方法有点复杂,但即使在 Windows 10 下也能工作。

Steps:脚步:

  1. Get the IFolderView2 interface of the desktop (supported since Windows Vista).获取桌面的IFolderView2界面(从 Windows Vista 开始支持)。
  2. Call IFolderView2::SetCurrentFolderFlags() with FWF_NOICONS for both the dwMask and dwFlags parameters.使用FWF_NOICONSdwMaskdwFlags参数调用IFolderView2::SetCurrentFolderFlags()

The effect of the flag is visible immediately.旗帜的效果立即可见。 There is no need to restart the computer nor "explorer.exe".无需重新启动计算机或“explorer.exe”。 The flag also persists after logoff or reboot.该标志在注销或重新启动后仍然存在。

The tricky thing is step 1).棘手的是步骤 1)。 Raymond Chen shows C++ code for that in his article "Manipulating the positions of desktop icons" , specifically in his FindDesktopFolderView() function. Raymond Chen 在他的文章“操作桌面图标的位置”中展示了 C++ 代码,特别是在他的FindDesktopFolderView()函数中。

Here is a full example in form of a console application.这是控制台应用程序形式的完整示例。 It is based on Raymond Chen's code.它基于 Raymond Chen 的代码。 The program toggles the visibility of the desktop icons each time it is run.该程序每次运行时都会切换桌面图标的可见性。

The code has been tested under Windows 10 Version 1803.代码已在 Windows 10 Version 1803 下测试。

"Library" code: “库”代码:

#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 );
}

Example to toggle desktop icons using the above code:使用上述代码切换桌面图标的示例:

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;
}

The third parameter isn't about changing the setting, it's to select the SHGetSetSettings() behavior.第三个参数不是关于更改设置,而是选择SHGetSetSettings()行为。

FALSE will get the value of the current setting and store it in ss , TRUE will set the value of the setting to what is in ss . FALSE将获取当前设置的值并将其存储在ssTRUE将设置的值设置为ss

So basically you have to do ss.fHideIcons = TRUE and then call SHGetSetSettings(&ss, SSF_HIDEICONS, TRUE) to set it.所以基本上你必须做ss.fHideIcons = TRUE然后调用SHGetSetSettings(&ss, SSF_HIDEICONS, TRUE)来设置它。

I know, it's weird, but on the other hand it allows you to change multiple settings simultaneously because SSF_* is a bitmask.我知道,这很奇怪,但另一方面,它允许您同时更改多个设置,因为SSF_*是位掩码。

The following seems to work (adapted from https://stackoverflow.com/a/6403014/5743288 ):以下似乎有效(改编自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);
}

Please note: this approach is not supported by Microsoft and disables right-clicking on ths desktop.请注意:Microsoft 不支持此方法并禁用在桌面上右键单击。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM