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;
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;