Close — Процедура Delphi


Содержание

Close — Процедура Delphi

На этом шаге мы перечислим основные события, которые могут быть обработаны формой.

Так как форма (компонент типа TForm ) является базовым интерфейсным элементом для всех программ, создаваемых в среде Delphi , уместно начать знакомство с обработчиков, имеющихся у компонента TForm . Напомним, что их перечень можно увидеть в Инспекторе Объектов на вкладке Events :

Рис.1. Перечень событий, обрабатываемых формой

Перечислим наиболее часто используемые:

  • OnActivate — возникает при активизации формы;
  • OnClose — возникает при закрытии формы;
  • OnCloseQuery — разрешает/отменяет закрытие формы;
  • OnCreate — возникает при создании формы;
  • OnDestroy — возникает при закрытии формы;
  • OnHide — возникает при «скрытии» формы;
  • OnPaint — возникает при необходимости перерисовки формы;
  • OnResize — возникает при изменении размеров формы;
  • OnShow — возникает при отображении формы.

Большинство событий и их обработчиков присущи и другим компонентам, поэтому они рассматриваются в следующих шагах. Здесь мы остановимся на событиях, характерных непосредственно для формы. Отметим, что эти события носят в большинстве своем нотификационный (уведомляющий) характер и имеют тип TNotifyEvent , описанный следующим образом:

но ряд обрабатываемых формой событий требует передачи дополнительной информации. К их числу относятся, например, события OnActivate, OnClose и OnCloseQuery . Нотификационные сообщения не несут в себе никакой информации о самом событии, только содержат указатель на источник события — параметр Sender .

Событие OnActivate

Форма получает событие OnActivate при ее активизации. Активизация формы может произойти при получении ею фокуса, например, когда пользователь нажал кнопку мыши в рабочей области формы. Для дочерних окон MDI-форм (форм, созданных со значением свойства FormStyle , равным fsMDIChild ) событие OnActivate возникает при переключении фокуса на данное окно. Если же происходит переключение фокуса с обычного дочернего окна на MDI-дочернее окно, то это событие получает родительское MDI-окно.

Событие OnActivate носит нотификационный характер.

Событие OnClose

Событие OnClose наступает при закрытии формы. Форма получает это событие перед закрытием формы, которое может наступить либо при вызове метода Close , либо при выборе команды Close из системного меню.

Событие OnClose имеет тип TCloseEvent , описанный следующим образом:

Параметр Action определяет тип закрытия формы и может принимать одно из следующих значений:

Проиллюстрируем использования параметра Action . Создадим новый проект, выполнив File | New | Application . Обработчик события OnClose выглядит следующим образом:

При закрытии формы на экран будет выведено диалоговое окно (рисунок 2):

Рис.2. Диалоговое окно, появляющееся при закрытии приложения

Текст этого примера можно взять здесь.

Событие OnCloseQuery

С помощью этого события можно разрешить или отменить закрытие формы. Это событие может наступить либо при вызове метода Close , либо при выборе команды Close из системного меню. В обработчике этого события можно изменять значение параметра CanClose сообщения OnCloseQuery .

Пример закрытия формы с подтверждением в этом случае может выглядеть следующим образом:

Текст этого примера можно взять здесь.

Таким образом, событие OnCloseQuery имеет тип TCloseQueryEvent , описанный следующим образом:

Событие OnCreate

Это событие возникает при начальном создании формы. В обработчике данного события можно, например, задавать начальные значения свойствам формы и предусматривать другие различные действия, которые должны происходить в момент создания формы. Форма создается при запуске приложения либо при вызове метода Create . Примечание . При создании формы события происходят в следующем порядке:

  • OnCreate;
  • OnShow;
  • OnActivate;
  • OnPaint.

Это событие имеет тип TNotifyEvent .

Таким образом, в обработчике события OnCreate помещаются те действия, которые должны выполниться только один раз при создании формы. Приведем пример обработчика этого события, где задается цвет фона формы, равный системному цвету, определенному в ядре Windows :

Текст этого примера можно взять здесь.

Событие OnDestroy

Событие OnDestroy возникает на финальной стадии закрытия формы и может быть вызвано с помощью методов Destroy или Free либо закрытием главной формы приложения. Это событие имеет тип TNotifyEvent .

Событие OnHide

Событие OnHide возникает при «скрытии» формы, то есть когда ее свойство Visible принимает значение False . Это событие имеет тип TNotifyEvent .

Событие OnPaint

Событие OnPaint возникает при необходимости перерисовки содержимого формы. Например, оно может возникнуть при получении формой фокуса. Обработчик этого события может отображать информацию в рабочей области формы. Сообщение OnPaint имеет тип TNotifyEvent .

В следующем примере показано, как загружать графическое изображение в обработчике события OnPaint :

Текст этого примера можно взять здесь.

Событие OnResize

Событие OnResize возникает при изменении размеров формы во время работы приложения. Обработчик этого события необходим только в том случае, если вы планируете выполнять какие-либо действия при изменении размеров формы. Например, это может быть перемещение интерфейсных элементов или другие действия. Сообщение OnResize имеет тип TNotilyEvent .

Событие OnShow

Событие OnShow возникает, когда форма отображается (то есть когда ее свойство Visible принимает значение True ). Это событие имеет тип TNotifyEvent .

На следующем шаге мы рассмотрим основные события от клавиатуры и мыши.

Процедуры Delphi

В процессе программирования на языке Delphi, как и на любом другом языке программирования, основная задача программиста состоит в том, чтобы разработать процедуры (подпрограммы) для обработки определенных событий. Как только это событие возникло, проводится автозапуск процедуры обработки события (если возникло соответствующее событие, Delphi осуществляет вызов процедуры обработки возникшего события). Именно эту процедуру разработчик программы и должен описать.

Главное отличие процедуры от функции состоит в том, что есть связь между именем функции и значением. Таким образом, возможно использование имени функции в разнообразных выражениях. Организация процедуры Delphi по сути ничем не отличается от организации функции.

Как и для функции, в начале каждой процедуры указывают ее заголовок. Затем называют эту процедуру каким-нибудь именем. После имени в скобках следует перечень параметров, заканчивающийся символом «;» и потом уже описывают разделы констант, типов, переменных и инструкций.

Общий вид процедуры Delphi:

Общий вид процедуры Delphi выглядит следующим образом:

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

