Can I obtain information about the windows explorer tree (left pane)?

352 Views Asked by At

Is it possible to obtain information about the Windows Explorer tree (what nodes are currently expanded, when a node is expanded etc.)?

enter image description here

1

There are 1 best solutions below

1
On BEST ANSWER

Starting from Vista there is official way to communicate with tree in Explorer window. This way uses INameSpaceTreeControl interface.

If you want to get INameSpaceTreeControl from external app you must:

1) Get IDispatch of shell window:

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) Query IServiceProvider from IDispatch.

3) Query INameSpaceTreeControl from IServiceProvider.

4) After this you can enum elements of tree. I used the following algorithm:

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;

Result:

Explorer tree

If you want to subscribe to tree actions use INameSpaceTreeControl.TreeAdvise.