Search code examples
delphitreeviewtmemo

Memo lines to TreeView


Good night friends,

I'm currently working on a project that involves enumeration of visible windows and their descendents (also visible).

And I can transfer all nodes of TreeView for a Memo (in text format) one by one, but now I'm trying to do the opposite (of necessity of the project).

Someone could help me with this here in StackOverflow?

Here is all the code that lists the windows on TreeView and after transfers it to one Memo.

    function GetWindowTitle(hwnd: HWND): string; 
    begin 
      SetLength(Result, 255); 
      SetLength(Result, GetWindowText(hwnd, PChar(Result), 255)); 
    end; 

    function GetWindowClass(hwnd: HWND): string; 
    begin 
      SetLength(Result, 255); 
      SetLength(Result, GetClassName(hwnd, PChar(Result), 255)); 
    end; 

    function GetWindowInfo(hwnd: HWND): string; 
    begin 
      Result := GetWindowTitle(hwnd) + ' [' + GetWindowClass(hwnd) + 
        '] (' + {IntToStr}IntToHex(hwnd, 8) + ')'; 
    end; 

    function EnumChildProc(hwnd: HWND; lParam: Integer): BOOL; stdcall; 
    var 
      NewNode, ParentNode: TTreeNode; 
    begin 
      Result := True; 
      ParentNode := TTreeNode(lParam); 

      if IsWindowVisible(hwnd) then 

      NewNode := ParentNode.Owner.AddChild(ParentNode, 
        GetWindowInfo(hwnd)); 
      EnumChildWindows(hwnd, @EnumChildProc, Integer(NewNode)); 
    end; 

    function EnumWindowsProc(hwnd: HWND; lParam: Integer): BOOL; stdcall; 
    var 
      NewNode: TTreeNode; 
    begin 
      Result := True; 
      if IsWindowVisible(hwnd) then 
      NewNode := TTreeView(lParam).Items.Add(nil, GetWindowInfo(hwnd)); 
      EnumChildWindows(hwnd, @EnumChildProc, Integer(NewNode)); 
    end; 

    procedure EnumWindowsTree(Tree: TTreeView); 
    begin 
      EnumWindows(@EnumWindowsProc, Integer(Tree)); 
    end; 

    // Listing all windows in TreeView

    procedure TForm2.Button1Click(Sender: TObject); 
    begin 
    TreeView1.Items.Clear; 
    EnumWindowsTree(TreeView1); 
    end; 

   //Tranfers all nodes of TreeView for a Memo (one by one)

    procedure TForm2.Button3Click(Sender: TObject); 
    var I,P,Cnt : Integer; 
        ParentNode, ChildNode: TTreeNode; 
    begin 
       P   := 65; 
       ParentNode  :=  TreeView1.Items[0]; 
       While ParentNode<>nil do 
       begin 
         if (ParentNode <> nil) then 
         begin 
              Memo1.Lines.Add(ParentNode.Text); 
             Cnt := 1; 
             ChildNode := ParentNode.GetFirstChild; 
             while (ChildNode <> nil) do 
             begin 
               Memo1.Lines.Add(ChildNode.Text); 

               if ChildNode.HasChildren then 
               begin 
                  ParentNode:= ChildNode.GetFirstChild; 
                  break; 
               end; 
               ChildNode := ChildNode.GetNextSibling; 
               Inc(Cnt); 
             end; 
         end; 
         if ChildNode=nil then 
         begin 
           if ParentNode.GetNextSibling<>nil then 
              ParentNode:=ParentNode.GetNextSibling 
           else 
           begin 
              while ParentNode.GetNextSibling=nil do 
              begin 
                 if ParentNode.Parent<>nil then ParentNode:=ParentNode.Parent else break; 
              end; 
              if ParentNode<>nil then ParentNode:=ParentNode.GetNextSibling; 
           end; 
         end; 
         Inc(P); 
       end; 
    end; 

Solution

  • It would better to use inbuilt methods of TreeView contents storing:

    // Tranfers all nodes of TreeView for a Memo (one by one)
    var
      MS: TMemoryStream;
    begin
      MS := TMemoryStream.Create;
      try
        TreeView1.SaveToStream(MS);
        MS.Position := 0;
        Memo1.Lines.LoadFromStream(MS);
      finally
        Ms.Free;
      end;
    end;
    
    // Tranfers all nodes to TreeView from a Memo
    var
      MS: TMemoryStream;
    begin
      MS := TMemoryStream.Create;
      try
        Memo1.Lines.SaveToStream(MS);
        MS.Position := 0;
        TreeView1.LoadFromStream(MS);
      finally
        Ms.Free;
      end;
    end;
    

    Note that unnamed windows break formatting needed for correct restoring, so I've changed string format a bit: '.[' instead of space.

    function GetWindowInfo(hwnd: HWND): string;
    begin
      Result := GetWindowTitle(hwnd) + '.[' + GetWindowClass(hwnd) + '] (' +
      { IntToStr } IntToHex(hwnd, 8) + ')';
    end;