Если процедура обладает какими-либо параметрами, то программист их указывает в скобках, сразу после имени процедуры. В конце заголовка процедуры ставится символ «;». В случае, когда в процедуре имеются именованные константы, программист объявляет их в разделеconst.

Далее за этим разделом идет раздел type, использующийся для объявления типов. После располагается раздел var, содержащий все переменные, которые впоследствии программист использует в своей программе. Затем следует раздел инструкций , которые включает в себя исполняемые инструкции данной процедуры.

Примеры процедуры Delphi:

Приведем пример процедуры Delphi, вычисляющей стоимость некоторой покупки:

Урок №9. Создание собственных процедур и функций Delphi

Подпрограммы — процедуры и функции в языке Delphi служат для выполнения специализированных операций. Delphi имеет множество стандартных подпрограмм, но всё равно приходится создавать собственные для выполнения часто повторяющихся операций с данными, которые могут меняться.

Вообще, существует методика программирования «сверху вниз». Методика программирования «сверху вниз» разбивает задачу на несколько более простых, которые оформляются в виде подпрограмм. Те, в свою очередь, при необходимости также делятся до тех пор, пока стоящие перед программистом проблемы не достигнут приемлемого уровня сложности (то есть простоты!). Таким образом, эта методика программирования облегчает написание программ за счёт создания так называемого скелета, состоящего из описателей подпрограмм, которые в дальнейшем наполняются конкретными алгоритмами. Пустое описание подпрограммы иначе называется «заглушкой».

И процедуры , и функции позволяют добиться одинаковых результатов. Но разница всё же есть.

Процедура Delphi просто выполняет требуемые операции, но никаких результатов своих действий не возвращает. Результат — в тех изменениях, которые произошли в программе в процессе выполнения этой процедуры. В частности, процедура может поменять значения переменных, записать новые значения в ячейки компонентов, сделать запись в файл и т.д.

Функция Delphi также позволяет выполнить всё перечисленное, но дополнительно возвращает результат в присвоенном ей самой значении. То есть вызов функции может присутствовать в выражении справа от оператора присваивания. Таким образом, функция — более универсальный объект!

Описание подпрограммы состоит из ключевого слова procedure или function , за которым следует имя подпрограммы со списком параметров, заключённых в скобки. В случае функции далее ставится двоеточие и указывается тип возвращаемого значения. Обычная точка с запятой далее — обязательна! Сам код подпрограммы заключается в «логические скобки» begin/end . Для функции необходимо в коде присвоить переменной с именем функции или специальной зарезервированной переменной Result (предпочтительно) возвращаемое функцией значение. Примеры:

procedure Имя_процедуры( (*параметры*) );

begin
//Код процедуры;
end ;

function Имя_функции( (*параметры*) ): тип_результата;
begin
//Код функции;

Result := результат;
end ;

Описанная таким образом подпрограмма должна быть размещена в основной программе до первого её вызова. Иначе при компиляции получите извещение о том, что «неизвестный идентификатор. » Следить за этим не всегда удобно. Есть выход — разместить только заголовок подпрограммы там, где размещают описания всех данных программы .

Параметры — это список идентификаторов, разделённых запятой, за которым через двоеточие указывается тип. Если списков идентификаторов разных типов несколько, то они разделяются точкой с запятой. Всё, как и в случае обычного описания данных. Это так называемые формальные параметры. При вызове подпрограммы они заменяются на фактические — следующие через запятую данные того же типа, что и формальные.
Параметры в описании подпрограммы могут и отсутствовать , тогда она оперирует данными прямо из основной программы.

Теперь нужно ввести понятие локальных данных. Это данные — переменные, константы, подпрограммы, которые используются и существуют только в момент вызова данной подпрограммы. Они так же должны быть описаны в этой подпрограмме. Место их описания — между заголовком и началом логического блока — ключевым словом begin . Имена локальных данных могут совпадать с именами глобальных . В этом случае используется локальная переменная, причём её изменение не скажется на глобальной с тем же именем.
Совершенно аналогично локальным типам, переменным, константам могут быть введены и локальные процедуры и функции, которые могут быть описаны и использованы только внутри данной подпрограммы.

Теперь пример. Напишем программу суммирования двух чисел. Она будет состоять из Формы, на которой будет кнопка (компонент Button ), по нажатию на которую будет выполняться наша подпрограмма, и двух строк ввода (компоненты Edit ), куда будем вводить операнды. Начнём с процедуры .

var
Form1: TForm1;
A, B, Summa: Integer;
procedure Sum(A, B: Integer);

implementation

procedure TForm1.Button1Click(Sender: TObject);
begin
A:=StrToInt(Edit1.Text);
B:=StrToInt(Edit2.Text);
Sum(A, B);
Caption:=IntToStr(Summa);
end ;

procedure Sum(A, B: Integer);
begin
Summa:=A+B;
end ;

Есть особенности в использовании в качестве параметров больших по объёму структур данных, например, массивов, состоящих из нескольких тысяч (и больше) элементов. При передаче в подпрограмму данных большого объёма могут быть большие расходы ресурсов и времени системы. Поэтому используется передача не самих значений элементов (передача «по значению» , как в предыдущих примерах), а ссылки на имя переменной или константы (передача «по имени» ). Достигается это вставкой перед теми параметрами, которые мы хотим передать по имени, ключевого слова var .

Function Sum(A, B: Integer; var Arr: array [1..1000000] of Integer): Integer;

Eсли взглянуть на описание нашей подпрограммы и описание обработчика нажатия кнопки (это тоже подпрограмма!), который был создан Delphi, то видим, что перед именем обработчика (Button1Click) стоит TForm1 . Как мы знаем, в Delphi точкой разделяется объект и его атрибуты (свойства и методы). Таким образом, Delphi создаёт Button1Click как метод объекта Form1. Причём, буква T перед объектом говорит о том, что Button1Click не просто метод объекта, а метод класса объекта. Не будем этим пока заморачиваться, а просто будем поступать также . Описав свою процедуру или функцию как метод класса TForm1, мы получаем возможность использовать в ней объекты класса без указания его имени, что гораздо удобнее. То есть, если мы используем в нашей подпрограмме какие-либо компоненты, размещённые на Форме (например, Button1), то мы пишем

Button1.W >//Ширина кнопки
а не
Form1.Button1.W >

Также появляется возможность использовать встроенные переменные, такие как параметр Sender . В каждом обработчике этот объект указывает на источник, то есть тот объект, который вызывает данную подпрограмму. Например, в нашей процедуре суммирования Sender = Button1 . Проанализировав эту переменную, можно принять решение о тех или иных действиях.

