【问题标题】:Manipulating the Windows 7 Explorer navigation pane操作 Windows 7 资源管理器导航窗格
【发布时间】:2010-01-24 17:45:35
【问题描述】:

根据我在superuser 收到的答案,很明显我必须将以下内容添加到自定义资源管理器窗口启动器中。我想启动一个根资源管理器视图,只是那个窗口使导航窗格看起来像旧的 Windows XP 文件夹窗格。我已经 wrote a program 将这些文件夹视图的快捷方式放在开始菜单上,因此更改快捷方式以通过启动器运行很简单。

这是 XP 文件夹窗格:

这是 Windows 7 导航窗格:


(来源:280z28.org

【问题讨论】:

  • 也许你可以解释你为什么要这样做。我认为用户会讨厌它。
  • @petebob796:我使用它是为了打开一个特殊的窗口,显示我正在处理的任何项目。该程序是我放置在开始菜单上的一个实用程序,用于“以根视图启动文件夹_____”,所以它不像我在偷偷设置人。

标签: navigation windows-explorer windows-shell


【解决方案1】:

好吧,我没有时间完全完成这段代码(它在 C# 中,我不知道你想要什么,但你没有真正指定)。其基本前提是将 ExplorerBrowser 控件托管在 .NET 表单中(使用您需要获取并添加引用的 WindowsAPICodePack),等待 TreeView 已创建并子类化窗口以允许我们拦截项目插入。

不幸的是,没有什么是简单的,文本不会让您直接了解项目是什么(因为他们没有设置它),您需要做的是从 insertStruct.lParam 获取 PIDL 并解析它变成有意义的东西,可能使用IShellFolder 接口。然后,您可以有选择地删除项目(通过将 0 作为 m.Result 返回),您可以拦截您需要的任何其他内容。你会认为会有一个简单的解决方案,但我猜你的运气不在 ;) 希望它会有所帮助。

另一种方法可能是类似的(直接主机资源管理器),但使用类似detours 的东西来挂钩注册表功能并有选择地更改资源管理器控件获取的视图,从而允许某些注册表调整工作。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.WindowsAPICodePack.Shell;
using System.Runtime.InteropServices;

namespace MyExplorer
{
    public partial class Form1 : Form
    {
        const int WH_CALLWNDPROC = 4;        
        const int WM_CREATE = 1;

        public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn,
        IntPtr hInstance, int threadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnhookWindowsHookEx(IntPtr hHook);

        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        public static extern int CallNextHookEx(IntPtr hHook, int nCode,
        IntPtr wParam, IntPtr lParam);

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

        IntPtr m_hHook;
        HookProc HookDelegate;

        struct WindowHookStruct
        {            
            public IntPtr lParam;
            public IntPtr wParam;
            public uint   message;
            public IntPtr hwnd;
        }

        public class SubclassTreeView : NativeWindow
        {           
            const int TV_FIRST = 0x1100;
            //const int TVM_INSERTITEMA = (TV_FIRST + 0);
            const int TVM_INSERTITEMW = (TV_FIRST + 50);

            struct TVINSERTSTRUCTW 
            {
               public IntPtr hParent;
               public IntPtr hInsertAfter;    
               /* TVITEMW */
               public uint mask;
               public IntPtr hItem;
               public uint state;
               public uint stateMask;
               public IntPtr pszText;
               public int cchTextMax;
               public int iImage;
               public int iSelectedImage;
               public int cChildren;
               public IntPtr lParam;
            }

            int count = 0;

            protected override void WndProc(ref Message m)
            {                
                bool bHandled = false;                             

                switch (m.Msg)
                {
                    case TVM_INSERTITEMW:                        
                        TVINSERTSTRUCTW insertStruct = (TVINSERTSTRUCTW)Marshal.PtrToStructure(m.LParam, typeof(TVINSERTSTRUCTW));

                        /* Change text to prove a point */
                        string name = String.Format("{0:X} {1} Hello", insertStruct.hParent.ToInt64(), count++);
                        insertStruct.pszText = Marshal.StringToBSTR(name);
                        insertStruct.cchTextMax = name.Length+1;
                        Marshal.StructureToPtr(insertStruct, m.LParam, false);                        

                        /* insertStruct.lParam is a pointer to a IDL, 
                           use IShellFolder::GetDisplayNameOf to pull out a sensible 
                           name to work out what to hide */
                        /* Uncomment this code to delete the entry */
                        //bHandled = true;
                        //m.Result = IntPtr.Zero;                                                  
                        break;
                }

                if (!bHandled)
                {
                    base.WndProc(ref m);
                }
            }
        }

        /* Not complete structure, don't need it */
        struct MSG
        {
            public IntPtr hwnd;
            public uint   message;
            public IntPtr wParam;
            public IntPtr lParam;   
        }

        SubclassTreeView sc = null;

        public Form1()
        {
            InitializeComponent();
            HookDelegate = new HookProc(HookWindowProc);
            m_hHook = SetWindowsHookEx(WH_CALLWNDPROC, HookDelegate, (IntPtr)0, AppDomain.GetCurrentThreadId());
        }

        int HookWindowProc(int nCode, IntPtr wParam, IntPtr lParam)
        {           
            if (nCode < 0)
            {
                return CallNextHookEx(m_hHook, nCode, wParam, lParam);
            }
            else
            {

                WindowHookStruct hookInfo = (WindowHookStruct)Marshal.PtrToStructure(lParam, typeof(WindowHookStruct));
                StringBuilder sb = new StringBuilder(1024);

                if (hookInfo.message == WM_CREATE)
                {
                    if (GetClassName(hookInfo.hwnd, sb, 1024) > 0)
                    {
                        System.Diagnostics.Debug.WriteLine(sb.ToString());
                        if (sb.ToString() == "SysTreeView32")
                        {
                            sc = new SubclassTreeView();
                            sc.AssignHandle(hookInfo.hwnd);
                            UnhookWindowsHookEx(m_hHook);
                        }
                    }
                }

                return CallNextHookEx(m_hHook, nCode, wParam, lParam);                
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {                        
            explorerBrowser1.Navigate(ShellLink.FromParsingName("C:\\"));
        }
    }
}

【讨论】:

  • 嗨,我已经使用了这段代码,它工作正常。但我如何才能隐藏探索者的不同痛苦。 IE。导航痛苦。它还隐藏了右上角的搜索区域。是否可以显示搜索选项?
【解决方案2】:

如果您可以检索到指向 Explorer 实例的 IShellFolderViewDual2IShellFolderViewDual3 接口的指针,那么 ViewOptions 方法可以让您指定 SFVVO_WIN95CLASSIC

【讨论】:

    【解决方案3】:

    在 Win 7 中无法按照您的要求进行操作,即自定义资源管理器窗口的外观以从导航窗格中删除所有项目(库、收藏夹等),文件夹树视图除外,例如Explorer 的单个实例。正如您可能已经发现的那样,您可以通过在 4 个位置修改注册表来执行此操作,作为系统范围的设置。或者更简单地说,您可以在资源管理器的属性窗口的导航窗格中设置“显示所有文件夹”(如果您对“收藏夹”链接仍然存在感到满意)。但是,这两个都是系统范围的设置,会影响所有资源管理器窗口。

    抱歉,我知道这并不能满足您的需求,但系统范围的设置是您从导航窗格中删除这些项目的唯一选择。 (顺便说一句,你并不孤单 - 有很多人更喜欢 XP Explorer 视图)。

    【讨论】:

    • 我知道这个答案适用于标准 Windows 设置,但您确定它适用于所有 Shell 界面吗?在这一点上,我正在寻找对窗口进行编程操作。 (在某些时候,资源管理器本身必须检查 Windows 设置,这意味着在最坏的情况下,可以通过将其调用挂钩到注册表来操纵它。)
    • 是的,我一直在检查注册表中的任何上帝模式,但没有找到符合这些规范的任何模式。 Win7 的组策略设置尚未完全记录(AFAIK),因此这是我一直在寻找的另一个领域,因为 GP 通常对管理员来说更易于配置。从用户设置配置的角度来看,MSFT 会一起删除这个视图似乎很奇怪。我将继续进行更多搜索,但我不确定结果是否与此视图相同。
    • 我猜答案在 COM 接口的深处。
    • 可能是这样,但这一切似乎都与注册表有关。我讨厌这么说(我真的这么说!),但这看起来不是一个容易获得的可能性。
    猜你喜欢
    • 2011-04-11
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多