2013-07-06 6 views
7

Windows 폴더 옵션에 대한 설정을 구현하는 WPF C# 프로젝트가 있습니다. 그 중 하나는 "두 번 클릭하는 대신 한 번 클릭하여 항목 열기"입니다. 그 문제에 대한 레지스트리 키를 변경하면 솔루션을 찾은 Windows Explorer를 새로 고쳐야합니다. 그러나 바탕 화면은 새로 고치지 않으며 수동으로 새로 고치기 만해도 변경 내용이 적용되지 않습니다. IActiveDesktop :: ApplyChanges 메서드를 사용했지만 작동하지 않았습니다 (또는 실수로). 나는이 코드를 사용했지만, 여전히 내가 변경 한 내용이 적용되지 않습니다 : 여기바탕 화면 새로 고침/새로 고침

SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero); 

내가 승리 탐색기 (마녀 새로 고침에 사용되는 전체 코드는이 사이트에서입니다을) :

[System.Runtime.InteropServices.DllImport("Shell32.dll")] 
    private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2); 

    public static void RefreshWindowsExplorer() 
    { 
     // Refresh the desktop 
     SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero); 

     // Refresh any open explorer windows 
     // based on http://stackoverflow.com/questions/2488727/refresh-windows-explorer-in-win7 
     Guid CLSID_ShellApplication = new Guid("13709620-C279-11CE-A49E-444553540000"); 
     Type shellApplicationType = Type.GetTypeFromCLSID(CLSID_ShellApplication, true); 

     object shellApplication = Activator.CreateInstance(shellApplicationType); 
     object windows = shellApplicationType.InvokeMember("Windows", System.Reflection.BindingFlags.InvokeMethod, null, shellApplication, new object[] { }); 

     Type windowsType = windows.GetType(); 
     object count = windowsType.InvokeMember("Count", System.Reflection.BindingFlags.GetProperty, null, windows, null); 
     for (int i = 0; i < (int)count; i++) 
     { 
      object item = windowsType.InvokeMember("Item", System.Reflection.BindingFlags.InvokeMethod, null, windows, new object[] { i }); 
      Type itemType = item.GetType(); 

      // Only refresh Windows Explorer, without checking for the name this could refresh open IE windows 
      string itemName = (string)itemType.InvokeMember("Name", System.Reflection.BindingFlags.GetProperty, null, item, null); 
      if (itemName == "Windows Explorer") 
      { 
       itemType.InvokeMember("Refresh", System.Reflection.BindingFlags.InvokeMethod, null, item, null); 
      } 
     } 
    } 

Windows 탐색기에서는 작동하지만 데스크톱에서는 작동하지 않습니다. 데스크톱은 탐색기에 따라 다르므로 이상합니다. 변경 사항을 적용하려면 데스크탑을 어떻게 다시 불러 와야합니까?

+0

모든 탐색기 인스턴스를 종료하고 새 탐색기 인스턴스를 만들려고하면 어떻게됩니까? – master131

+0

@ master131 그게 작동하지만 사용자가 모든 탐색기 창을 잃게되므로 옵션이 아닙니다. – SepehrM

+0

가능한 복제본 [바탕 화면 아이콘 표시/숨기기] 설정을 적용하려면 어떻게합니까?] (http://stackoverflow.com/questions/3326062/how-do-i-make-the-show-hide-desktop -icons-setting-take-effect) –

답변

2

모든 답장과 의견을 보내 주셔서 감사합니다. 나는이 문제에 대한 해결 방법을 마침내 찾아 냈습니다. 모든 바탕 화면 아이콘을 숨기고 다시 표시 할 수 있습니다. 이렇게하면 바탕 화면이 다시로드됩니다.

업데이트 : 윈도우 8에서SHELLDLL_DefViewWorkerW 창 중 하나의 자식입니다.

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

지금 우리가 두 번 바탕 화면 아이콘을 전환 할 수 있습니다 : (대신 Progman의)는 그래서 여기에 너무 윈도우 8과 8.1에서 작동 업데이트 된 코드이 다른 사람이 도움이

 ToggleDesktopIcons(); 
     ToggleDesktopIcons(); 

희망 ..

2

해당 설정을 변경하는 코드를 게시했다면 회신하기 전에 다음 제안 사항에 대해 테스트했을 것입니다. 가() 바탕 화면을 포함하여 모든 창을 새로 고쳐 있도록

1) 위의 코드에서 문 if (itemName == "Windows Explorer") 제거 :

는 시도 했습니까?

2) SendMessage WIN32 API를 통해 WM_SETTINGCHANGE를 브로드 캐스팅 하시겠습니까?

[Credit]

3

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

)이 작동하지 않는 경우, 알려

[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]

IActiveDesktop.ApplyChanges. 내려갈 경우 열려있는 모든 탐색기 창을 각각의 위치에 저장하고 탐색기를 종료하고 탐색기가 다시 시작될 때까지 기다린 다음 각 탐색기 창을 다시 열고 위치를 다시 지정할 수 있습니다.

희망이 도움이됩니다.

+0

감사합니다.하지만 불행히도 그들 중 누구도 저를 위해 일하지 않았습니다. 그래서 바탕 화면 아이콘을 숨기고 그 아이콘을 보여줄 수 있다고 생각했습니다. 그건 내가 원하는 것을하고 바탕 화면을 다시로드합니다. – SepehrM

+1

@feedwall 그렇다면 데스크톱 핸들을 가져 와서 {F5} 키를 수동으로 보낼 수 있습니다 ... – SepehrM