Описав подпрограмму как метод класса, её описание мы должны поместить туда же, куда их помещает Delphi — в описание класса TForm1. Смотрите сами, где находится описание процедуры Button1Click. Для этого , поставив курсор внутрь подпрограммы Button1Click, нажмите CTRL+Shift и кнопку управления курсором » Вверх » или » Вниз » одновременно. Произойдёт переход к описанию подпрограммы (чтобы вернуться обратно, повторите это действие ещё раз). Ставьте описание своей подпрограммы рядом, с новой строки. Обратите внимание, что TForm1 уже не пишется.

Рекурсия — важное и мощное свойство процедур и функций в Delphi. Рекурсия это возможность подпрограммы в процессе работы обращаться к самой себе. Без использования рекурсии приходилось бы применять циклы, а это усложняет чтение программы. Рекурсивный вызов подпрограммы сразу проясняет смысл происходящего. Естественно, приходится следить за тем, чтобы в подпрограмме обязательно было условие, при выполнении которого дальнейшая рекурсия прекращается, иначе подпрограмма зациклится.

Пример вычисления факториала

Вычисление факториала — классическая в программировании задача на использование рекурсии . Факториал числа N — результат перемножения всех чисел от 1 до N (обозначается N! ):

N! = 1*2* . *(N-1) *N = N* (N-1)!

Создавая программу вычисления факториала числа, мы можем применить и функции, и рекурсию . Можно скачать проект данной программы.

RAD Studio from Embarcadero

пятница, 7 февраля 2014 г.

5. Свойства и методы формы. Лабораторные Delphi, C++ (2)

Приложение, содержащее несколько форм в Delphi и C ++ Builder

Задание характеристик главной формы

Положите на форму из списка Standard набора инструментов Tool Palette две кнопки Button . Кнопкам задайте надписи (свойство Caption ) Форма 2 и Форма 3. Форма примет следующий вид (рис. 1).

Создание дочерних форм

Задание стартовой формы

1 комментарий:

Зачем так сложно? Почему же не «aForm := TForm3.Create(Self);»?

И в немодальную форму стоит добавить подобный обработчик, иначе память течет:

procedure TForm3.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;

Ну и если уж совсем буквоедствовать, то Form2 и Form3 можно перенести в список «Available forms» и создавать их не всегда при запуске приложения, а самостоятельно по требованию.

Close — Процедура Delphi

Я что -то не пойму..
вот для примера сделал простенький проект для теста.
Есть две формы, Form1 и Form2 . В Form2 создаю событие OnCloseQuery и пишу там сообщение ShowMessage(«Close Form2»).
Т.е. И та и другая форма создаются в autocreate.

Далее запускаю проект, — вижу только Form1, как и должно быть, и выхожу из сесии Windows — Logoff. И вылетает Close Form2″, т.е. срабатывает OnCloseQuery второй формы.
Так и должно быть?
D 2009

> [0] Stan (09.04.09 01:11)

вообще OnCloseQuery весьма запутанное событие. я бы использовал простой OnClose, а для закрытия сеанса напрямую бы перехватывал сообщение.

Смущает то, что Form2 ни разу не открывался.
При закрытии программы, OnCloseQuery этой формы не отрабатывает. А при LogOff или рестарте отрабатывает.. Проверил с 5 формами, то же самое, перечисляются все невидимые формы, и вызывается OnCloseQuery у каждой. при обычном закрытии, все ок..
разве так должно быть?

Хм, вот специально подождал что бы кто-то ответил. И так и получилось — верять блин разработчикам, это же компания!

Капец, честно говоря неожидал такого бага от CodeGear.
Нет, такого быть не должно!!
Вообще какой идиот мог допустить подобное.
Сейчас буду у себя проверять в программах это.

По вашему, Герман, при закрытии программы, должны срабатывать всех OnCloseQuery невидимых форм? Слушайте, учиться учиться и еще раз туда же.
Кстати, при закрытии программы, OnCloseQuery невидимых форм не срабатывает, как и положено, а вот при LogOff или рестарте, вызывается OnCloseQuery всех невидимых форм (создал несколько форм, ни одна из них ни разу не открывалась, но OnCloseQuery отработал). Т.е. если там стоит — «Вы действительно хотите закрыть эту форму» — то это будет ад для юзеров кликать.
Здец.. У меня уже ком. проекты запущены два месяца.


> Кто б сомневался © (09.04.09 01:31) [5]
>
> Хм, вот специально подождал что бы кто-то ответил. И так
> и получилось — верять блин разработчикам, это же компания!
>
>
> Капец, честно говоря неожидал такого бага от CodeGear.
> Нет, такого быть не должно!!
> Вообще какой идиот мог допустить подобное.
> Сейчас буду у себя проверять в программах это.
>
> По вашему, Герман, при закрытии программы, должны срабатывать
> всех OnCloseQuery невидимых форм? Слушайте, учиться учиться
> и еще раз туда же.
> Кстати, при закрытии программы, OnCloseQuery невидимых форм
> не срабатывает, как и положено, а вот при LogOff или рестарте,
> вызывается OnCloseQuery всех невидимых форм (создал несколько
> форм, ни одна из них ни разу не открывалась, но OnCloseQuery
> отработал). Т.е. если там стоит — «Вы действительно хотите
> закрыть эту форму» — то это будет ад для юзеров кликать.
> ..
> Здец.. У меня уже ком. проекты запущены два месяца.

А что есть «невидимые формы»?


> А что есть «невидимые формы»?

Ну елки-палки, это формы которые были созданы (в том же автоcreate), но не были показаны юзеру по ShowModal или Show итп.

Блин.
Проверяю..
AV поймал в logoff, cудя по стэку madexcept — как раз в форме которая еще не отображалась, в WM_QUERYENDSESSION >> OnCloseQuery. Оно.
Пойду ругаться в саппорт.. >:|

P.s. Stan ты не постил еще это баг?


> Кто б сомневался © (09.04.09 01:41) [7]
>
>
> > А что есть «невидимые формы»?
>
>
> Ну елки-палки, это формы которые были созданы (в том же
> автоcreate), но не были показаны юзеру по ShowModal или
> Show итп.

А «окна» этих форм были созданы?
А не эти ли окна получают сообщение WM_CLOSE?

