diff --git a/Chameleon.lpi b/Chameleon.lpi index e9cba0c..c476752 100644 --- a/Chameleon.lpi +++ b/Chameleon.lpi @@ -45,7 +45,7 @@ - + @@ -83,6 +83,11 @@ + + + + + diff --git a/DfmEngine.pas b/DfmEngine.pas index 856c214..35f8ada 100644 --- a/DfmEngine.pas +++ b/DfmEngine.pas @@ -8,13 +8,6 @@ uses Windows, Messages, SysUtils, Classes, Forms, Graphics, Writers; type - PEnumParams = ^TEnumParams; - - TEnumParams = record - List: TList; - ParentWnd: HWND; - end; - TKnownControl = ( kcUnknown, kcButton, kcCheckBox, kcComboBox, kcEdit, kcGroupBox, kcImage, kcLabel, kcListBox, kcListView, @@ -66,7 +59,6 @@ const function BitTest(Value, Mask: integer): boolean; function GetWndText(wnd: HWND): string; -function EnumChildrenProc(wnd: HWND; lp: LPARAM): BOOL; stdcall; procedure WriteBitmapData(dfm1: TDfmWriter; bmp: HBITMAP; BelongsToPicture: boolean; const Name: string); procedure WriteIconData(dfm1: TDfmWriter; icon: HICON; BelongsToPicture: boolean; @@ -74,6 +66,8 @@ procedure WriteIconData(dfm1: TDfmWriter; icon: HICON; BelongsToPicture: boolean implementation +uses WindowEnumerator; + function BitTest(Value, Mask: integer): boolean; begin Result := (Value and Mask) = Mask; @@ -88,16 +82,6 @@ begin GetWindowText(wnd, PChar(Result), len + 1); end; -function EnumChildrenProc(wnd: HWND; lp: LPARAM): BOOL; stdcall; -var - p: PEnumParams; -begin - p := PEnumParams(lp); - if GetParent(wnd) = p^.ParentWnd then - p^.List.Add(Pointer(wnd)); - Result := True; -end; - function GetBorderIconsStr(ABorderIcons: TBorderIcons): string; const biStr: array [TBorderIcon] of string = ( @@ -127,11 +111,9 @@ end; procedure TDfmBuilder.Build(OutStream: TStream; const frmName: string; wnd: HWND); var InStream: TMemoryStream; - childlist: TList; i: integer; style, exstyle: longint; wndX: HWND; - EnumParams: TEnumParams; procedure WriteBorderIcons; var @@ -156,7 +138,6 @@ begin FillChar(Counts, sizeof(Counts), #0); InStream := TMemoryStream.Create; Dfm1 := TDfmWriter.Create(InStream); - childlist := TList.Create; dfm1.WriteLn('object ' + frmName + ': T' + frmName); style := GetWindowLong(wnd, GWL_EXSTYLE); @@ -175,14 +156,7 @@ begin dfm1.WriteIntProp('TextHeight', 13); // write the children - EnumParams.List := childlist; - EnumParams.ParentWnd := wnd; - EnumChildWindows(wnd, @EnumChildrenProc, integer(@EnumParams)); - for i := 0 to childlist.Count - 1 do - begin - wndX := HWND(childlist[i]); - PreHandleCtl(wndX); - end; + EnumerateChildWindows(wnd, Self.PreHandleCtl); dfm1.Ident := 0; dfm1.WriteLn('end'); InStream.Position := 0; @@ -190,29 +164,18 @@ begin ObjectTextToResource(InStream, OutStream); // finalization - childlist.Free; DFM1.Free; end; procedure TDfmBuilder.HandleUnknown(wnd: HWND; style: integer); var class_name: array [0..100] of char; - childlist: TList; - EnumParams: TEnumParams; i: integer; begin // since we don't know what window we're after write the class name GetClassName(wnd, class_name, 100); dfm1.WriteStringProp('Caption', class_name); - childlist := TList.Create; - EnumParams.List := childlist; - EnumParams.ParentWnd := wnd; - EnumChildWindows(wnd, @EnumChildrenProc, integer(@EnumParams)); - for i := 0 to childlist.Count - 1 do - begin - PreHandleCtl(HWND(childlist[i])); - end; - childlist.Free; + EnumerateChildWindows(wnd, Self.PreHandleCtl); end; procedure TDfmBuilder.HandleButton(wnd: HWND; style: integer); diff --git a/WindowEnumerator.pas b/WindowEnumerator.pas new file mode 100644 index 0000000..084e2c6 --- /dev/null +++ b/WindowEnumerator.pas @@ -0,0 +1,66 @@ +unit WindowEnumerator; + +{$mode Delphi} + +interface + +uses + Windows; + +type + TWndConsumer = procedure (wnd: HWND) of object; + +procedure EnumerateChildWindows(wnd: HWND; consumer: TWndConsumer); + +implementation + +type + TWindowEnumerator = class + private + wnd: HWND; + consumer: TWndConsumer; + class function MyEnumChildrenProc(wnd: HWND; lp: LPARAM): BOOL; static; stdcall; + procedure Add(wnd: HWND); + public + constructor Create(wnd: HWND; consumer: TWndConsumer); + procedure Run; + end; + +procedure EnumerateChildWindows(wnd: HWND; consumer: TWndConsumer); +var + enumerator: TWindowEnumerator; +begin + enumerator := TWindowEnumerator.Create(wnd, consumer); + try + enumerator.Run; + finally + enumerator.Free; + end; +end; + +constructor TWindowEnumerator.Create(wnd: HWND; consumer: TWndConsumer); +begin + Self.wnd := wnd; + Self.consumer := consumer; +end; + +procedure TWindowEnumerator.Run; +begin + EnumChildWindows(wnd, @TWindowEnumerator.MyEnumChildrenProc, LPARAM(Self)); +end; + +class function TWindowEnumerator.MyEnumChildrenProc(wnd: HWND; lp: LPARAM): BOOL; static; stdcall; +var + me: TWindowEnumerator; +begin + me := TWindowEnumerator(lp); + me.Add(wnd); + Result := True; +end; + +procedure TWindowEnumerator.Add(wnd: HWND); +begin + consumer(wnd); +end; + +end. diff --git a/frmResults.pas b/frmResults.pas index de2e104..b63a2ca 100644 --- a/frmResults.pas +++ b/frmResults.pas @@ -32,7 +32,7 @@ var implementation -uses DfmEngine, StyleNames; +uses StyleNames, WindowEnumerator; {$R *.lfm} @@ -208,33 +208,44 @@ begin end; end; +type + TTreeNodeChildConsumer = class + private + ParentNode: TTreeNode; + ChildrenRootNode: TTreeNode; + ChildCount: Integer; + Form: TResults; + public + constructor Create(Form: TResults; ParentNode: TTreeNode); + procedure Consume(wnd: HWND); + end; + +constructor TTreeNodeChildConsumer.Create(Form: TResults; ParentNode: TTreeNode); +begin + Self.Form := Form; + Self.ParentNode := ParentNode; + Self.ChildrenRootNode := nil; + Self.ChildCount := 0; +end; + +procedure TTreeNodeChildConsumer.Consume(wnd: HWND); +var + node2: TTreeNode; +begin + if not Assigned(ChildrenRootNode) then + ChildrenRootNode := Form.TreeView1.Items.AddChild(ParentNode, 'Children information'); + Inc(ChildCount); + node2 := Form.TreeView1.Items.AddChild(ChildrenRootNode, 'Child #' + IntToStr(ChildCount)); + Form.GetWinInfo(integer(wnd), node2); +end; + procedure TResults.GetWinInfoChildren(wnd: HWND; ParentNode: TTreeNode); var - i: integer; - node1, node2: TTreeNode; - childlist: TList; - EnumParams: TEnumParams; - class_name: String; + consumer: TTreeNodeChildConsumer; begin - childlist := TList.Create; - - EnumParams.List := childlist; - EnumParams.ParentWnd := wnd; - EnumChildWindows(wnd, @EnumChildrenProc, integer(@EnumParams)); - - with TreeView1.Items do - begin - if childlist.Count > 0 then - begin - node1 := AddChild(ParentNode, 'Children information'); - for i := 1 to childlist.Count do - begin - node2 := AddChild(node1, 'Child #' + IntToStr(i)); - GetWinInfo(integer(childlist[i - 1]), node2); - end; - end; - end; - childlist.Free; + consumer := TTreeNodeChildConsumer.Create(Self, ParentNode); + EnumerateChildWindows(wnd, consumer.Consume); + consumer.Free; end; end.