EnumWindows и EnumChildWindows для обновления моего Treeview - PullRequest
2 голосов
/ 14 мая 2011

Я пытаюсь создать программу, похожую на Winspector Spy. Моя проблема в том, что я хотел бы, чтобы мой Virtual Treeview постоянно обновлялся, то есть обновлял его при создании окна, когда окно разрушается и т. Д. Конечно, все внешние HWND.

Для этого я подумывал написать контейнер данных, содержащий всю информацию Handles +, и сделать EnumWindows и EnumChildWindows в отдельном потоке, где я бы заполнил свой контейнер данных указанной информацией.

Вы бы порекомендовали мне сделать это таким образом, или у вас есть другое решение? Если я делаю это таким образом, то должен ли я запускать свой поток в течение всего времени жизни программы, а затем просто иметь бесконечный цикл в пределах Execute, который очистит мой контейнер данных и заполнит его снова, каждую секунду или что-то еще?

Вот мой контейнер данных:

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.

Ответы [ 2 ]

3 голосов
/ 14 мая 2011

Вы можете зацепить за WH_CBT и проверить HCBT_CREATEWND / HCBT_DESTROYWND

Система вызывает хук WH_CBT процедура до активации, создания, разрушая, минимизируя, максимизируя, перемещение или определение размера окна ...

Также взгляните на Что мне нужно сделать, чтобы моя подключаемая процедура WH_SHELL или WH_CBT получала события от других процессов?

1 голос
/ 14 мая 2011

Это действительно должен быть комментарий, но код не выглядит нормально в комментариях.

В вашем коде есть несколько странностей:

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 или '' в конструкторе, все члены класса автоматически устанавливаются на 0 перед вызовом create.

Наконец, примечание о стиле

Ваш стиль капитализации слишком сложен для чтения и отвлекает от проблемы.
Кроме того, ваши отступы являются непостоянными и необычными.программа.Люди, которые часто используют его для сканирования структуры программы, сильно отвлекаются на необычные отступы.

То же самое с ключевыми словами.В моем коде я знаю, что зарезервированные слова всегда начинаются со строчной буквы, а имена, которые я дал переменным, а подпрограммы всегда начинаются с заглавной буквы.
Это позволяет мне быстро просматривать структуру программы.Зарезервированные слова Разрывает поток сканирования (как при чтении предыдущего предложения) и по этой причине не рекомендуется.

Специально для людей, страдающих аллергией на небрежные отступы и заглавные буквы. Зарезервированные слова.

См .: http://en.wikipedia.org/wiki/Indent_style

Я бы порекомендовалиспользуя тот же стиль, который используется в источнике VCL.Это не мой личный фаворит, но это чистый стиль, которым пользуются многие люди.

Стив МакКоннель: его превосходная книга code complete обозначает страницы с 399 по 452 для макета и стиля, делаяэто самая большая глава книги.

...