根据我在superuser收到的答案,很明显我必须将以下内容添加到自定义资源管理器窗口启动器中。我想启动一个有根的资源管理器视图,并且仅针对该窗口使导航窗格看起来像旧的 Windows XP 文件夹窗格。我已经编写了一个程序来将这些文件夹视图的快捷方式放在“开始”菜单上,因此更改快捷方式以通过启动器运行是微不足道的。
这是 XP 文件夹窗格:
这是 Windows 7 导航窗格:
(来源:280z28.org)
根据我在superuser收到的答案,很明显我必须将以下内容添加到自定义资源管理器窗口启动器中。我想启动一个有根的资源管理器视图,并且仅针对该窗口使导航窗格看起来像旧的 Windows XP 文件夹窗格。我已经编写了一个程序来将这些文件夹视图的快捷方式放在“开始”菜单上,因此更改快捷方式以通过启动器运行是微不足道的。
(来源:280z28.org)
好吧,我没有时间完全完成这段代码(它在 C# 中,我不知道你想要什么,但你没有真正指定)。其基本前提是在 .NET 表单中托管 ExplorerBrowser 控件(使用您需要获取并添加引用的WindowsAPICodePack),等到 TreeView 已创建并子类化窗口以允许我们拦截项目插入。
不幸的是,没有什么是简单的,文本不会让您直接了解该项目是什么(因为他们没有设置它),您需要做的是从中获取 PIDLinsertStruct.lParam
并将其解析为有意义的东西,可能使用IShellFolder
界面。然后,您可以有选择地删除项目(通过返回 0 作为m.Result
),您可以拦截您需要的任何其他内容。你会认为会有一个简单的解决方案,但我猜你的运气不在;)希望它会有所帮助。
另一种方法可能是类似的(直接主机资源管理器),但使用诸如绕道之类的东西来挂钩注册表功能并有选择地更改资源管理器控件获得的视图,从而允许某些注册表调整工作。
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:\\"));
}
}
}
如果您可以检索指向 Explorer 实例IShellFolderViewDual2
或IShellFolderViewDual3
接口的指针,则该ViewOptions
方法允许您指定SFVVO_WIN95CLASSIC
.
在 Win 7 中无法执行您要求的操作,即自定义资源管理器窗口的外观以从导航窗格中删除所有项目(库、收藏夹等),文件夹树视图除外,对于单个实例探险家。正如您可能已经发现的那样,您可以通过在 4 个位置修改注册表来执行此操作,作为系统范围的设置。或者更简单地说,您可以在资源管理器的属性窗口的导航窗格中设置“显示所有文件夹”(如果您对“收藏夹”链接仍然存在感到满意)。但是,这两个都是系统范围的设置,会影响所有资源管理器窗口。
抱歉,我知道这并不能满足您的需求,但系统范围的设置是您从导航窗格中删除这些项目的唯一选择。(顺便说一句,你并不孤单 - 有很多人更喜欢 XP Explorer 视图)。