Короче, вот шаги:
создаю проект.
Создаю еще 3 формы. т.е. получается всего 4 с главной.

В трех последних формах, я пишу OnCloseQuery и вставляю туда ShowMessage(«Закрываем»).
Компилирую, запускаю из Windows, делаю Logoff или restart — возбужаются события во всех 3 формах подряд. Если закрыть прогу, такого не происходит.

как они тестировали?
Да и я тоже как тестировал. Но я ж не думал..


> Я что -то не пойму..
> вот для примера сделал простенький проект для теста.
> Есть две формы, Form1 и Form2 . В Form2 создаю событие OnCloseQuery
> и пишу там сообщение ShowMessage(«Close Form2»).
> Т.е. И та и другая форма создаются в autocreate.
>
> Далее запускаю проект, — вижу только Form1, как и должно
> быть, и выхожу из сесии Windows — Logoff. И вылетает Close
> Form2″, т.е. срабатывает OnCloseQuery второй формы.
> Так и должно быть?

Да, так и должно быть

Читать forms.pas до полного и окончательного просветления:

procedure TCustomForm.WMQueryEndSession(var Message: TWMQueryEndSession);
begin
Message.Result := Integer(CloseQuery);
end;


> Игорь Шевченко © (09.04.09 02:00) [11]

Для чего?
и почему только на QueryEndSession, а не на закрытие программы?
И почему для невидимых форм. И я что то этого в справке не вижу..


> И почему для невидимых форм?

Для всех причем.
А ведь обычно туда вставляют — «Вы действительно хотите закрыть итп».
А ведь это не mdi формы.. Для них это еще понятно..

> [12] Кто б сомневался © (09.04.09 02:05)

потому что WM_QUERYENDSESSION рассылается всем окнам верхнего уровня.

Просто ответьте на вопрос.
Почему только на QueryEndSession, а не на закрытие программы?

Да не в тех. плане . Это и так понятно.

> [16] Кто б сомневался © (09.04.09 02:09)

а что тут можно сказать не в тех. плане? так задумано. могу лишь повторить [3].


> а что тут можно сказать не в тех. плане? так задумано. могу
> лишь повторить [3].

Ага, еще скажи что это фича..
Побольше б таких «фич» — тогда совсем станет весело..

Я советую немножко изучить как работает операционная система, под которую вы пишете программы. Для облегчения этого процесса есть специальный сайт http://msdn.microsoft.com

В этом случае будет проще избегать непонятных ситуаций, подобных сабжевой.

Да и вообще кругозор расширять весьма полезное занятие

Для того, чтобы иметь возможность сохранить данные (событие OnCloseQuery преимущественно для этого предназначено)


> Для того, чтобы иметь возможность сохранить данные

Ага, во всех формах, даже в тех, которые еще даже не показывались и есть не-ви-ди-мы-е.
Вдумайтесь в последнее слово, потом говорите.

Я тебе простой пример приведу

uses
Forms,
main in «main.pas» ,
f2 in «f2.pas» ;

begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm2, Form2);
Application.Run;
end.

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;

var
Form1: TForm1;

procedure TForm1.Button1Click(Sender: TObject);
begin
form2.Close;
end;

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;

type
TForm2 = class(TForm)
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
end;

var
Form2: TForm2;

procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
ShowMessage(«Form2Close»);
end;


> Вдумайтесь в последнее слово, потом говорите.

У меня есть привычка — я обычно думаю, когда говорю.
Но если тебе эта привычка кажется странной, то я процитирую справку по Delphi:

«You can use an OnCloseQuery event handler to ask users if they are sure they really want the form closed immediately. For example, you can use the handler to display a message box that prompts the user to save a file before closing the form.»

«В последнее время наметилась одна тенденция. Дело в том, что сейчас для того, чтобы выйти на рынок программных средств и занять в нём свою нишу, фирма, а, соответственно, и программисты должны делать продукт как можно быстрее. При этом, естественно, достаточно часто вопросы эффективности, быстродействия, минимизации размера используемой памяти и тому подобные во внимание просто не принимаются. Зачем, дескать, думать о таких «мелочах», если современные компьютеры достаточно мощные и «переваривают» почти любые объёмы. Подумаешь, мегабайт памяти туда, мегабайт сюда… Кроме того, очень сильное влияние на квалификацию программистов оказывают многочисленные средства быстрой разработки, бурное развитие которых наблюдается в последнее время. Средства, предназначенные для повышения производительности труда квалифицированных программистов, заняли на рынке совершенно другое место. Достаточно часто эти средства используются программистами низкой квалификации для того, чтобы в кратчайшее время создать работающую программу, прикладывая при этом минимум усилий. Более того, средства быстрой разработки позволяют программисту скрыть недостаток квалификации, ибо вся черновая работа делается без участия программиста. Вместо того, чтобы овладеть необходимым для профессиональной деятельности минимумом, можно недостаток квалификации скрыть посредством использования программы, которая всё сделает сама. Таким образом, средства быстрой разработки используются превратились в средства создания неэффективных программ неквалифицированными программистами. Что поделаешь, рынок диктует свои условия…

Соответственно, такой подход приводит к тому, что достаточно часто у программистов появляется завышенная самооценка. Раз я могу «накропать» программу за неделю, значит, я – ВЕЛИКИЙ ПРОГРАММИСТ, всё умею, всё могу. Зачем мне чему-то учиться, я (при помощи конкретного средства) всегда сделаю то, что хочу! Появилось даже расхожее определение – «программист, пишущий мышкой»… Но стоит у подобных, с позволения сказать, программистов, забрать средство быстрой разработки, как они становятся беспомощными. Ведь они являются программистами на конкретном средстве! Другими словами, они являются ПОЛЬЗОВАТЕЛЯМИ конкретного средства… А пользователи и программисты – это совершенно различные классы людей, использующих компьютер в своей профессиональной деятельности. И если пользователю необходимо знать только порядок использования и взаимодействие частей одной или нескольких программ (WinWord, бухгалтерская или банковская программы, программа обработки изображений и так далее), то программист помимо всего прочего должен, почти обязан понимать то, как функционирует компьютер, на основе каких принципов построена операционная система, понимать принципы организации данных и быть в состоянии написать эффективную программу, решающую поставленную перед программистом задачу. В том случае, если программист является профессионалом, то использование средств быстрой разработки только поможет ему, позволив сократить время, необходимое для разработки программы, и минимизировать усилия, необходимые для разработки таковой. «

