Come hide le icone del desktop in modo programmatico?

Come posso mostrare / hide le icone del desktop in modo programmatico, usando C #?

Sto cercando di creare un desktop alternativo, che utilizza i widget e ho bisogno di hide le vecchie icone.

Puoi farlo usando l’API di Windows. Ecco un codice di esempio in C # che triggers le icone del desktop.

[DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr GetWindow(IntPtr hWnd, GetWindow_Cmd uCmd); enum GetWindow_Cmd : uint { GW_HWNDFIRST = 0, GW_HWNDLAST = 1, GW_HWNDNEXT = 2, GW_HWNDPREV = 3, GW_OWNER = 4, GW_CHILD = 5, GW_ENABLEDPOPUP = 6 } [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); private const int WM_COMMAND = 0x111; static void ToggleDesktopIcons() { var toggleDesktopCommand = new IntPtr(0x7402); IntPtr hWnd = GetWindow(FindWindow("Progman", "Program Manager"), GetWindow_Cmd.GW_CHILD); SendMessage(hWnd, WM_COMMAND, toggleDesktopCommand, IntPtr.Zero); } 

Questo invia un messaggio alla finestra secondaria SHELLDLL_DefView di Progman, che gli dice di triggersre la visibilità (aggiungendo o rimuovendo lo stile WS_VISIBLE) del suo unico figlio, “FolderView”. “FolderView” è la finestra reale che contiene le icone.

Per verificare se le icone sono visibili o meno, puoi eseguire una query per lo stile WS_VISIBLE utilizzando la funzione GetWindowInfo, mostrata di seguito:

  [return: MarshalAs(UnmanagedType.Bool)] [DllImport("user32.dll", SetLastError = true)] private static extern bool GetWindowInfo(IntPtr hwnd, ref WINDOWINFO pwi); [StructLayout(LayoutKind.Sequential)] public struct RECT { private int _Left; private int _Top; private int _Right; private int _Bottom; } [StructLayout(LayoutKind.Sequential)] struct WINDOWINFO { public uint cbSize; public RECT rcWindow; public RECT rcClient; public uint dwStyle; public uint dwExStyle; public uint dwWindowStatus; public uint cxWindowBorders; public uint cyWindowBorders; public ushort atomWindowType; public ushort wCreatorVersion; public WINDOWINFO(Boolean? filler) : this() // Allows automatic initialization of "cbSize" with "new WINDOWINFO(null/true/false)". { cbSize = (UInt32)(Marshal.SizeOf(typeof(WINDOWINFO))); } } 

Ecco una funzione che chiama il codice sopra riportato e restituisce true se la finestra è visibile, false in caso contrario.

  static bool IsVisible() { IntPtr hWnd = GetWindow(GetWindow(FindWindow("Progman", "Program Manager"), GetWindow_Cmd.GW_CHILD), GetWindow_Cmd.GW_CHILD); WINDOWINFO info = new WINDOWINFO(); info.cbSize = (uint)Marshal.SizeOf(info); GetWindowInfo(hWnd, ref info); return (info.dwStyle & 0x10000000) == 0x10000000; } 

Il codice API di Windows e ulteriori informazioni sugli stili di finestra sono disponibili qui: http://www.pinvoke.net/default.aspx/user32/GetWindowInfo.html

Un approccio diverso è quello di creare un desktop separato e mostrarlo invece. Non avrà icone.

Applicazione in esecuzione su un desktop separato

È ansible creare un’applicazione di visualizzazione a schermo intero e renderla la finestra più in alto.

Quindi fai in modo che la tua applicazione sia avviata con Windows.

Puoi farlo in RegEdit HKEY_CURRENT_USER \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Explorer \ Advanced cambia HideIcons a 1

  static void HideIcons() { RegistryKey myKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", true); if (myKey != null) { myKey.SetValue("HideIcons", 1); myKey.Close(); } } 

Utilizzare la class del Registro di sistema come descritto qui.

http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.aspx

C’è un’API ufficiale per fare cose del genere, si chiama l’API della shell. Dovrebbe essere preferibile manipolare il registro e l’approccio FindWindow / SendMessage , entrambe “soluzioni” fragili che tendono a rompere con le versioni future di Windows (per quest’ultimo, questo è già stato confermato dai commentatori).

Passi coinvolti:

  1. Ottieni l’interfaccia IFolderView2 del desktop (supportata da Windows Vista).
  2. Chiama IFolderView2::SetCurrentFolderFlags() con FWF_NOICONS per entrambi i parametri dwMask e dwFlags .

L’effetto della bandiera è immediatamente visibile. Non è necessario riavviare il computer né “explorer.exe”. La bandiera persiste anche dopo la disconnessione o il riavvio.

La cosa complicata è il passaggio 1). Raymond Chen mostra il codice C ++ per questo nel suo articolo “Manipolazione delle posizioni delle icone del desktop” , in particolare nella sua funzione FindDesktopFolderView() .

Ecco un esempio completo di C ++ sotto forma di un’applicazione console. È basato sul codice di Raymond Chen. Il programma alterna la visibilità delle icone del desktop ogni volta che viene eseguito.

Il codice è stato testato in Windows 10 Build 17134.

 #include  // Shell API #include  // CComPtr & Co. #include  #include  #include  // 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( msg ) }; } // RAII wrapper to initialize/uninitialize COM struct CComInit { CComInit() { ThrowIfFailed( ::CoInitialize( nullptr ), "CoInitialize failed" ); } ~CComInit() { ::CoUninitialize(); } }; // Query an interface from the desktop shell view. void FindDesktopFolderView( REFIID riid, void **ppv, std::string const& interfaceName ) { CComPtr spShellWindows; ThrowIfFailed( spShellWindows.CoCreateInstance( CLSID_ShellWindows ), "Failed to create IShellWindows instance" ); CComVariant vtLoc( CSIDL_DESKTOP ); CComVariant vtEmpty; long lhwnd; CComPtr spdisp; ThrowIfFailed( spShellWindows->FindWindowSW( &vtLoc, &vtEmpty, SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp ), "Failed to find desktop window" ); CComQIPtr spProv( spdisp ); if( ! spProv ) ThrowIfFailed( E_NOINTERFACE, "Failed to get IServiceProvider interface for desktop" ); CComPtr spBrowser; ThrowIfFailed( spProv->QueryService( SID_STopLevelBrowser, IID_PPV_ARGS( &spBrowser ) ), "Failed to get IShellBrowser for desktop" ); CComPtr 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 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; } 

Stai andando in questo modo nel modo sbagliato. Quello che stai davvero cercando di fare è sostituire la shell. Windows prevede questo, quindi dovresti semplicemente approfittarne. Scrivi la tua shell per sostituire explorer.