如何以编程方式隐藏桌面图标?

时间:2011-06-19 14:08:43

标签: c# .net icons desktop show-hide

如何使用C#以编程方式显示/隐藏桌面图标?

我正在尝试创建一个使用小部件的替代桌面,我需要隐藏旧图标。

6 个答案:

答案 0 :(得分:20)

您可以使用Windows API执行此操作。以下是C#中的示例代码,用于切换桌面图标。

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

这会向Progman的SHELLDLL_DefView子窗口发送一条消息,告诉它切换它唯一的子项“FolderView”的可见性(通过添加或删除WS_VISIBLE样式)。 “FolderView”是包含图标的实际窗口。

要测试图标是否可见,可以使用GetWindowInfo函数查询WS_VISIBLE样式,如下所示:

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

    }

这是一个调用上面代码的函数,如果窗口可见则返回true,否则返回false。

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

可以在此处找到Windows API代码以及有关窗口样式的更多信息:http://www.pinvoke.net/default.aspx/user32/GetWindowInfo.html

答案 1 :(得分:2)

另一种方法是创建一个单独的桌面并显示它。它没有图标。

Application running itself on a separate desktop

答案 2 :(得分:1)

您可以创建全屏视图应用程序并使其成为最顶层的窗口。

然后让你的应用程序启动Windows。

答案 3 :(得分:1)

您可以在RegEdit中执行此操作 HKEY_CURRENT_USER \ SOFTWARE \微软\的Windows \ CurrentVersion \ Explorer中\高级 将HideIcons更改为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();
        }
    }

使用此处所述的Registry类。

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

答案 4 :(得分:1)

即使当我尝试使用Ondrej Balas的answer时,这已经很老了,但我发现此解决方案的一个问题是,如果使用ToggleDesktop命令显示桌面(也启用了墙纸旋转),则该解决方案将不起作用)。

在这两种情况下,SHELLDLL_DefView窗口(它是ToggleDesktopIcons函数中的toggleDesktopCommand的接收者)不是“程序管理器”窗口的子级,而是“ WorkerW”窗口的子级(请参阅WinApi - How to obtain SHELLDLL_DefViewWindows Desktop ListView Handle

基于这些并基于Ondrej Balas的早期answer,将ToggleDesktopIcons函数更改为:

static void ToggleDesktopIcons()
{
    var toggleDesktopCommand = new IntPtr(0x7402);
    SendMessage(GetDesktopSHELLDLL_DefView(), WM_COMMAND, toggleDesktopCommand, IntPtr.Zero);
}

并添加GetDesktopSHELLDLL_DefView函数:

    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
    [DllImport("user32.dll", SetLastError = false)]
    static extern IntPtr GetDesktopWindow();

    static IntPtr GetDesktopSHELLDLL_DefView()
    {
        var hShellViewWin = IntPtr.Zero;
        var hWorkerW = IntPtr.Zero;

        var hProgman = FindWindow("Progman", "Program Manager");
        var hDesktopWnd = GetDesktopWindow();

        // If the main Program Manager window is found
        if (hProgman != IntPtr.Zero)
        {
            // Get and load the main List view window containing the icons.
            hShellViewWin = FindWindowEx(hProgman, IntPtr.Zero, "SHELLDLL_DefView", null);
            if (hShellViewWin == IntPtr.Zero)
            {
                // When this fails (picture rotation is turned ON, toggledesktop shell cmd used ), then look for the WorkerW windows list to get the
                // correct desktop list handle.
                // As there can be multiple WorkerW windows, iterate through all to get the correct one
                do
                {
                    hWorkerW = FindWindowEx(hDesktopWnd, hWorkerW, "WorkerW", null);
                    hShellViewWin = FindWindowEx(hWorkerW, IntPtr.Zero, "SHELLDLL_DefView", null);
                } while (hShellViewWin == IntPtr.Zero && hWorkerW != IntPtr.Zero);
            }
        }
        return hShellViewWin;
    }

现在,无论桌面切换或墙纸旋转如何,ToggleDesktopIcons都应始终起作用。

作为参考,这是我的切换桌面函数,导致原始ToggleDesktopIcons函数出现问题

static public void ToggleDesktop(object sender, EventArgs e)
        {
            var shellObject = new Shell32.Shell();
            shellObject.ToggleDesktop();
        }

答案 5 :(得分:0)

你这是错误的方式。你真正想要做的是更换外壳。 Windows提供了这个,所以你应该利用它。编写自己的shell来替换资源管理器。