(c) Павел Румянцев
http://www.techbook.ru/rumyantsev.html

Послушайте, не надо меня за дурочка считать.
По меркам Windows — это сообщение передается всем окнам верхнего уровня..
Но VCL должна отрабатывать этот вариант, и проверять видимо ли окно или нет. Т.к. по меркам VCL если форма Close, то она может быть и скрыта (Hidden) (те самые варианты caHidenn, caFree итд).
А что здесь получается?
А то, что при закрытии программы, OnCloseQuery не отрабатывает для скрытых форм, а вот при Logoff и рестарте отрабатывает (форма даже еще не показывалась, данные еще даже не инициализировались, а уже просят OnCloseQuery — тут я кстати получил AV, и я думаю не один я, хотя прекрасно знал как работает QUERYENDSESSION).
что самое интересное OnClose не отрабатывает при скрытой форме никак, втч и при LogOff. Что есть корректно.
Там просто забыли проверить видимо ли окно или нет, именно для QUERYENDSESSION.
Все я не собираюсь спорить над такой очевидной вещью.
С точки зрения API — отсылки сообщения окнам, здесь все ок, с точки зрения постобработки этого сообщения формой VCL — здесь баг. точка.

Кто б сомневался © (09.04.09 02:49) [24]


> А то, что при закрытии программы, OnCloseQuery не отрабатывает
> для скрытых форм

Потому что им не приходит сообщение WM_CLOSE и для них не вызывается метод Close.

А WM_QUERYENDSESSION посылается всем окнам верхнего уровня, независимо от наличия у окна в стилях WS_VISIBLE — ну так система устроена, это надо знать и не удивляться срабатыванию события CloseQuery.

в Borland все сделали верно — они не знают, были ли выполнены конкретно в настоящий момент невидимой формой какие-то действия до того момента, как она стала невидимой, требующие уведомления о событии EndSession и честно вызывают это уведомление.

Посмотрел в KOL MCK — там все логично и правильно (там OnClose совмещен с OnCloseQuery — т.е. . в OnClose можно указать CanClose (Accept)), даже комментарий есть:

Called before closing the window. It is possible to set Accept parameter to False to prevent closing the window. This event events is not called when windows session is finishing (to handle this event, handle WM_QUERYENDSESSION message, or assign OnQueryEndSession event to another or the same event handler)


Т.е. KOL как обертка API корректно обрабатывает сообщение.
А вот VCL как обертка, не корректно.


> Игорь Шевченко © (09.04.09 03:02) [25]

Елки палки, да не надо мне рассказывать технические детали.
Должна быть пост обработка самой обертки (VCL) для логичной работы на уровне форм, а не окон.

Кто б сомневался © (09.04.09 03:06) [27]


> Должна быть пост обработка самой обертки (VCL) для логичной
> работы на уровне форм, а не окон.

На уровне форм тоже все логично сделано.


> Called before closing the window. It is possible to set
> Accept parameter to False to prevent closing the
> window. This event events is not called when windows
> session is finishing (to handle this event, handle WM_QUERYENDSESSION
> message, or assign OnQueryEndSession event to another
> or the same event handler)

У KOL немножко меньше пользователей, чем у VCL, соответственно, меньше и репортов о проблемах, меньше и реакции.
Впрочем, это не единственный недостаток этой библиотеки.

тут важно другое — в VCL есть много свойств, обусловленных ее кодом и дизайном — их просто надо понимать и воспринимать такими, как есть, в случае использования VCL. В обработке сообщения WM_QUERYENDSESSION дизайн совершенно логичен, мне бы, как пользователю, не понравилось бы тихое закрытие окна при завершении сеанса, особенно если я в нем что-то успел сделать. Вводить в VCL возможность отслеживать «а было ли что-то сделано (в частности, была бы форма хотя бы раз показана) и стоит ли выдавать сообщение» — это настолько неуклюже, что даже не обсуждается.


> В обработке сообщения WM_QUERYENDSESSION дизайн совершенно
> логичен, мне бы, как пользователю, не понравилось бы тихое
> закрытие окна при завершении сеанса, особенно если я в нем
> что-то успел сделать.
>

Вы что прикидываетесь что-ли?!

Вот например как у меня получилось после моей проверки — на второй форме при закрытии отображается диалог, «сохранить профайл?» в OnCloseQuery. На третей форме — у меня храняться настройки, там также переспрашивается «сохранить?» Итак я запускаю программу, но не открываю вторую форму и третью, в которой создается профайл и отображаются настройки. Юзеру просто нужно быстро запустить программу по делу.
А теперь он делает LogOff — и что получает, а получает 2 диалога, которые спрашивате у юзера «сохранить профайл?» -а юзер в непонятках конечно. А потом вдруг получает — «сохранить настроки?» . А если бы я бы проверял что то, непроинициализированное, то получил бы AV — это еще лучше.

Итого, юзер получает два вопроса с форм, которые он не запускал, и которые по логике не должны вообще рыпаться, и на которых ничего не изменялось, — т.к. формы не были отображены, а также высокую вероятность AV.


> У KOL немножко меньше пользователей, чем у VCL, соответственно,
> меньше и репортов о проблемах, меньше и реакции.

Да-да, и комментарий написали тоже случайно, не подумавши..

Все, перечитывайте еще раз [27] особенно вторую часть предложения.
Я пойду спать.
И сделайте для себя разницу между окнами и формами, не с тех. точки зрения, а с логической точки зрения VCL.

> [30] Кто б сомневался © (09.04.09 03:27)

еще в делфи можно обращаться к private членам другого класса, объявленного в том же модуле, так что ж теперь хоронить её что ли? ))


> еще в делфи можно обращаться к private членам другого класса,
> объявленного в том же модуле, так что ж теперь хоронить
> её что ли? ))

Можно и не обращаться — strict private. Как видите исправились, косвенно признав этот ньюанс..

> Вот например как у меня получилось после моей проверки — на второй форме при закрытии отображается диалог, «сохранить профайл?»
> в OnCloseQuery. На третей форме — у меня храняться настройки, там также переспрашивается «сохранить?
у меня тоже так делается. в смысле диалогов о сохранении.

