How to refresh/reload Desktop

前端 未结 2 874
时光说笑
时光说笑 2021-01-04 19:00

I have a WPF C# project in which I\'m implementing settings for Windows folder options. One of them is \"Single-click to open an item\" (instead of double-click). When I cha

相关标签:
2条回答
  • 2021-01-04 19:01

    If you would have posted the code to change that setting, I would have tested it against the following suggestions before replying.

    Have you tried:

    1) Removing the statement if (itemName == "Windows Explorer") from the above code, so it refreshes every window (including the desktop)?

    2) Broadcasting a WM_SETTINGCHANGE via SendMessage WIN32 API?

    private const int HWND_BROADCAST = 0xffff;
    private const int WM_WININICHANGE = 0x001a, WM_SETTINGCHANGE = 0x001a, INI_INTL = 1;
    [DllImport("user32.dll")]
    private static extern int SendMessage(int hWnd, uint wMsg, uint wParam, uint lParam);
    
    SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, INI_INTL);
    

    [Credit]

    3) IActiveDesktop.ApplyChanges

    [ComImport]
    [Guid("F490EB00-1240-11D1-9888-006097DEACF9")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IActiveDesktop
    {
         [PreserveSig]
         int ApplyChanges(AD_Apply dwFlags);
         // [...]
         // Note: There is a lot more to this interface,
         //        please see PInvoke.net link below.
    }
    private const int AD_APPLY_REFRESH = 4;
    
    IActiveDesktop.ApplyChanges(AD_APPLY_REFRESH);
    

    [PInvoke.net - IActiveDesktop]

    If these do not work, let me know. If it comes down to it, it is possible to save all the open explorer windows & their positions, terminate explorer, wait for explorer to restart, re-open each explorer window and re-position them... if that would acceptable.

    Hope this helps.

    0 讨论(0)
  • 2021-01-04 19:14

    Thanks for all your replies and comments. I finally figured out a workaround for this problem. We could just hide all desktop icons and then show them again. This will force the desktop to reload.

    Update: In Window 8, SHELLDLL_DefView is the child of one of WorkerW windows. (instead of Progman) So here is the updated code which works on Windows 8 and 8.1 too:

        [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);
    
    
        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
            {
                var ptrs = FindWindowsWithClass("WorkerW");
                int i = 0;
                while (hWnd == IntPtr.Zero && i < ptrs.Count())
                {
                    hWnd = FindWindowEx(ptrs.ElementAt(i), IntPtr.Zero, "SHELLDLL_DefView", null);
                    i++;
                }
            }
            SendMessage(hWnd, WM_COMMAND, toggleDesktopCommand, IntPtr.Zero);
        }
    

    Now we can just toggle desktop icons twice:

            ToggleDesktopIcons();
            ToggleDesktopIcons();
    

    Hope this helps someone else ...

    0 讨论(0)
提交回复
热议问题