我找到了一些显示/隐藏桌面图标的代码,但是它在此过程中移动了图标。如何编辑代码以不移动图标?

Mil*_*ast 0 desktop icons batch-file

我正在为Rainmeter使用两个批处理文件,一个用于隐藏所有图标,然后启动Rainmeter,另一个用于显示所有图标,然后退出Rainmeter以使我的桌面恢复正常。

我的最终目标是使这两个批处理文件成为任务栏上的按钮,单击这些按钮可以切换桌面的外观。

到目前为止,我只有两个批处理文件,但它们所做的只是显示和隐藏桌面图标。(我在网上找到了代码,因为我自己无法编写代码)

show.bat

REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /V HideIcons /T REG_DWORD /D 0 /F
taskkill /f /im explorer.exe
start explorer.exe
Run Code Online (Sandbox Code Playgroud)

hide.bat

REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /V HideIcons /T REG_DWORD /D 1 /F
taskkill /f /im explorer.exe
start explorer.exe
Run Code Online (Sandbox Code Playgroud)

因此,我发现的代码可以正常工作,但比手动隐藏桌面图标要流畅得多……唯一的问题是,当我运行show.bat时,我的图标又回到了我不希望它们进入的位置。

如何使批处理文件更顺畅地显示/隐藏图标,以及如何不使图标四处移动?

PS:只是想强调一下,我真的不知道我发现的代码是如何工作的,因此您可能必须使用ELI5。

Smi*_*art 5

首先,TLDR:我认为批处理文件中没有您想要的东西,因此我编译了一个小程序,该程序每次运行时都会打开和关闭桌面图标,并且不会影响位置。 https://drive.google.com/open?id=0B3XhtKLdqFaMOUtrLTk2VEQyVWM

这要归功于关于堆栈溢出的另一个答案,但是从您所说的来看,我认为您没有技巧自己使用该答案……所以我为您做到了。

ELI5:

我相信您的图标移动的原因是因为您正在使用taskkill结束explorer.exe。资源管理器是Windows中的程序,可运行您看到的大多数内容,例如启动栏和桌面,以及浏览驱动程序和文件夹时的程序。

所以,

taskkill /f /im explorer.exe
Run Code Online (Sandbox Code Playgroud)

停止explorer.exe停止运行,这就是为什么您运行批处理时看到启动栏瞬间消失的原因。这样停止它,就没有机会保存您的Icon位置,因此它们始终会还原到最后一个已知的位置。

您找到的脚本执行此操作的原因是,停止explorer.exe,然后再次将其备份会刷新您的桌面,这意味着第一行:

REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /V HideIcons /T REG_DWORD /D 1 /F
Run Code Online (Sandbox Code Playgroud)

可以生效。此行将Windows中的设置更改为“隐藏我的桌面图标”

解决方案(种类)我不知道在简单的批处理文件中刷新桌面设置的方法,但是,我确实在用c#编写的堆栈溢出中看到此答案 如何刷新/重新加载桌面

我知道您可能不知道如何使用此答案,所以我为您制作了一个仅用于切换图标的exe文件

https://drive.google.com/open?id=0B3XhtKLdqFaMOUtrLTk2VEQyVWM

每次运行它时,它都称为ToggleIcons.exe,它所做的就是打开或关闭桌面图标。

要使用它,只需将其弹出到与批处理文件相同的文件夹中,然后添加以下行:

ToggleIcons.exe

到您的脚本。

您可以删除现有的3行,因为这基本上完成了所有这3件事。但是,它不会重新启动explorer.exe,这意味着您的图标将不会在任何地方移动

我还为您提供了源代码,因为从陌生人那里获取糖果通常并不理想,因此,如果您不习惯使用它,我不会感到冒犯!:D

以防万一其他答案的链接丢失了,这里是消息来源:

class Program
{
    //Thanks to /sf/ask/1225230261/

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

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    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
    }

    private const int WM_COMMAND = 0x111;

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

    private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern int GetWindowTextLength(IntPtr hWnd);

    [DllImport("user32.dll")]
    private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

    [DllImport("user32.dll", SetLastError = false)]
    static extern IntPtr GetShellWindow();

    public static string GetWindowText(IntPtr hWnd)
    {
        int size = GetWindowTextLength(hWnd);
        if (size++ > 0)
        {
            var builder = new StringBuilder(size);
            GetWindowText(hWnd, builder, builder.Capacity);
            return builder.ToString();
        }

        return String.Empty;
    }

    public static IEnumerable<IntPtr> FindWindowsWithClass(string className)
    {
        IntPtr found = IntPtr.Zero;
        List<IntPtr> windows = new List<IntPtr>();

        EnumWindows(delegate (IntPtr wnd, IntPtr param)
        {
            StringBuilder cl = new StringBuilder(256);
            GetClassName(wnd, cl, cl.Capacity);
            if (cl.ToString() == className && (GetWindowText(wnd) == "" || GetWindowText(wnd) == null))
            {
                windows.Add(wnd);
            }
            return true;
        },
                    IntPtr.Zero);

        return windows;
    }

    static void ToggleDesktopIcons()
    {
        var toggleDesktopCommand = new IntPtr(0x7402);
        IntPtr hWnd = IntPtr.Zero;
        if (Environment.OSVersion.Version.Major < 6 || Environment.OSVersion.Version.Minor < 2) //7 and -
            hWnd = GetWindow(FindWindow("Progman", "Program Manager"), GetWindow_Cmd.GW_CHILD);
        else
        {
            IEnumerable<IntPtr> ptrs = FindWindowsWithClass("WorkerW");
            int i = 0;
            while (hWnd == IntPtr.Zero && i < ptrs.Count())
            {
                hWnd = FindWindowEx(ptrs.ElementAt(i), IntPtr.Zero, "SHELLDLL_DefView", null);
                i++;
            }
        }
        if (hWnd == IntPtr.Zero)
        {
            //"SHELLDLL_DefView" was not found as a child within WorkerW - Lets check the current ShellWindow
            IntPtr desktop = GetShellWindow();
            hWnd = FindWindowEx(desktop, IntPtr.Zero, "SHELLDLL_DefView", null);
        }
        if (hWnd != IntPtr.Zero)
        {
            SendMessage(hWnd, WM_COMMAND, toggleDesktopCommand, IntPtr.Zero);
        }

    }

    static void Main(string[] args)
    {
            ToggleDesktopIcons();
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:进程“ SHELLDLL_DefView”是我们需要发送命令切换图标的地方,这实际上开始了作为progman的孩子的生活。用户激活其他一些功能(不确定哪些功能,但Windows + Tab为其中一项)后,它将父级切换为WorkerW更改此代码以在currentShellWindow中进行检查