> А теперь он делает LogOff — и что получает, а получает 2 диалога
не получает, если он ничего не менял в данных формы т.е. настройках/профайле, т.к. условие показа диалога на закрытии у меня еще включает изменение контента формы.
т.е. даже если он открыл настройки, посмотрел не трогая их, и закрыл форму диалога не будет (как и во всех нормальных программах (проверь ворд/паинт/любую профессиональную)). не говоря о том чтобы когда ее даже не показывали (также если предварительно нажал «сохранить»).
у меня либо по онченж взводится флаг необходимости (при сохранении/отмене сбрасывается), либо просто сравниваются используемые значения настроек в переменных с меняемыми в контролах.
обычно у меня даже кнопка сохранения задизейблена если нет изменений для сохранения.
и уж кстати, обычно я не рассчитываю на автосоздание (там у меня минимум, датамодули и основная форма) остальное создается по требованию. но даже если их автосоздать все то ни одного диалога не будет.

> Итого, юзер получает два вопроса с форм, которые он не запускал
не получает. если делать нормально.


> И сделайте для себя разницу между окнами и формами, не с
> тех. точки зрения, а с логической точки зрения VCL

С логической точки зрения делает пользователь. И если пользователь вставил обработчик события OnCloseQuery, значит, подразумевал его вызов. Вот он и вызвался. А в тех формах, где пользователь не предусмотрел обработчика события OnCloseQuery, он не вызывался.
Все логично.

Представь себе ситуацию, ты открыл много приложений, в том числе и на delphi, и что-то в них делал. Потом тебе пришло критическое обновление от Microsoft, установилось и попросило перезагрузку.
Все приложения начали закрываться по завершению сеанса.

Неужели приложения на delphi должны тихо умереть, дав возможность пользователю потерять несохраненные данные ?
На мой взгляд, не должны, на взгляд Borland тоже.

> Кто б сомневался (09.04.2009 2:08:15) [15]

Потому что это сообщение Виндоус, а не Дельфи и оно действительно посылается всем окнам верхнего уровня.
Иначе странно бы было, как что закрыть или запретить закрытие Виндоус.
А то что программист не отреагировал на эту ситуацию и выдал подобный запрос плохо говорит об его квалификации, это же не запрос на сохранение файлов.

> Кто б сомневался (09.04.2009 2:13:18) [18]

Слушай, а ты почему работаешь в Виндоус?

> Кто б сомневался (09.04.2009 3:34:32) [32]

Ничего не признали, немного расширили да, но для признания должно быть всегда strict private и без ключевого слова, а как мы видим этого нет.

to Игорь Шевченко и Anatoly Podgoretsky

Вчера запостил этот баг уже и он уже в статусе Open.
Вы понимаете что это? Это не Reported как обычно, и не Pending.
Это значит его сразу открыли, и уже работают над ним.


> Потому что это сообщение Виндоус, а не Дельфи и оно действительно
> посылается всем окнам верхнего уровня.
> Иначе странно бы было, как что закрыть или запретить закрытие
> Виндоус.

Мне надоело уже повторять очевидные вещи. OnCloseQuery должна получать видимая форма по очевидным и логичным причинам, — я их описал выше. Это баг, т.к. в саппорте его даже в очередь не поставили, а сразу открыли.


> А то что программист не отреагировал на эту ситуацию и выдал
> подобный запрос плохо говорит об его квалификации, это же
> не запрос на сохранение файлов.

По меркам VCL скрытая форма- это уже закрытая форма (caHidden).
Какие могут быть события перед закрытием — OnCloseQuery если форма уже закрыта?

Close and restart the current application in DELPHI

How can I do this one?

For some reason or selected by the user, “ask” the current application to restart it self.

4 Answers 4

There is another way for closing-restarting the application:

Save a scheduled task to a short time after the application closes. This will have to be the VERY LAST thing your application does before exiting (no further data processing, saving, uploading or whatever)

  1. get the system time first
  2. set the scheduled task some time after this time (scheduled event will have to start your executable)
  3. exit your application (closing the main form or application.terminate will do it)

When your program starts again, it should check for any such scheduled task and remove them. This must be the VERY FIRST action your application should do when starting. (cleanup)

  1. check for any scheduled tasks created by your executable
  2. remove them

AFAIK, The Delphi Jedi component set has a component you can do the task scheduling stuff with.

Использование процедур и функций в Delphi

Скобки

Добавление скобок при вызове процедур и функций без параметров уже давно не является новинкой в Delphi, тем не менее, эта возможность мало известна. Эту возможность оценят по достоинству те программисты, которым приходится работать на двух языках (C++ и Delphi), так как им не нужно будет постоянно помнить о разнице в синтаксисе при вызове процедур и функций в разных языках. В Delphi оба варианта, приведенные ниже, считаются корректными.

Возможность перегрузки

Впервые концепция перегрузки процедур и функций была реализована в Delphi 4. Она позволяет иметь несколько различных процедур и функций с одинаковыми именами, но с разными списками параметров. Такие процедуры и функции должны быть описаны с применением директивы overload.

procedure Test (I: integer); overload;
procedure Test (S: string); overload;
procedure Test (D: double); overload;

При вызове процедуры Test, Delphi сама решит, какую из трех процедур необходимо выполнить, в зависимости от передаваемого ей параметра. Но нужно отметить, что это не самая безопасная возможность языка. Применение перегружаемых процедур и функций может стать неиссякаемым источником трудноуловимых ошибок в программе. Поэтому пользуйтесь этой возможностью осторожно.

Передача параметров

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

Передача параметров по значению

Этот режим передачи параметров применяется по умолчанию. Если параметр передается по значению, создается локальная копия данной переменной, которая и предоставляется для обработки в процедуру или функцию. Посмотрите на следующий пример:

procedure Test(s: string);

При вызове указанной процедуры будет создана копия передаваемой ей в качестве параметра строки s, с которой и будет работать процедура Test. При этом все внесенные в строку изменения никак не отразятся на исходной переменной s.

Однако это не относится к объектам. Например, если в функцию передается переменная (а точнее экземпляр объекта) TStringList, то в данном случае произойдет передача по ссылке (даже если это не указано явно). Этот способ передачи является у большинства самым излюбленным, но в тоже время является и самым не практичным, т.к. для выполнения метода выделяется дополнительная память для создания точной копией передаваемой переменой. Для решения этой проблемы следует использовать один из способов описанных ниже.

Передача параметров по ссылке

Pascal позволяет также передавать параметры в функции или процедуры по ссылке — такие параметры называются параметрами-переменными. Передача параметра по ссылке означает, что функция или процедура сможет изменить полученные значения параметров. Для передачи параметров по ссылке используется ключевое слово var, помещаемое в список параметров вызываемой процедуры или функции.

