EnumWindows 和 EnumChildWindows 使我的 Treeview 保持更新
我正在尝试制作一个类似于 Winspector Spy 的程序。我的问题是我希望我的虚拟树视图始终更新 - 也就是说,在创建窗口、销毁窗口等时更新它。当然,所有外部 HWND。
为此,我正在考虑编写一个包含所有句柄+信息的数据容器,并在单独的线程中执行 EnumWindows 和 EnumChildWindows ,在其中我将用所述信息填充我的数据容器。
您会建议我这样做,还是有其他解决方案?如果我这样做,那么我应该让我的线程在整个程序生命周期内运行,然后在执行
中进行无限循环,以清除我的数据容器,并每秒再次填充它,或者什么?
这是我的数据容器:
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.
I am trying to make a program similar to Winspector Spy. My problem is that I would like my Virtual Treeview to be updated at all times - that is, update it when a window is created, when a window is destroyed, etc. Of course, all external HWND's.
For that, I was thinking of writing a data container that contained all the Handles + information, and do the EnumWindows and EnumChildWindows in a seperate Thread, where I would fill my data container with said information.
Would you recommend I do it that way, or do you have another solution? If I do it this way, then should I make my Thread run during the whole Program Lifetime, and then just have an infinite loop within the Execute
that would clear my datacontainer, and fill it again, every second, or something?
Here is my Data Container:
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以挂钩
WH_CBT
并检查HCBT_CREATEWND
/HCBT_DESTROYWND
另请参阅 我需要做什么才能让我的 WH_SHELL 或 WH_CBT 挂钩过程接收来自其他进程的事件?
You could hook for
WH_CBT
and examineHCBT_CREATEWND
/HCBT_DESTROYWND
Also take a look at What do I have to do to make my WH_SHELL or WH_CBT hook procedure receive events from other processes?
这确实应该是一个注释,但是注释中的代码看起来不太好。
您的代码中有一些奇怪的地方:
不需要在析构函数中清空字符串,但您需要调用继承的 Destroy。
将其更改为:
TWindow 继承自 TObject,因此在此代码中无关紧要,但如果更改继承,您的代码将中断,因此切勿在
析构函数inherited
>。在构造函数中,您需要调用继承的构造函数:
将其更改
为:
由于 TWindow 继承自 TObject,因此您在此处省略
inherited Create
并不重要,但如果您决定更改代码并从其他东西继承,那么你的构造函数就会崩溃。无需在构造函数中将任何内容设置为
0
、nil
或''
,在调用 create 之前,所有类成员都会自动设置为 0 。最后是关于风格的注释
您的大写风格也很难阅读并分散对问题的注意力。
而且你的缩进不稳定且不寻常。
缩进对于遵循程序的逻辑很重要。
经常使用它来扫描程序结构的人会因为不寻常的缩进而分心。
与关键字相同。在我的代码中,我知道保留字总是以小写字母开头,而我给变量和例程指定的名称总是以大写字母开头。
这使我能够快速扫描程序的结构。
在保留字中使用大写会破坏扫描流程(就像阅读上一句时一样),因此不建议这样做。
特别是对于那些对草率缩进和在保留字中使用大写字母过敏的人。
请参阅:http://en.wikipedia.org/wiki/Indent_style
我建议使用与 VCL 源代码中使用的相同样式。
这不是我个人最喜欢的,但它是很多人使用的干净风格。
Steve McConnel 他的优秀书
代码完整
在第 399 至 452 页的布局和风格上进行了说明,使其成为本书中最大的一章。This should really be a comment, but the code doesn't look OK in comments.
There are a few oddities in your code:
There's no need to empty strings in a destructor, but you need to call inherited Destroy.
Change it to:
TWindow inherits from TObject, so it doesn't matter in this code, but if you change the inheritance your code will break, so never omit
inherited
in adestructor
.In a constructor you need to call the inherited constructor:
Change this:
To this:
Because TWindow inherits from TObject, it does not matter that you ommited
inherited Create
here, but if you decide to change the code and inherit from something else, than your constructor will break.There's no need to set anything to
0
,nil
or''
in a constructor, all class member are automatically set to 0 before create is called.Finally a note on style
YoUr Capitalization style Is Hard too Read and distracts from the issue.
Also your indentation is inconstant and unusual.
Indentation is important to follow the logic of a program.
People who use it to scan program structure a lot get very distracted by unusual indentation.
Same with the keywords. In my code I know that reserved words always start with a lower case and names I gave to vars and routines always start with a capital.
This enables me to scan the structure of a program quickly.
Use of Capitals In Reserved words Breaks the FloW of scanning (like it does when reading the previous sentence) and is not recommended for that reason.
Especially for people who are allergic to sloppy indentation and Use Of Capitals In reserved words.
See: http://en.wikipedia.org/wiki/Indent_style
I'd recommend using the same style that is used in the VCL source.
It's not my personal favourite, but it is a clean style used by a lot of people.
Steve McConnel his excellent book
code complete
denotes pages 399 to 452 to layout and style, making it the largest chapter of the book.