我可以获取有关Windows资源管理器树(左窗格)的信息吗?

时间:2014-11-17 16:24:37

标签: winapi treeview windows-explorer

是否可以获取有关Windows资源管理器树的信息(当前扩展的节点,扩展节点时等)?

enter image description here

1 个答案:

答案 0 :(得分: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;

结果:

Explorer tree

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