procedure ChangeMe(var x: longint);
begin
x := 2; // Параметр х изменен вызванной процедурой
end;

Вместо создания копии переменной x, ключевое слово var требует передачи адреса самой переменной x, что позволяет процедуре непосредственно изменять ее значение.

Передача параметров констант

Если нет необходимости изменять передаваемые функции или процедуре данные, можно описать параметр как константу. Ключевое слово const не только защищает параметр от изменения, но и позволяет компилятору сгенерировать более оптимальный код передачи строк и записей. Вот пример объявления параметра-константы:

procedure Test(const s: string );

Передача открытых массивов

Открытый массив параметров позволяет передавать в функцию или процедуру различное количество параметров. В качестве параметров можно передать либо открытый массив элементов одинакового типа, либо массивы констант различного типа. В приведенном ниже примере объявляется функция, которой в качестве параметра должен передаваться открытый массив целых чисел.

function AddEmUp(A: array of integer): integer;

В открытом массиве можно передавать переменные, константы или выражения из констант.

Для получения информации о фактически передаваемом массиве параметров в функции или процедуре могут использоваться функции High, Low и SizeOf.

Object Pascal также поддерживает тип array of const, который позволяет передавать в одном массиве данные различных типов. Синтаксис объявления функций или процедур, использующих такой массив для получения параметров, следующий:

procedure WhatHaveIGot( A: array of const );

Вызвать объявленную выше функцию можно, например, с помощью такого оператора:

procedure WhatHaveIGot( [‘Text’, 10, 5.5, @WhatHaveIGot, 3.14, true, ‘c’] );

При передаче функции или процедуре массива констант все передаваемые параметры компилятор неявно конвертирует в тип TVarRec. Тип данных TVarRec объявлен в модуле System следующим образом:

PVarRec = ^TVarRec;
TVarRec = record
case Byte of
vtInteger: (VInteger: Integer; VType: Byte);
vtBoolean: (VBoolean: Boolean);
vtChar: (VChar: Char);
vtExtended: (VExtended: PExtended);
vtString: (VString: PShortString);
vtPointer: (VPointer: Pointer);
vtPChar: (VPChar: PChar);
vtObject: (VObject: TObject);
vtClass: (VClass: TClass);
vtWideChar: (VWideChar: WideChar);
vtPWideChar: (VPWideChar: PWideChar);
vtAnsiString: (VAnsiString: Pointer);
vtCurrency: (VCurrency: PCurrency);
vtVariant: (VVariant: PVariant);
vtInterface: (VInterface: Pointer);
vtWideString: (VWideString: Pointer);
vtInt64: (VInt64: PInt64);
end;

Поле VType определяет тип содержащихся в данном экземпляре записи TVarRec данных и может принимать одно приведенных значений.

Поскольку массив констант способен передавать данные разных типов, это может вызвать определенные затруднения при создании обрабатывающей полученные параметры функции или процедуры. В качестве примера работы с таким массивом рассмотрим реализацию процедуры WhatHaveIGot, которая просматривает элементы полученного массива параметров и выводит их тип.

procedure WhatHaveIGot( A: array of const );
var
i: integer;
TypeStr: string;
begin
for i := Low(A) to High(A) do
begin
case A[i].VType of
vtInteger : TypeStr := ‘Integer’;
vtBoolean : TypeStr := ‘Boolean’;
vtChar : TypeStr := ‘Char’;
vtExtended : TypeStr := ‘Extended’;
vtString : TypeStr := ‘String’;
vtPointer : TypeStr := ‘Pointer’;
vtPChar : TypeStr := ‘PChar’;
vtObject : TypeStr := ‘Object’;
vt ;
vtW ;
vtPW ;
vtAnsiString : TypeStr := ‘AnsiString’;
vtCurrency : TypeStr := ‘Currency’;
vtVariant : TypeStr := ‘Variant’;
vtInterface : TypeStr := ‘Interface’;
vtW ;
vtInt64 : TypeStr := ‘Int64’;
end;
ShowMessage( Format( ‘Array item %d is a %s’, [i, TypeStr] ) );
end;
end;

Значения параметров по умолчанию

В Delphi есть одна очень полезная возможность — использование значений параметров по умолчанию. Она позволяет установить принимаемое по умолчанию значение параметра процедуры или функции. Это значение будет использоваться в тех случаях, когда вызов процедуры или функции производится без указания значения данного параметра. В объявлении процедуры или функции принимаемое по умолчанию значение параметра указывается после знака равенства, следующего после его имени. Поясним это на следующем примере:

procedure HasDefVal( s: string; i: integer = 0 );

Подобное объявление означает, что процедура HasDefVal может быть вызвана двумя путями. В первом случае — как обычно, с указанием обоих параметров:

procedure HasDefVal( ‘Hello’, 26 );

Во втором случае можно задать только значение параметра s, а для параметра i использовать значение, установленное по умолчанию:

procedure HasDefVal( ‘Hello’ );

При использовании значении параметров по умолчанию следует помнить о нескольких приведенных ниже правилах:

  • Параметры, имеющие значения по умолчанию, должны располагаться в конце списка параметров. Параметр без значения по умолчанию не должен встречаться в списке после параметра, имеющего значение по умолчанию.
  • Значения по умолчанию могут присваиваться только параметрам обычных типов, указателям или множествам.
  • Значение по умолчанию может передаваться только по значению либо с модификатором const. Оно не может быть ссылкой или нетипизированным параметром.

Одним из важных преимуществ применения значений параметров по умолчанию является простота расширения функциональных возможностей уже имеющихся процедур и функции с соблюдением обратной совместимости. Предположим, на рынок программных продуктов была выпущена программа, ключевым звеном которой является функция сложения двух целых величин:

function Add( I1, I2: integer ): integer;
begin
Result := I1 + I2;
end;

Предположим также, что исследования показали целесообразность добавления в программу возможности сложения трех чисел. Однако замена имеющейся функции функцией сложения трех чисел приведет к тому, что вам придется переправлять немало текста, который перестанет компилироваться из-за внесения в функцию еще одного параметра. Однако при использовании значений параметров по умолчанию проблема решается легко и просто. Достаточно изменить объявление функции так, как показано ниже.

function Add( I1, I2: integer; I3: integer = 0 ): integer;
begin
Result := I1 + I2 + I3;
end;

