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

发布于 2024-11-15 22:14:02 字数 70 浏览 6 评论 0原文

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

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

How can I show/hide the desktop icons programmatically, using C#?

I'm trying to create an alternative desktop, which uses widgets, and I need to hide the old icons.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

ゃ懵逼小萝莉 2024-11-22 22:14:02

您可以使用 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

You can do this using the Windows API. Here is sample code in C# that will toggle desktop icons.

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

This sends a message to the SHELLDLL_DefView child window of Progman, which tells it to toggle visibility (by adding or removing the WS_VISIBLE style) of it's only child, "FolderView". "FolderView" is the actual window that contains the icons.

To test to see if icons are visible or not, you can query for the WS_VISIBLE style by using the GetWindowInfo function, shown below:

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

    }

Here is a function that calls the above code and returns true if the window is visible, false if not.

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

The windows API code along with more information about the window styles can be found here: http://www.pinvoke.net/default.aspx/user32/GetWindowInfo.html

老街孤人 2024-11-22 22:14:02

尽管当我尝试 Ondrej Balas 的答案时,这个问题已经很老了,但我发现这个解决方案的一个问题是它不起作用如果使用 ToggleDesktop 命令显示桌面(如果启用了壁纸旋转)。

在这两种情况下,SHELLDLL_DefView 窗口(ToggleDesktopIcons 函数中的toggleDesktopCommand 的接收者)不是“程序管理器”窗口的子窗口,而是“WorkerW”窗口的子窗口。(请参阅 WinApi - 如何获取SHELLDLL_DefViewWindows 桌面 ListView 句柄

基于这些内容并以 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();
        }

响应 James M,此函数返回当前状态:

bool IconsVisible()
{
    var hWnd = GetDesktopListView();
    var info = new User32.WINDOWINFO(null);
    User32.GetWindowInfo(hWnd, ref info);
    return (info.dwStyle & User32.WindowStyle.WS_VISIBLE) == User32.WindowStyle.WS_VISIBLE;
}

Even though this is quite old when I tried Ondrej Balas's answer, one problem I found with this solution is that it does not work if the ToggleDesktop command is used to show the desktop ( also if wallpaper rotation is enabled ).

In both of these cases the SHELLDLL_DefView window, which is the recipient of the toggleDesktopCommand in the ToggleDesktopIcons function, is not a child of the "Program manager" window but of a 'WorkerW" window. (see WinApi - How to obtain SHELLDLL_DefView and Windows Desktop ListView Handle.

Based on those and building upon Ondrej Balas's earlier answer change the ToggleDesktopIcons function to be :

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

And add a GetDesktopSHELLDLL_DefView function:

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

Now regardless of the desktop toggle or wallpaper rotation the ToggleDesktopIcons should always work.

For reference this is my toggle desktop function which caused the issue with the original ToggleDesktopIcons function

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

In response to James M, this function returns the current state:

bool IconsVisible()
{
    var hWnd = GetDesktopListView();
    var info = new User32.WINDOWINFO(null);
    User32.GetWindowInfo(hWnd, ref info);
    return (info.dwStyle & User32.WindowStyle.WS_VISIBLE) == User32.WindowStyle.WS_VISIBLE;
}
从来不烧饼 2024-11-22 22:14:02

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

应用程序在单独的桌面上自行运行

A different approach is to create a separate desktop and show it instead. It will not have icons.

Application running itself on a separate desktop

玻璃人 2024-11-22 22:14:02

您可以在 RegEdit 中执行此操作
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced
将 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

You can do this in RegEdit
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced
change HideIcons to 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();
        }
    }

Use the Registry class as described here.

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

绿光 2024-11-22 22:14:02

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

然后使您的应用程序随 Windows 一起启动。

You can create a full screen view application and make it the top most window.

Then make your application to be start up with windows.

别靠近我心 2024-11-22 22:14:02

你的处理方式是错误的。你真正想做的是更换外壳。 Windows 提供了此功能,因此您应该充分利用它。编写自己的 shell 来替换 explorer。

You are going about this the wrong way. What you are really trying to do is to replace the shell. Windows provides for this so you should just take advantage of it. Write your own shell to replace explorer.

戴着白色围巾的女孩 2024-11-22 22:14:02

好话题。在不实际创建不同桌面的情况下,将正在运行的应用程序同时最小化会在视觉上令人愉悦。

Nice topic. Without actually creating a different desktop it would be visually pleasant to have the running applications minimized in the same swoop.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文