А. Григорьев - О чём не пишут в книгах по Delphi

Здесь есть возможность читать онлайн «А. Григорьев - О чём не пишут в книгах по Delphi» — ознакомительный отрывок электронной книги совершенно бесплатно, а после прочтения отрывка купить полную версию. В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Город: СПб, Год выпуска: 2008, ISBN: 2008, Издательство: БХВ-Петербург, Жанр: Программирование, на русском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

О чём не пишут в книгах по Delphi: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «О чём не пишут в книгах по Delphi»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Рассмотрены малоосвещённые вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные механизмы их работы, особенности для протоколов TCP и UDP и др. Большое внимание уделено разбору ситуаций возникновения ошибок и получения неверных результатов в "простом и правильном" коде. Отдельно рассмотрены особенности работы с целыми, вещественными и строковыми типами данных, а также приведены примеры неверных результатов, связанных с ошибками компилятора, VCL и др. Для каждой из таких ситуаций предложены методы решения проблемы. Подробно рассмотрен синтаксический анализ в Delphi на примере арифметических выражений. Многочисленные примеры составлены с учётом различных версий: от Delphi 3 до Delphi 2007. Прилагаемый компакт-диск содержит примеры из книги.
Для программистов

О чём не пишут в книгах по Delphi — читать онлайн ознакомительный отрывок

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «О чём не пишут в книгах по Delphi», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Тем не менее флаг csDestroyingвсе же может помочь нам. Компонент удаляется в одном из трех случаев:

1. Удаляется непосредственно данный компонент.

2. Удаляется владелец компонента.

3. Удаляется родитель компонента.

В первом случае удаление начинается не с удаления окна, а с вызова деструктора компонента, и окно компонент удаляет уже сам, когда флаг csD estroying установлен деструктором. Во втором случае деструктор владельца, прежде чем удалить окно, заботится о том, чтобы компонент получил флаг csDestroying, поэтому даже если владелец является одновременно и родителем, флаг у компонента в момент удаления окна уже будет. И, наконец, остается третья ситуация, в которой флага csDestroyingу компонента может и не быть. Но в любом случае удаление цепочки компонентов начинается с вызова деструктора "главного" из них. По линии владельца флаг csDestroyingпередается, по линии родителя — нет, но самый верхний из цепочки родителей обязательно имеет такой флаг. Соответственно, чтобы определить, удаляется ли окно из-за уничтожения визуального компонента, нужно искать флаг csDestroyingне только у самого компонента, но и у всей цепочки его родителей. Если флаг нигде не найден, значит, удаляется только окно, но не сам компонент.

На главном окне примера ParentWnd есть также кнопка Right Combo, которая создает на форме визуальный компонент типа TRightCombo. Это правильный вариант класса TWrongCombo, в котором деструктор не переопределяется, а обработчик сообщения WM_DESTROYреализован в соответствии с тем, что написано ранее (листинг 3.65).

Листинг 3.65. Обработчик сообщения WM_DESTROYкласса TRightCombo

procedure TRightCombo.WMDestroy(var Msg: TMessage);

var

I: integer;

FinalDestruction: Boolean;

P: TControl;

begin

FinalDestruction := False;

P := Self;

while Assigned(P) do

begin

if csDestroying in F.ComponentState then

begin

FinalDestruction := True;

Break;

end;

P := P.Parent;

end;

if FinalDestruction then

for I := 0 to Items.Count - 1 do

Dispose(PDateTime(Items.Objects[I]));

inherited;

end;

Такой компонент корректно освобождает память при его удалении, но не освобождает ее тогда, когда окно создается заново.

Примечание

Есть еще одна очень распространенная причина получения ошибки "Control has no parent window" при разработке собственных компонентов — попытка обращения к свойствам, требующим наличия окна, до назначения свойства Parent. Например, такая ошибка появилась бы, если бы мы в наших наследниках TComboBoxпопытались при создании добавить элементы, вызвав в конструкторе метод AddItem. Свойство Items.Objectsв случае TComboBoxработает через оконные сообщения CB_GETITEMDATAи CB_SETITEMDATA, при попытке отправить которые будет использовано свойство Handle. Это также приведет к попытке создания окна, которая завершится исключением из-за отсутствия родителя. Другими словами, ошибку мы получим не при удалении компонента, а при его создании. Бороться с этой проблемой можно, выполняя начальную инициализацию тогда, когда родитель уже назначен, например, в перекрытом методе SetParentпосле того, как отработает унаследованный SetParent. Необходимо только помнить, что SetParentможет быть вызван не только при создании компонента и при необходимости позаботиться о том, чтобы инициализация выполнялась только при первом вызове SetParentс аргументом, отличным от nil.

Чтобы убедиться, насколько некорректно реализовано удаление компонентов в VCL, рассмотрим еще один пример (на компакт-диске он называется FrameDel). В этом примере на форму помещается фрейм с одним компонентом типа TComboBox. Код фрейма показан в листинге 3.66.

Листинг 3.66. Код фрейма

type

TFrame1 = class(TFrame)

ComboBox1: TComboBox;

private

{ Private declarations }

public

destructor Destroy; override;

procedure AddComboItem;

end;

destructor TFrame1.Destroy;

var

I: Integer;

begin

for I := 0 to ComboBox1.Items.Count - 1 do

if Assigned(ComboBox1.Items.Objects[I]) then

Dispose(PDateTime(ComboBox1.Items.Objects[I]));

inherited;

end;

procedure TFrame1.AddComboItem;

var

P: PDateTime;

begin

New(P);

P^:= Now;

ComboBox1.Items.AddObject('Item ' + TimeToStr(P^), TObject(P));

end;

На форму в обработчике события OnShowпомещается такой фрейм и вызывается его метод AddComboItem, чтобы в компоненте ComboBox1появился один элемент в списке. Если закрыть такую форму, никаких исключений не возникает, все выглядит нормально. Но при трассировке можно заметить, что цикл внутри деструктора не выполняется ни разу, потому что ComboBox1.Items.Countвозвращает 0. Это происходит потому, что на момент вызова этого деструктора и окно фрейма, и окно ComboBox1уже не существуют, в чем легко убедиться, проверив в деструкторе значение поля ComboBox1.FHandle(до обращения к свойству ComboBox1.Items.Countоно равно нулю). А при обращении к этому свойству происходит попытка создать окно. Так как свойство TComboBox1.Parent в этот момент еще не обнулено, предпринимается попытка создать заново и фрейм тоже, и эта попытка становится успешной. К этому моменту свойство Parentфрейма уже обнулено, но метод TCustomFrame.CreateParamsреализован таким образом, что родителем всех фреймов, для которых родитель не задан явно, становится невидимое окно приложения, которое на этот момент еще не разрушено. Таким образом, окно фрейма и окно компонента TComboBox1успешно создаются заново, и им можно посылать сообщения.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «О чём не пишут в книгах по Delphi»

Представляем Вашему вниманию похожие книги на «О чём не пишут в книгах по Delphi» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «О чём не пишут в книгах по Delphi»

Обсуждение, отзывы о книге «О чём не пишут в книгах по Delphi» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x