我正在尝试制作类似于Winspector Spy的程序。我的问题是我希望我的Virtual Treeview能够随时更新 - 也就是说,在创建窗口时,窗口被破坏时更新它等等。当然,所有外部HWND都是。
为此,我正在考虑编写一个包含所有Handles +信息的数据容器,并在一个单独的Thread中执行EnumWindows和EnumChildWindows,在那里我将使用所述信息填充我的数据容器。
你会建议我这样做,还是你有另一种解决方案?如果我这样做,那么我应该在整个程序生命周期内运行我的线程,然后在Execute
内只有一个无限循环,它将清除我的datacontainer,并再次填充,每秒,或某事?
这是我的数据容器:
unit WindowList;
interface
Uses
Windows, SysUtils, Classes, VirtualTrees, WinHandles, Messages,
Generics.Collections;
type
TWindow = class;
TWindowList = class(TObjectList<TWindow>)
public
constructor Create;
function AddWindow(Wnd : HWND):TWindow;
end;
///////////////////////////////////////
TWindow = class
public
Node : PVirtualNode;
Children : TObjectList<TWindow>;
Handle : HWND;
Icon : HICON;
ClassName : string;
Text : string;
constructor Create(Wnd : HWND);
destructor Destroy;
function AddWindow(Wnd : HWND):TWindow;
end;
implementation
{ TWindowList }
function TWindowList.AddWindow(Wnd: HWND): TWindow;
var
Window : TWindow;
begin
Window := TWindow.Create(Wnd);
Add(Window);
Result := Window;
end;
constructor TWindowList.Create;
begin
inherited Create(True);
end;
{ TWindow }
function TWindow.AddWindow(Wnd: HWND): TWindow;
var
Window : TWindow;
begin
Window := TWindow.Create(Wnd);
Children.Add(Window);
Result := Window;
end;
constructor TWindow.Create(Wnd: HWND);
begin
Handle := Wnd;
if Handle = 0 then Exit;
ClassName := GetClassName(Handle);
Text := GetHandleText(Handle);
Node := Nil;
Children := TObjectList<TWindow>.Create(True);
end;
destructor TWindow.Destroy;
begin
ClassName := '';
Text := '';
Children.Free;
end;
end.
答案 0 :(得分:3)
答案 1 :(得分:1)
这应该是一个评论,但代码在评论中看起来不行。
您的代码中有一些奇怪之处:</ p>
destructor TWindow.Destroy;
begin
ClassName := '';
Text := '';
Children.Free;
end;
不需要在析构函数中清空字符串,但是你需要调用继承的Destroy 将其更改为:
destructor TWindow.Destroy;
begin
Children.Free;
inherited Destroy;
end;
TWindow继承自TObject,因此在此代码中无关紧要,但如果更改继承,则代码将中断,因此永远不要在inherited
中省略destructor
。
在构造函数中,您需要调用继承的构造函数:
改变这个:
constructor TWindow.Create(Wnd: HWND);
begin
Handle := Wnd;
if Handle = 0 then Exit;
ClassName := GetClassName(Handle);
Text := GetHandleText(Handle);
Node := Nil;
Children := TObjectList<TWindow>.Create(True);
end;
对此:
constructor TWindow.Create(Wnd: HWND);
begin
inherited Create;
Handle := Wnd;
if Handle = 0 then Exit;
ClassName := GetClassName(Handle);
Text := GetHandleText(Handle);
Children := TObjectList<TWindow>.Create(True);
end;
因为TWindow继承自TObject,所以你在这里省略了inherited Create
并不重要,但是如果你决定改变代码并继承其他东西,那么你的构造函数就会破坏。
无需在构造函数中为0
,nil
或''
设置任何内容,在调用create之前,所有类成员都会自动设置为0。
最后关于风格的说明
YoUr资本化风格难以阅读并分散注意力。
与关键字相同。在我的代码中,我知道保留字总是以小写字母开头,而我给vars和例程的名字总是以大写字母开头。
这使我能够快速扫描程序的结构
在保留字中使用Capitals打破扫描的FloW(就像读取前一句时一样),因此不建议使用。
尤其适用于对草率压痕过度过敏和使用大写字母的人。保留字。
请参阅:http://en.wikipedia.org/wiki/Indent_style
我建议使用VCL源中使用的相同样式。 这不是我个人的最爱,但它是很多人使用的干净风格。
Steve McConnel他的优秀书籍code complete
表示第399至452页的布局和风格,使其成为本书的最大篇章。