Для чего используется инспектор объектов
Инспектор объектов. Объекты
Закладка Инспектор объектов используется для выполнения общих операций с выбранными объектами конструкции. Он состоит из закладок «Геометрия» и «Группы».
Закладка состоит из двух полей:
Просматривают, выбирают и фильтруют объекты в поле Показать (сверху).
При нажатии на кнопку список объектов фильтруется по группам.
При нажатии на кнопку фильтруется информация о выбранных объектах.
При щелчке правой кнопкой мышки в поле доступа к контекстному меню фильтруют, сортируют, подбирают, ищут и обновляют элементы на закладке Геометрия.
Объекты, принадлежащие этажам, перечислены под созданными этажами. Инспектор позволяет перемещаться по этажам (установить текущий этаж означает работать только с данным этажом) и редактировать параметры этажа (имя, отметку, высоту, цвет и список объектов, принадлежащих этажу).
В Инспекторе объектов с этажами можно выполнять следующие операции:
Просматривают и редактируют свойства выбранного объекта в поле Свойства (внизу).
Поле свойства появляется на большинстве закладок Инспектора объектов. Благодаря ему он представляется и функционирует каждый раз по разному. Оно также группирует атрибуты по категориям таким образом, чтобы они могли быть увеличены и уменьшены.
Создают произвольные иерархии объектов для группы объектов на закладке Группы. Это позволяет быстро просматривать и выбирать пользовательские группы объектов.
Для того, чтобы создать новую группу, необходимо нажать на кнопку (на панели инструментов или в контекстном меню), и тогда программа автоматически создаст группу вне текущего выбора.
Если выбрать разные типы объектов, то будет создано несколько групп. Таким же образом,
если выбрать папку Группы, то только что созданная группа будет автоматически добавлена в эту папку.
Для создания новой папки выбирают группу папок или одну из подпапок и нажимают на кнопку (на панели инструментов или в контекстном меню). Новая папка будет расположена в выбранной пользователем папке.
При выборе группы выбираются все ее элементы.
Предварительный просмотр выбора
Во второй колонке поля Показать находится кнопка, которая указывает на статус просмотра соответствующих групп и папок. Для изменения текущего статуса нажимают на кнопку.
: активная и видимая;
: неактивная и невидимая;
: отображение нескольких объектов в папке; некоторые из них активны, а некоторые нет.
Активные группы можно просмотреть, нажав на следующие кнопки:
– просмотреть активные группы;
– скрыть неактивные группы.
Предварительный просмотр закрывается после нажатия на Выход в графическом редакторе.
Над группами можно выполнять основные логические операции. Кроме того, выбор группы может включать выбор, который был сделан ранее. Если щелкнуть на иконку на панели инструментов Показать (или в контекстном меню), то можно получить доступ к следующим логическим операциям:
Инспектор объектов
Открыть окно «Инспектор объектов» можно двумя способами:
выполнить команду главного меню «Вид > Инспектор объектов» ;
В верхней части окна «Инспектора объектов» расположен раскрывающийся список, содержащий все компоненты проектируемой формы. В список входит также и сама форма. После выбора элемента списка он выделяется на форме. Инспектор объектов отображает свойства выбранного элемента. Если отмечено несколько объектов, то в инспекторе отображаются только общие свойства выбранных объектов.
В инспекторе объектов доступно контекстное меню, содержащее следующие команды:
Справка по данному свойству/событию;
Перейти в инспектор классов.
Для вызова справки также можно выделить необходимое свойство/событие и нажать клавишу F1.
Свойства
Вид редактора значения зависит от типа свойства:
События
Работа с событиями в инспекторе объектов производится почти так же, как и с перечислимыми свойствами. В список допустимых значений для событий входят имена подходящих подпрограмм текущего модуля. Двойной щелчок в правой колонке события приводит к автоматической генерации заготовки подпрограммы-обработчика события.
Если в качестве обработчика события ввести имя несуществующей подпрограммы, то заготовка подпрограммы-обработчика с таким именем также будет вставлена в окно редактирования.
Переименовать обработчик события можно, отредактировав его имя в инспекторе объектов.
Глава 10. Инспектор объектов
В этой главе дается описание окна, в котором производится редактирование размеров окон, шрифт и цвет текста, вид кнопок и т. п., именуемых в среде разработки свойствами объектов.
Инспектор объектов (Inspector Object) предназначен для редактирования свойств объектов (форм и визуальных компонентов) во время разработки программы. С его помощью можно установить начальные свойства объектов и назначить обрабатываемые события. Рассмотрим окно инспектора объектов (рис. 10.1).
Рис. 10.1. Окно инспектора объектов
В верхней части окна инспектора находится поле выбора объектов, в котором отображается название выбранного объекта. Для выбора нового объекта необходимо открыть выпадающий (раскрывающийся) список щелчком левой кнопки мыши по кнопке со стрелкой. Затем выбрать необходимый объект из списка. После этого можно редактировать свойства выбранного объекта. Второй способ выбора объекта заключается в том, что производится щелчок левой кнопкой мыши по самому объекту. Третий способ выбора объекта состоит в том, что производится щелчок левой кнопкой мыши по названию объекта в окне просмотра дерева объектов Object TreeView (рис. 10.2).
Рис. 10.2. Окно просмотра дерева объектов
Ниже поля выбора объектов находятся кнопки вкладок свойств Properties и событий Events. На вкладке Properties располагаются все не скрытые свойства выбранного объекта. Вкладка состоит из двух полей. В левом поле отображается название свойств, а в правом — их значение. Свойства могут быть вложенными с обозначением плюса в квадратике, расположенном левее названия свойства. Для их раскрытия и редактирования необходимо щелкнуть левой кнопкой мыши по этому значку, а затем по самому свойству. Если свойств много, их можно просматривать с помощью кнопки прокрутки. Например, свойство Caption отражает заголовок объекта, а свойство Name — имя объекта.
На вкладке Events располагаются события, на которые может реагировать объект. Она позволяет связать объект с событиями, происходящими в момент выполнения программы. Вкладка Events разделена на два поля. В левом поле отображаются названия событий, на которые может реагировать объект, а в правом — название методов их обработки, или проще, функций-подпрограмм обработки. Для создания обработчика необходимо выполнить двойной щелчок левой кнопкой мыши в правом поле напротив названия выбранного события. При этом появится окно редактора кода, в котором автоматически создастся заготовка текста программы обработчика события. Между фигурными скобками заготовки разработчиком вводится код программы обработки события. В результате при возникновении описанного события для выбранного объекта будет выполняться данная программа. Например, событие OnClick означает щелчок левой кнопкой мыши по объекту.
Теперь запустите программу, выполнив команду Run из главного меню или из панели быстрых кнопок или нажав клавишу на клавиатуре. После компиляции программа запустится и появится окно, подобное приведенному на рис. 10.3.
Рис. 10.3. Окно программы
Щелкните левой кнопкой мыши на кнопке Выход, и приложение закроется. Программа работает и уже выполняет команды, пусть даже такие простые. Если в программе имеются ошибки и она не будет закрываться, выполните команду Program reset из главного меню или нажмите комбинацию клавиш + на клавиатуре. После чего проверьте программу и, устранив ошибки, запустите снова.
Рис. 10.4. Окно контекстного меню команд
Для доступа к дополнительным командам и настройкам инспектора объектов необходимо нажать правую кнопку мыши на окне инспектора. При этом на экране появится окно контекстного меню команд (рис.10.4).
В этом окне содержатся команды просмотра View свойств и событий по группам размещения (упорядочивания) Arrange записей полей по категории или имени, размещения окна поверх всех других окон Stay on Top, скрытия окна Hide, вызова справки Help, изменения настроек Properties и пр. После щелчка левой кнопкой мыши по команде настроек Properties откроется окно настроек инспектора объектов (рис. Ю.5). Это же окно можно открыть, вызвав команду главного меню Tools Environment Options и затем открыв вкладку Object Inspector.
В данном окне можно настроить цвета записей свойств и событий на полях инспектора объектов, а также осуществить выбор Options отображения некоторых свойств и событий, в том числе и тех, на которые имеются ссылки References.
При изучении визуальных компонентов и разборе новых примеров программ мы еще не раз вернемся к инспектору объектов. А пока для закрепления материала на практике самостоятельно попробуйте изменить некоторые свойства формы и кнопки и посмотрите, что при этом получается при выполнении программы.
Рис. 10.5. Окно настроек инспектора объектов
Инспектор объектов (Object Inspector)
Этот инструмент представляет собой отдельное окно, где можно в период проектирования программы устанавливать значения свойств и событий объектов (Properties & Events). Информация в Инспекторе объектов меняется в зависимости от компонента, выбранного на форме. Его вид и поведение можно менять с помощью Инспектора объектов.
Существует несколько типов свойств в зависимости от их «природы».
Вложенные свойства вида «множество» обычно имеют значения типа bool. Наиболее распространенным примером такого свойства является свойство Style с вложенным множеством булевых значений. Комбинированные значения отображаются в Инспекторе объектов как коллекция некоторых величин, каждый со своим типом данных (рис. 11).
Рис. 11. Отображение комбинированных значений вложенных свойств
Некоторые свойства, например, Font, для изменения своих значений имеют возможность вызвать диалоговое окно. Для этого достаточно щелкнуть по маленькой кнопке с тремя точками в правой части строки Инспектора объектов, показывающей данное свойство.
CBuilder позволяет легко манипулировать свойствами компонент как в режиме проектирования (design time), так и в режиме выполнения программы (run time).
В режиме проектирования манипулирование свойствами осуществляется с помощью Дизайнера форм или на страничке Properties Инспектора объектов.
Например, для того, чтобы изменить свойства Height (высоту) и Width (ширину) кнопки, достаточно «зацепить» мышкой за любой ее угол и раздвинуть до нужного представления. Того же результата можно добиться, просто подставив новые значения свойств Height и Width в окне Инспектора объектов.
Вышеприведенная строка устанавливает ширину компонента равной значению 35. Если свойство Width компонента еще не было равно 35 к моменту выполнения данной строки программы, то компонент визуально изменит свою ширину.
Если изменить свойства Width и Height компонента Button, то кнопка соответствующим образом изменит свои ширину и высоту.
Можно ввести элементы в список компонента ComboBox как в режиме проектирования, так и при выполнении программы. При этом в режиме проектирования можно просто ввести нужные элементы в список Items, щелкнув маленькую кнопку с тремя точками в правой части строки Инспектора Объектов, показывающей данное свойство.
Появится диалоговое окно текстового редактора (String List Editor), в котором и вводятся элементы:
7.2Формы, модули и метод разработки «Two-Way Tools»
При создании новой формы генерируется заготовка модуля.
Такая синхронизация и делает CBuilder two-way-инструментом, обеспечивая полное соответствие между кодом и визуальным представлением. Например, предположим, что добавляется описание поведения формы (соответствующий обработчик событий), чтобы показывать окно сообщения по нажатию кнопки. Такое описание появляется, если дважды щелкнуть мышкой непосредственно на объект Button в форме или на событие OnClick на странице Events в Инспекторе объектов. В любом случае CBuilder в файле .cpp создаст заголовок метода, куда можно добавить код.
void __fastcall TPr_Form::Button5Click(TObject *Sender)
Cоздавая этот код, CBuilder автоматически корректирует описание объекта TPr_Form, добавляя заголовок процедурыButton5Click в файл .h.
class TPr_Form : public TForm
void __fastcall Button1Click(TObject *Sender);
void __fastcall FormShow(TObject *Sender);
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall Button2Click(TObject *Sender);
void __fastcall Button3Click(TObject *Sender);
void __fastcall Button4Click(TObject *Sender);
void __fastcall Button5Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TPr_Form(TComponent* Owner);
Чтобы отобразить неактивную форму, следует использовать метод ShowModal. Этот метод отображает форму и делает ее модальной, что позволяет работать с элементами управления на этой форме. При закрытии формы, активизированной с помощью метода ShowModal,свойство формы ModalResult должно получить значение из следующего набора: mrNone, mrOK, mrCancel, mrYes, mrNo. При этом форма закрывается, и значение ModalResult передается как результат метода ShowModal.
Для закрытия формы можно также использовать метод Close.
Событие OnActivate происходит, когда форма становится активной.
Прежде чем сослаться на свойство или на метод формы из метода другой формы (в предположении, что обе формы принадлежат одному проекту), необходимо выполнить пункт меню File, Include Unit Hdr (это приводит к добавлению в файл .h директив #include).
Палитра компонент
Поскольку в CBuilder программа строится визуальным образом, то все компоненты имеют свои пиктограммы, когда они размещаются на поле формы, для того, чтобы можно было ими соответствующим образом оперировать. Но у работающей программы видимыми остаются только визуальные компоненты.
Перечислим основные компоненты страницы Standardидадим некоторые пояснения.
TMainMenuпозволяет поместить главное меню в программу. Создание меню включает три шага:
· Помещение TMainMenu на форму.
· Вызов Дизайнера меню через свойство Items в Инспекторе объектов.
· Определение пунктов меню в Дизайнере меню.
Работа с Дизайнером меню.
Страница Events при работе с Дизайнером меню
TLabelслужит для отображения текста на экране. Текст задается в качестве значения свойства Caption. Для изменения шрифта и цвета текста существует свойство Font.
TEdit— поле ввода. Эта компонента может быть использована для отображения короткого фрагмента текста и позволяет пользователю вводить текст (он представляет собой значение свойства Text) во время выполнения программы.
TButton(обычная кнопка) позволяет выполнить какие-либо действия при нажатии кнопки во время выполнения программы. Поместив объект типа TButton на форму, по двойному щелчку можно создать заготовку обработчика события нажатия кнопки. Далее нужно заполнить заготовку кодом (подчеркнуто то, что нужно написать вручную):
void __fastcall TPr_Form::Button2Click(TObject *Sender)
Инспектор объектов и метаданные
Мотивация и постановка задачи
При попытке сформулировать требования к инспектору объектов у меня получился такой список:
Может показаться, что это завышенный набор требований, но, тем не менее, все перечисленные пункты были не придуманы, а продиктованы той реальной необходимостью, которую мне пришлось учитывать в одном из выполняемых мною проектов.
Как видно из перечисленных выше требований, объекты должны обладать существенно большим набором атрибутов, чем это требуется нам, программистам, для работы с объектами внутри программного кода. Для обозначения этой дополнительной информации будем использовать термин «метаданные» или «атрибуты». Приставка «мета» подчеркивает, что это данные, описывающие другие данные, то есть, «данные о данных». Именно такие термины используются в языке C#. Примером метаданных является информация RTTI, которую формирует компилятор Delphi. Очевидно также, что метаданные, формируемые Delphi недостаточны для удовлетворения всех поставленных требований, а такая возможность, как описание своих атрибутов (доступная в C#), в Delphi отсутствует. Кроме того, нужно удовлетворить указанному выше требованию о том, что инспектор должен работать и с такими объектами, которые не были спроектированы в расчете на инспекцию.
При анализе поставленных требований я выделил четыре основные задачи, необходимые для создания инспектора. Каждой из этих задач посвящен в статье свой раздел:
Метаданные
Можно придумать, вероятно, много различных способов организации метаданных. Например, метаданные объектов различных типов можно описывать в отдельном файле (или файлах) в каком-либо формате, например, как текст на языке XML. Структура метаданных может быть в этом случае сколь угодно сложной и содержать такие крупные разделы, как категория пользователя или локализация. Файлы метаданных можно распространять вместе с программой или внести их в ресурсы, размещаемые в самой программе или в DLL. Для доступа к метаданным потребуется некоторого рода база или список метаданных, индексируемых именем типа, а также XML-парсер для разбора текста.
Не вдаваясь пока в подробности, опишем, в целом, назначение методов класса.
Все остальные функции реализуют различные вспомогательные преобразования, которые служат для преобразования значений свойств в строковый вид для отображения в инспекторе и, наоборот, преобразования строковых значений, измененных в инспекторе, к реальным типам свойств. Методы класса не являются абстрактными, а реализуют свою функциональность для некоторого общего случая (по умолчанию), например, в качестве имени объекта возвращается пустая строка, а преобразование из целого в строку выполняется стандартной функцией IntToStr. Это позволяет переопределять в наследуемых классах только некоторые, действительно нужные, методы.
Поле Kind может принимать (в данной версии инспектора) следующие значения:
pkText значение свойства отображается как текст, доступный для редактирования, pkDropDownList значение свойства доступно для выбора из списка возможных значений, pkDialog значения свойства редактируются специализированным диалогом-мастером, pkFolder фиктивное свойство, не имеющее значения, но позволяющее выстроить иерархический список дочерних подсвойств, pkReadOnlyText аналогично pkText, но доступно только для чтения, pkImmediateText аналогично pkText, но изменение значения свойства фиксируются немедленно при любом изменении текста, pkBoolean свойство отображается как CheckBox, pkTextList подобно pkDropDownList, но значение свойства можно редактировать, то есть, диапазон значений не ограничен списком, pkSet свойство-множество, отображается как родительское для вложенного списка элементов множества, каждый из которых представляется как логическое значение, pkColor свойство для выбора цвета из заданного списка, pkColorRGB подобно предыдущему, но цвет задается и редактируется в виде R.G.B и имеется возможность выбора цвета с помощью стандартного Windows-диалога, pkFloat свойство для отображения вещественного числа. Используется совместно с полем FloatFormat дескриптора метаданных, pkFloat подобно pkText, но содержит также кнопку диалога, что позволяет ввести значение не только напрямую, но также и с помощью специализированного диалога.
Для иллюстрации всего сказанного приведем конкретный пример. Для простоты предположим, что мы будем инспектировать объекты всем известного типа TLabel. Причем, будем считать, что пользователю доступны для инспекции только свойства Caption, Font, Color, а также координаты и размеры. Класс метаданных для TLabel будет, в данном случае, таким:
Поскольку в предложенном описании даны ссылки на другие метаклассы, то продолжим пример и предоставим их реализацию.
Метакласс TGsvBounds_INFO перегружает два метода базового класса.
TypeInfo возвращает указатель на метаданные всего класса в целом. Это позволяет задать атрибуты свойства в одном метаклассе и ссылаться на них из множества других метаклассов. Метод возвращает указатель на константную запись, в которой мы задаем название, вид поля и справочную информацию о свойстве, ChildrenInfo описывает координаты верхнего левого угла прямоугольника и его размеры, ссылаясь на соответствующие published-свойства компонента.
Метакласс для шрифта будет задавать имя шрифта, его размер, стиль и цвет:
Класс TFont_INFO порожден от класса TGsvObjectInspectorTypeFontInfo, в котором переопределены методы ShowDialog и ObjectToString. Метод ShowDialog вызывает стандартный Windows-диалог выбора шрифта, а метод ObjectToString выводит в качестве значения свойства Font строку, включающую имя шрифта и его размер. Свойства стиля и цвета заданы собственными метаклассами:
Вот каким получится вид инспектора при инспектировании объекта типа TLabel для определенных нами метаданных:
Может показаться, что нам потребовалось довольно много описаний, но нужно учесть, что все определенные выше метаклассы могут быть использованы в большом числе других классов, создавая, таким образом, дерево классов метаданных. Например, если бы мы захотели теперь создать метаданные для TButton, то нам потребовалось определить всего один метакласс TButton_INFO.
Процедура GsvRegisterTypeInfo регистрирует метакласс в реестре метаданных. Регистрируемый метакласс передается по ссылке на класс, которая определяется как:
Вторая процедура подобна первой, но позволяет зарегистрировать сразу несколько метаклассов, например:
Удобнее всего регистрировать метаклассы в секции initialization того программного модуля, в котором они определяются. Третья функция выполняет поиск метакласса в реестре на основе его имени, причем она самостоятельно добавляет к имени суффикс _INFO, например, поиск метакласса по имени инспектируемого типа может выглядеть так:
Реализация реестра метаданных весьма проста:
Фактически, реестр представляет собой объект сортированного списка строк TStringList. Этот объект создается при регистрации первого метакласса. Поскольку список сортирован, то поиск в нем выполняется достаточно быстро. Каждый элемент списка содержит имя метакласса и ассоциированную с ним ссылку на метакласс.
Объекты и их заместители
В предыдущем разделе речь шла только о типах инспектируемых объектов. В этом разделе «фокус ввода» перемещается на инспектируемые объекты. Как было сказано, инспектор получает доступ к значениям свойств на основе RTTI. Это означает, что инспектируемые классы должны содержать объявление и реализацию published-свойств. Если мы инспектируем классы визуальных компонентов, порожденных от TComponent, то это условие выполняется автоматически и никаких других усилий нам прикладывать не нужно. Если мы проектируем классы, специально рассчитанные на инспекцию, то мы можем удовлетворить этому требованию, если при объявлении классов укажем директиву <$M+>или будем порождать классы данных от TPersistent. Все свойства, доступные для инспекции, нужно объявить в секции published. В этом случае от нас также не требуется дополнительных усилий. Ситуация осложняется, если нам требуется инспектировать объекты, которые не содержат RTTI или вообще не являются Delphi-объектами. Такое может произойти, например, если:
Менеджер объектов
В задачу менеджера входит организация взаимодействия между визуальным компонентом инспектора и инспектируемым объектом. Может возникнуть вопрос, для чего нужен посредник? Для ответа на этот вопрос можно выделить несколько моментов:
Учитывая эти аргументы, введение посредника становится достаточно обоснованным. Основные задачи менеджера объектов можно сформулировать так:
Используя терминологию паттернов проектирования можно заметить, что менеджер объектов является фасадом, который сводит к минимуму зависимость подсистем инспектора друг от друга и контролирует обмен информации между ними. Далее будет описана только одна реализация менеджера. Конкретика этого менеджера состоит в том, что он использует те метаданные, которые формируются на основе метаклассов, то есть, поддерживает описанный выше способ организации метаданных. Как уже было сказано, можно было бы построить целое семейство различных менеджеров, но в данной версии инспектора я ограничился только одним менеджером.
Можно заметить, что методы менеджера напоминают методы базового класса метаданных TGsvObjectInspectorTypeInfo. И это не случайно, ведь в большинстве случаев менеджер просто перенаправляет запрос соответствующему методу конкретного класса метаданных, то есть, играет роль диспетчера.
HasChildren указывает на наличие у данного свойства вложенных подсвойств, Level уровень свойства в полном дереве свойств, Expanded признак того, что вложенные свойства раскрыты и отображаются, TheObject объект или заместитель, которому принадлежит свойство, NestedObject объект или заместитель вложенного свойства.
Назначение остальных методов:
FillList перенаправляет запрос на заполнение списка перечислимых значений свойства конкретному метаклассу вложенного свойства, ShowDialog перенаправляет запрос на отображение диалога-мастера конкретному метаклассу вложенного свойства, GetStringValue получает значение свойства инспектируемого объекта в строковом виде на основе RTTI. Если свойство имеет вложенный метакласс, то используется его специализация (запрос перенаправляется метаклассу), а иначе выполняется стандартное преобразование, например, из типа Double в тип String, SetStringValue устанавливает значение свойства на основе заданного строкового значения, GetIntegerValue и SetIntegerValue подобны двум предыдущим методам, но специализированы не на строковом, а на целочисленном значении свойства.
Говоря о перенаправлении запросов от менеджера, нельзя не упомянуть о тех методах метаклассов, которых мы только коснулись в первом разделе статьи. В текущей версии инспектора определено несколько вспомогательных специализированных классов, порожденных от базового класса TGsvObjectInspectorTypeInfo. Это:
TGsvObjectInspectorTypeListInfo предоставляет дополнительную функциональность при работе со свойствами, реализующими перечислимые типы. Такие свойства отображаются в инспекторе как выпадающие списки, TGsvObjectInspectorTypeSetInfo помогает описывать свойства-множества, TGsvObjectInspectorTypeFontInfo специализируется на описании свойства типа TFont и инкапсулирует стандартный Windows-диалог выбора шрифта, TGsvObjectInspectorTypeColorRGBInfo специализируется на описании простого свойства типа TColor и инкапсулирует стандартный Windows-диалог выбора цвета.
Все эти классы являются вспомогательными и уменьшают трудозатраты на описание конкретных классов метаданных. Для примера рассмотрим подробнее парочку из указанных вспомогательных классов.
Inspector родительский компонент для формы-диалога, Info метаданные свойства, EditRect прямоугольник, представляющий собой экранные координаты поля редактирования визуального компонента инспектора. Эти координаты можно использовать для того, чтобы расположить диалог, скажем, прямо под значением редактируемого свойства (подобно списку). Конечно, это имеет смысл только для небольших по размеру диалогов.
После того, как мы определили, что инспектируемое свойство действительно является объектом нужного нам типа (в данном случае TFont), мы создаем диалог, инициализируем его данные текущим значением свойства, отображаем диалог и при успешном завершении переносим новое значение свойства в инспектируемый объект.
Визуальный компонент инспектора
В этом разделе мы рассмотрим визуальный компонент инспектора, его основные методы и события, а также некоторые пользовательские аспекты, какие, как хинты. Причем, для простоты опустим аспекты реализации и, кроме того, будем использовать понятия «инспектор» и «визуальный компонент инспектора» как синонимы.
Вначале отметим самые простые свойства и методы:
AutoSelect если AutoSelect установить в True, то при выборе свойства, доступного для редактирования весь его текст будет выделяться, HideReadOnly если установить в True, то инспектор будет скрывать все свойства, доступные только по чтению, Clear вызов этого метода очистит инспектор, что означает отсутствие инспектируемого объекта, SmartInvalidate этот метод позволяет учесть изменение объекта, которое может произойти в то время, когда инспектор отображает данные. В принципе, для обновления можно использовать обычный метод Invalidate, но достоинство SmartInvalidate состоит в том, что инспектор перерисовывается только в том случае, если изменено одно из его отображаемых (видимых) свойств. Метод можно вызывать по таймеру, по событию Application.OnIdle или по какому-либо событию, которое связано с изменением объектов программы, ExpandAll раскрыть все вложенные веточки дерева свойств, CollapseAll свернуть все вложенные веточки.
Цикл событий инспектора при инспектировании начинается с вызова метода NewObject. Это приведет к тому, что инспектор начнет циклически вызывать событие OnEnumProperties. Сигнатура обработчика этого события следующая:
Обработчику передается монотонно увеличивающееся значение Index и, при каждом обращении, обработчик должен вернуть в out-аргументе указатель на метаданные очередного свойства или nil, если все свойства перечислены. Обработчик может выглядеть так:
То есть, запрос на очередное свойство просто передается менеджеру. После того, как все свойства перечислены, инспектор начинает отображение имен свойств и их значений. При этом, для доступа к значениям свойств он вызывает один из обработчиков OnGetStringValue или OnGetIntegerValue в зависимости от того, имеет ли значение свойства текстовое представление или графическое (например, значения boolean-свойств отображаются как CheckBox и не имеют текста). Обработчики этих событий также выглядят очень просто, например:
то есть, просто вывести строку хинта из метаданных в статусную строку или в специальное окно подсказок. Хинт может быть весьма длинным, чтобы ясно изложить подсказку по свойству. Это облегчает работу пользователя при большом числе объектов и их свойств. Если пользователь нажимает клавишу F1, то формируется событие OnHelp, по которому программа вызывает справочную подсистему. Всплывающие подсказки (tooltips) используются в инспекторе для других целей, а именно, для отображения длинных имен и значений, которые не вмещаются в поля инспектора, например:
При отображении всплывающей подсказки редактирования курсор мыши приобретает вид стрелки, направленной вверх, и перемещается на область подсказки, чтобы не мешать редактированию. Контролируются подсказки редактирования свойством LongEditHintTime аналогично LongTextHintTime.
Завершающие штрихи
GsvObjectInspectorGrid.pas визуальный компонент, GsvObjectInspectorTypes.pas все определения, базовый и вспомогательные метаклассы, менеджер, реестр и вспомогательные процедуры.
Весь код достаточно полно комментирован, так что можно всегда обратиться к нему при возникновении вопросов.
Download
Кроме того, к тексту инспектора приложен простенький пример, картинки из которого использованы в статье: модули UnitMainForm (главная форма примера) и UnitInfo (классы метаданных для объектов, инспектируемых в примере). Пример можно компилировать не устанавливая компонент инспектора в палитру компонентов, так как в примере компонент создается явно во время выполнения.