Директива

Директива <$X->запрещает вызов функций как процедур (с игнорированием возвращаемого результата). По умолчанию этот режим включен (<$X+>). Так вот, запомните, использование переменной Result недопустимо при сброшенном флажке опции Extended Syntax, расположенном во вкладке Compiler диалогового окна Project Options, или при указании директивы компилятора <$X->.

В каждой функции языка Objecl Pascal существует локальная переменная с именем Result, предназначенная для размещения возвращаемого значения. Кроме того, вернуть значение из функции можно также путем присвоения значения переменной, имеющей то же имя, что и данная функция. Это стандартный синтаксис языка Pascal, сохранившийся от его предыдущих версий. При использовании в теле функции переменной с ее именем не забывайте, что существуют большие отличия в обработке этого имени — все зависит от того, где она расположена — в левой части оператора присвоения или же в любом другом месте текста функции. Если имя функции указано в левой части оператора присвоения, то предполагается, что назначается возвращаемое функцией значение. Во всех других случаях предполагается, что осуществляется рекурсивный вызов этой функции.

Процедура и функция — это ключевые понятия в любом языке программирования, без которых не обходится ни одна серьезная программа. И поэтому очень важно иметь полное понимание о механизме их работы.

CloseFile

Posted by key under Delphi

CloseFile

закрывает файл с сохранением в нём данных

|| procedure CloseFile ( var FileHandle : TextFile ) ;

Описание:

Delphi процедура CloseFile закрывает открытый файл, связанный процедурой AssignFile. После закрытия файла процедурой CloseFile, все данные, записанные до этого в файл, сохраняются. Переменная типа TFile может после этого связываться с другим физическим файлом.

Пример кода:

var
myFile : TextFile;
text : string;

begin
// Try to open the Test.txt file for writing to
AssignFile(myFile, ‘Test.txt’);
ReWrite(myFile);

// Write a couple of well known words to this file
WriteLn(myFile, ‘Hello’);
WriteLn(myFile, ‘World’);

// Close the file
CloseFile(myFile);

// Reopen the file in read only mode
Reset(myFile);

// Display the file contents
while not Eof(myFile) do
begin
ReadLn(myFile, text);
ShowMessage(text);
end;

// Close the file for the last time
CloseFile(myFile);
end;

Программирование Delphi

Все о программировании.

Главное меню

Функции и процедуры

Краткий обзор как использовать различные типы процедур и функций Delphi, указателей на функции и процедуры, методы и указатели методов, анонимные методы.

Автономные процедуры

Более или менее все RTL процедуры — так называемые «автономные» процедуры. Они объявлены на уровне модулей и чтобы вызвать такую процедуру, Вы должны знать, где она объявлена (имя модуля и список параметров для передачи).

Пример — процедура ShowMessage, объявленная в модуле dialogs.pas, вот ее объявление:

Чтобы вызвать такую процедуру, Вы просто должны включить имя модуля, где объявлена эта процедура в раздел uses вызывающего модуля. Большинство общих модулей уже перечислено в пункте uses модуля формы, таким образом, Вы не должны вручную добавлять dialogs.pas, чтобы использовать ShowMessage.

Вложенные процедуры

Функции и процедуры иногда содержат другие функции и процедуры в пределах своих блоков:

Вышеупомянутые два типа объявления процедур не связаны с классом или объектом.

Методы

Процедуры, которые связаны с классом, называют методами. Большинство методов используют экземпляры класса — объекты. Некоторые методы, называемые методами класса, работают в классах.

Функция Add — метод класса TStringList. Например, метод Add объявляется как:

Процедурные типы и указатели процедур

Delphi позволяет обрабатывать подпрограммы (функции и процедуры) как значения, которые могут быть назначены переменным.

Рассмотрим отрывок кода:

В этом коде TDisplayerProc и TIntegerDisplayerFuncпроцедурные типы

Переменные dp и idp — указатели процедур. Обратите внимание, что функция DisplayDoubleInteger получает процедурный тип, как второй параметр (TDisplayerProc).

Указатели методов

Подобно указателям процедур, указатели методов ссылаются на методы экземпляра объекта.

Анонимные методы

Начиная с Delphi 2006, язык Delphi знает также анонимные методы.

Анонимный метод — процедура или функция, которая не связана с ассоциированным именем.

Пример анонимных методов: сортировка объекта TList.

освободить объект в onclose событие Tform в delphi

Я новичок в Delphi, и мой вопрос может быть очень простым. Я создал форму в процедуре Delphi. До сих пор я использовал ShowModal а затем освободил все объекты, которые я хочу обработать утечкой памяти после закрытия формы. Нет, мне нравится показывать форму без режима, но я не знаю, как освободить объект внутри события OnClose . Кто-нибудь знает решение для этого?

2 ответа

Просто установите для параметра Action значение caFree :

Значение параметра Action определяет, действительно ли форма закрывается. Вот возможные значения Action:

caNone
Форма не разрешается закрывать, поэтому ничего не происходит.

caHide
Форма не закрыта, а просто скрыта. Ваше приложение все еще может получить доступ к скрытой форме.

caFree
Форма закрывается и вся выделенная память для формы освобождается .

caMinimize
Форма свернута, а не закрыта. Это действие по умолчанию для дочерних форм MDI.

Если для caFree Action caFree значение caFree , форма вызовет caFree Release() для себя после выхода OnClose обработчика OnClose :

Уничтожает форму и освобождает связанную с ней память.

Используйте Release, чтобы уничтожить форму и освободить связанную с ней память.

Release не разрушает форму, пока все обработчики событий формы и обработчики событий компонентов в форме не завершат выполнение. Release также гарантирует, что все сообщения в очереди событий формы будут обработаны до того, как форма будет освобождена. Любые обработчики событий для формы или ее дочерних элементов должны использовать Release вместо Free (Delphi) или delete (C ++). Невыполнение этого требования может привести к ошибке доступа к памяти.

Примечание. Release немедленно возвращается вызывающей стороне. Он не ждет освобождения формы перед возвратом.

Release() CM_RELEASE отложенное сообщение CM_RELEASE в окно формы. Как только поток выполнения возвращается в основной цикл обработки сообщений и сообщение отправляется, форма освобождается из памяти.

Если ваш объект TForm владеет другими объектами, они будут автоматически освобождены при освобождении TForm .

Илон Маск рекомендует:  Windows api описание
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL