【问题标题】:Can I obtain information about the windows explorer tree (left pane)?我可以获得有关 Windows 资源管理器树(左窗格)的信息吗?
【发布时间】:2014-11-17 16:24:37
【问题描述】:

是否可以获得有关 Windows Explorer 树的信息(当前展开了哪些节点、何时展开节点等)?

【问题讨论】:

  • 两个问题都是。
  • 对于可用的树形视图控制消息,请参阅msdn.microsoft.com/en-us/library/windows/desktop/…
  • 看起来很有希望。谢谢。
  • 我编辑了您的问题以使其更通用,看看您是否同意。我删除了屏幕截图,因为它太大(您需要滚动才能找到 cmets/answers),而且有点多余 - 人们知道什么是树视图控件,他们不需要屏幕截图。语言也是C++吗?这很重要,你应该标记它。

标签: winapi treeview windows-explorer


【解决方案1】:

从 Vista 开始,在资源管理器窗口中可以通过官方方式与树进行通信。这种方式使用 INameSpaceTreeControl 接口。

如果您想从外部应用程序获取 INameSpaceTreeControl,您必须:

1) 获取shell窗口的IDispatch:

var
  ShellWindows: IShellWindows;
  i: Integer;
  Dispatch: IDispatch;
  SL: TStrings;
begin
  OleCheck(CoCreateInstance(CLASS_ShellWindows, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IShellWindows, ShellWindows));
  try
    for i := ShellWindows.Count - 1 downto 0 do
      begin
        Dispatch := ShellWindows.Item(i);
        try
          SL := CreateNodeList(Dispatch);
          try
            Memo1.Lines.Assign(SL);
          finally
            SL.Free;
          end;
          Exit;
        finally
          Dispatch := nil;
        end;
      end;
  finally
    ShellWindows := nil;
  end;
end;

2) 从 IDispatch 查询 IServiceProvider。

3) 从 IServiceProvider 查询 INameSpaceTreeControl。

4) 在此之后,您可以枚举树的元素。我使用了以下算法:

function GetItemName(AShellItem: IShellItem): UnicodeString;
var
  Name: PWideChar;
begin
  OleCheck(AShellItem.GetDisplayName(SIGDN_NORMALDISPLAY, Name));
  try
    Result := Name;
  finally
    CoTaskMemFree(Name);
  end;
end;

function GetLevelSpaces(ALevel: Integer): UnicodeString;
var
  i: Integer;
begin
  Result := '';
  for i := 0 to ALevel - 1 do
    Result := Result + '    ';
end;

function CalcLavel(AShellItem: IShellItem): Integer;
var Parent: IShellItem;
begin
  Result := 0;
  if Succeeded(AShellItem.GetParent(Parent)) then
    try
      Inc(Result);
      Result := Result + CalcLavel(Parent);
    finally
      Parent := nil;
    end;
end;

function GetExpanded(ATree: INameSpaceTreeControl; AItem: IShellItem): WideChar;
var
  State: DWORD;
begin
  OleCheck(ATree.GetItemState(AItem, NSTCIS_EXPANDED, State));
  if State and NSTCIS_EXPANDED <> 0 then Result := '+'
                                    else Result := '-';
end;

function CreateNodeList(ADispatch: IDispatch): TStrings;
var
  ServiceProvider: IServiceProvider;
  Tree: INameSpaceTreeControl;
  L: Integer;
  ShellItem, ShellItem2: IShellItem;
begin
  OleCheck(ADispatch.QueryInterface(IServiceProvider, ServiceProvider));
  try
    OleCheck(ServiceProvider.QueryService(SID_SNavigationPane, INameSpaceTreeControl, Tree));
    try
      Result := TStringList.Create;
      try
        if Succeeded(Tree.GetNextItem(nil, NSTCGNI_CHILD, ShellItem)) then
          repeat
            try
              L := CalcLavel(ShellItem);
              Result.Add(GetLevelSpaces(L - 1) + GetExpanded(Tree, ShellItem) + ' ' + GetItemName(ShellItem));
            finally
              ShellItem2 := ShellItem;
              ShellItem := nil;
            end;
          until Failed(Tree.GetNextItem(ShellItem2, NSTCGNI_NEXTVISIBLE, ShellItem));
      finally
        ShellItem2 := nil;
      end;
    finally
      Tree := nil;
    end;
  finally
    ServiceProvider := nil;
  end;
end;

结果:

如果您想订阅树操作,请使用 INameSpaceTreeControl.TreeAdvise。

【讨论】:

  • 对于托管代码解决方案,您有 SID_SNavigationPane 的 Guid 吗? @丹尼斯·阿尼西莫夫
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-28
  • 2011-03-11
  • 2010-09-24
  • 2016-12-24
相关资源
最近更新 更多