Отправляет email-рассылки с помощью сервиса Sendsay

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

  Все выпуски  

Программирование на Delphi (выпуск 74)


Программирование на DELPHI
Выпуск #74 (07 августа 2007 г.)

Разделы сайта:

Delphi.int.ru

Новости сайта
Регистрация »
Файловый архив
Статьи
Компоненты
Plug-in's
Документация
Исходники
Изображения
Игры
Программы
Рассылки сайта
Дружеств. сайты

IRC-канал сайта:

Сервер: irc.dalnet.ru
(либо irc.tic-tac.ru)
Порт: 6667
Канал: #delphiintru

Ждём Вас на нашем канале!

Доброго времени суток, уважаемые читатели!

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

Какими средствами общения типа "чат" Вы пользуетесь?

2. Присылайте свои предложения на темы статей - какие статьи Вы хотели бы увидеть в рассылке. Все предложения принимаются на info@delphi.int.ru.

3. Рассылка уходит в отпуск, но совсем ненадолго - до конца августа. Так что следующий выпуск будет в начале сентября. Сайт, естественно, функционирует без перерывов.

4. Об изменениях (последних новостях) Delphi.int.ru Expert Вы можете прочитать в соответствующем разделе выпуска. Новостей достаточно много.

Статистика Delphi.int.ru Expert на 07.08.2007, 10:00 (предыдущий подсчёт - 18.07.2007, 12:00):

Количество экспертов: 57 (+0).
Участниками задано вопросов: 833 (+76).
Всего получено ответов: 1355 (+110).
Количество сообщений на мини-форумах: 1588 (+306).
Максимальное число разосланных в день писем (за август '07): 1695 (01.08.2007).
Максимальное число разосланных в день писем (за всю историю): 1820 (30.07.2007, +1011).

Разделы рассылки:

» Авторское слово
» Обучение Delphi
» Delphi.int.ru Expert
» Статья по Delphi
» Файловый архив
» Юмор

Delphi.int.ru Expert
Сообщество программистов: общение, помощь, обмен опытом.

Количество читателей рассылки (07.08.2007, 10:00):
5487+1309+404= 7200 (+61)

Связь по e-mail:

admin@delphi.int.ru
expert@delphi.int.ru
info@delphi.int.ru
support@delphi.int.ru

Если Вы хотите где-нибудь разместить материалы, представленные на www.delphi.int.ru или в данной рассылке, свяжитесь, пожалуйста, с их автором или администратором.
Обучение Delphi

» Найти все предыдущие уроки можно на www.delphi.int.ru в разделе "Статьи".
Последние 3 урока:

10. Логические выражения
11. События
12. Функции и процедуры. Математические вычисления. Случайные числа

Ввод и вывод

Автор:
Ерёмин Андрей
Начинать поиски надо с самого неподходящего места.
Номер урока:
13
 

Знаний, полученных в предыдущих уроках, достаточно, чтобы приступить к изучению механизмов ввода и вывода данных. Общая схема работы программы примерно такова: пользователь вводит данные, программа их считывает, производит с ними какие-то операции и выдаёт результат. Упрощённо: ввод, обработка, вывод. Что мы уже умеем? Для ввода данных нам понадобятся такие элементы как текстовое поле ввода (TEdit) или многострочное поле - TMemo, CheckBox или RadioButton для выбора параметров и др. Для вывода можно использовать текстовую метку (TLabel). Теперь разберём программную часть. Мы уже умеем описывать переменные, знаем, что такое тип данных и какие бывают типы (числа, строки и т.п.) Осталось лишь выяснить как связать визуальные элементы с программным кодом. В примерах, рассмотренных в предыдущих уроках, мы задавали значения переменным вручную (в коде), но это конечно же неприемлемо ни для одной программы. Программа должна быть универсальной и обрабатывать те данные, которые передал пользователь. Для ввода и вывода будут использоваться некоторые функции. Что такое функции, зачем они нужны, и как с ними работать, мы рассмотрели на прошлом уроке. Ну что, ближе к делу?

Ввод на примере TEdit

Текстовое поле ввода (TEdit) - простой и в то же время удобный элемент для ввода данных. В поле мы можем ввести и число и текст - никаких ограничений нет. Итак, наша первая задача - узнать, что введено в поле. Для этого мы должны обратиться к свойствам этого объекта. За текст, находящийся в поле, отвечает свойство Text. Именно им мы и воспользуемся. Попробуем считать число, которое будет введено... Расположим на форме само поле (TEdit) и кнопку (TButton). Создадим обработчик нажатия кнопки и сделаем следующее: объявим переменную целочисленного типа, а затем попробуем поместить в неё значение, которое введено в поле.

procedure TForm1.Button1Click(Sender: TObject);
var A: Integer;
begin
  A:=Edit1.Text;
end;

Казалоось бы, всё верно - переменную мы объявили, и просто хотим узнать, что введено в поле. Попробуем запустить (F9) - всё не так просто! Компилятор сообщает об ошибке:

[Error] Unit1.pas: Incompatible types: 'Integer' and 'TCaption'

Здесь сказано, что типы данных Integer и TCaption не соответствуют друг другу. TCaption - это тип данных свойства Text у TEdit. Этот тип "обозначает" текстовую строку, т.е. любые символы. Становится понятнее? В поле ввода мы можем ввести не только цифры, но и буквы и даже любые знаки, какие есть на клавиатуре (а на самом деле - вообще любые символы из кодовой таблицы). Однако наша переменная - число! Получается, что мы хотим в качестве числа записать символы. Непорядок! Да, вы скажете: но мы ведь будем вводить в поле цифры, а не буквы... Верно, но знает ли об этом компилятор? Конечно нет. А уговорить его не удастся :-)

Несоответствие типов данных - частая ошибка. Преобразовывать одни типы данных в другие требуется очень часто. Наш пример - яркое тому подтверждение. Чтобы работать с числом, мы должны введённый текст (именно текст) преобразовать в число.

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

Для преобразования текста (строки) в целое число служит функция StrToInt(). Название абсолютно точно отражает назначение функции. У функции единственный параметр - строка, а на выходе получается число. Поэтому, чтобы наш пример работал, мы должны написать так:

procedure TForm1.Button1Click(Sender: TObject);
var A: Integer;
begin
  A:=StrToInt(Edit1.Text);
end;

Теперь программа запустится. Попробуем ввести число и нажать кнопку - никакой ответной реакции не наблюдается. Это верно, ведь мы кроме считывания введённого числа ничего не запрограммировали. А теперь попробуем ввести посторонние символы (т.е. не цифры) - программа "вылетит" с сообщением об ошибке:

Сообщение об ошибке при преобразовании строки в число

В сообщении указана и причина возникновения ошибки: "'abc' - неверное целое число". Как избегать подобных сообщений, а вместо этого выполнять свои действия, мы разберёмся позже.

Вывод данных на примере TLabel

Прежде чем делать вывод, давайте произведём с введённым числом какие-нибудь операции. К примеру, давайте возведём число в квадрат. Как это делается, вы уже знаете. Вывод осуществим в текстовую метку (TLabel). За текст метки отвечает свойство Caption. В данном случае наши действия должны быть обратными: при вводе мы заносили в переменную введённое в поле значение, а при выводе мы должны значение из переменной перенести в элемент. Caption у TLabel описывается тоже типом данных TCaption, т.е. это текст. А значит мы должны сделать обратное преобразование, т.е. преобразовать число в текстовую строку. Как называется функция для такого перевода, легко догадаться - IntToStr(). Финальный вариант обработчика кнопки:

procedure TForm1.Button1Click(Sender: TObject);
var A: Integer;
begin
  A:=StrToInt(Edit1.Text);
  A:=Sqr(A);
  Label1.Caption:=IntToStr(A)
end;

Запускаем программу и пробуем:

Программа для возведения числа в квадрат

Простейшая программа ввода-вывода готова.

Где узнать о типах данных свойств?

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

Подсказки редактора кода

Обратите внимание, что редактор автоматически отслеживает, какие команды содержатся в коде и в этом списке всегда находятся только те пункты, которые применимы в данной ситуации. Так, если написать "A:=Edit1.", то в списке будет отсутствовать свойство Text, ведь тип переменной A и тип этого свойства не совпадают:

Редактор скрывает строки, неуместные в данной ситуации

При написании функции StrToInt() строка свойства Text конечно же появится.

Обобщение сказанного

Мы рассмотрели механизм ввода-вывода на примере обработки числа. Если обработке подлежит текст, то преобразовывать типы данных не придётся. Подобным образом осуществляется ввод и вывод практически любых данных, главное - выполнять преобразование одних типов в другие.

Для ввода целых чисел также есть удобный элемент - TSpinEdit. Расположен он на вкладке Samples. По внешнему виду похож на TEdit, только в поле ещё находятся две кнопки со стрелками - для изменения значения. Допустимые границы числа задаются свойствами MinValue и MaxValue, а само значение хранится в свойстве Value.

TSpinEdit

Работа с вещественными числами

Следует упомянуть и о дробных числах, ведь иногда без них не обойтись. В целом, их ввод и вывод практически такой же, как и целых чисел, только используются функции StrToFloat() и FloatToStr(). Всё просто. Однако с вещественными числами есть одна проблема - разделитель целой и дробной части. Дело в том, что нет определённости, какой символ считать разделителем - точку или запятую. Какой символ выбирается - зависит от настроек операционной системы (в Windows этот знак определяется в Панели управления в разделе Язык и региональные стандарты). Таким образом, если заточить программу под запятую, то на системах, где установлена точка, работать ничего не будет и будут возникать ошибки во время работы. В то же время, под точку тоже нельзя затачивать программу, ведь может стоять и запятая. К счастью, решение есть. Есть переменная, которую нигде не нужно объявлять, но значение которой можно менять - это переменная DecimalSeparator. Она объявлена в модуле SysUtils и хранит тот символ, который будет считаться разделителем. Установить нужное значение достаточно один раз - например при запуске программы. Вот так можно установить разделителем точку:

procedure TForm1.FormCreate(Sender: TObject);
begin
  DecimalSeparator:='.';
end;

Другие способы вывода

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

1. Простое окно с сообщением - ShowMessage()

Самое примитивное окно содержит указанный текст и кнопку OK для закрытия окна. Вызвать такое окно можно процедурой ShowMessage(), параметром которой является текст - он и будет отображён в окне. Модифицируем нашу мини-программу, убрав TLabel и заменив строку вывода:

procedure TForm1.Button1Click(Sender: TObject);
var A: Integer;
begin
  A:=StrToInt(Edit1.Text);
  A:=Sqr(A);
  ShowMessage(IntToStr(A));
end;

В этом случае мы увидим следующее:

Окно с сообщением - ShowMessage()

Следует обратить внимание на то, что пока окно сообщения находится на экране, интерфейс программы блокируется, а также прекращается выполнение дальнейших команд. Только после нажатия на кнопку программа продолжит свою работу.

2. Диалоговое окно - MessageDlg()

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

Создаются диалоговые окна функцией MessageDlg(). Это именно функция, а не процедура. Возвращаемым значением является кнопка, которую нажал пользователь. У функции 4 входных параметра:

  • Текст сообщения (тип данных - String);
  • Тип диалогового окна (специальный тип данных - TMsgDlgType) - указывает на значок, расположенный в окне и на заголовок окна. Этот параметр задаётся одной из следующих констант:
    • mtInformation - информационное окно (значок в окне - буква "i");
    • mtConfirmation - окно с вопросом (значок - воспросительный знак);
    • mtWarning - предупреждающее окно (значок - восклицательный знак);
    • mtError - окно с сообщением об ошибке (значок - крест на красном фоне);
    • mtCustom - окно без значка, а в заголовке - название исполняемого файла программы (все остальные типы в заголовок помещают соответствующее типу диалога название - Information, Warning и т.д.)
  • Кнопки, которые будут показаны в окне. Каждой кнопке также соответствует определённая константа. Кнопки перечисляются через запятую, а весь этот "комплект" обрамляется квадратными скобками (что означают квадратные скобки - узнаем позже). Вот константы всех доступных кнопок: mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore, mbAll, mbNoToAll, mbYesToAll, mbHelp. Название константы говорит о названии самой кнопки.
  • Четвёртый параметр указывает на индекс раздела в справочной системе, соответствующий данному диалогу. Как правило, не используется и задаётся просто 0.

В качестве возвращаемых функцией значений служат все те же константы кнопок, только с тем отличием, что вместо "mb" они начинаются на "mr" (сокращения от "modal button" и "modal result" соответственно).

Изменим нашу программу - пусть результат выдаётся в информационном окошке. Обратите внимание, насколько красивее выглядит такое окно:

Информационное окно - MessageDlg()

procedure TForm1.Button1Click(Sender: TObject);
var A: Integer;
begin
  A:=StrToInt(Edit1.Text);
  MessageDlg('Квадрат числа '+IntToStr(A)+' равен '+IntToStr(Sqr(A)),mtInformation,[mbOK],0);
end;

Примечание: Текстовые строки можно объединять, просто складывая их - знак "+" (см. фрагмент кода выше). Сами строки записываются в одиночных кавычках.

Ну и напоследок попробуем использовать диалог для уточнения у пользователя дополнительной информации. К примеру, если введено отрицательное число, будем спрашивать, нужно ли его возвести в квадрат... Код получится приблизительно таким:

procedure TForm1.Button1Click(Sender: TObject);
var A: Integer;
begin
  A:=StrToInt(Edit1.Text);
  if A < 0 then
    if MessageDlg('Число отрицательное. Возвести его в квадрат?',mtConfirmation,[mbYes,mbNo],0) = mrYes then
      MessageDlg('Квадрат числа '+IntToStr(A)+' равен '+IntToStr(Sqr(A)),mtInformation,[mbOK],0);
end;

А результат будем таким:

Окно с вопросом - MessageDlg()

Внешний вид окон всех типов:

Внешний вид окон всех типов (MessageDlg)

3. Диалоговые окна MessageBox()

C помощью фунции MessageBox() можно также выводить диалоговые окна. По внешнему виду они практически ничем не отличаются от окон MessageDlg(), однако есть возможность указать и заголовок окна. Для формирования строки кода с использованием MessageBox() есть программа Master MessageBox. C помощью неё можно быстро создать нужное диалоговое окно. Проблема MessageBox() в том, что тип диалога и кнопки задаются немного необычным образом.

Ввод с помощью диалогового окна

Специальные окошки существуют не только для вывода на экран, но и для ввода. Примером такого окна является InputBox(). Функции передаётся 3 параметра: текст заголовка окна, текст пояснения и значение, находящееся в поле при показе окна на экран. Введённую в поле строку функция возвращает как значение-результат. Пример:

procedure TForm1.Button2Click(Sender: TObject);
begin
  if InputBox('Загадка','Сидит дед, в сто шуб одет. Кто его раздевает - тот слёзы проливает. Кто это?','') = 'лук' then
    MessageDlg('Правильно!',mtInformation,[mbOk],0)
  else
    MessageDlg('Вы не угадали.',mtWarning,[mbOk],0)
end;

Окно ввода - InputBox()

Заключение

Мы рассмотрели способы ввода и вывода данных, а также познакомились с диалоговыми окнами. Приёмы ввода-вывода используются практически в любом приложении: в тех, которые имеют оконный интерфейс, это делается с использованием визуальных объектов, а для консольных приложений - в режиме командной строки.

Домашнее задание

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

Оцените данный урок по пятибалльной шкале:
1 2 3 4 5
Комментарии и замечания приветствуются.

 

Delphi.int.ru Expert
Сообщество программистов: общение, помощь, обмен опытом
(текущая версия системы: 2.15; последнее обновление: 01.08.2007)

Навигация

» Главная страница
» Новости портала
» Информация и правила
» Тематические разделы
» Задать вопрос
» Эксперты сообщества
» Рейтинги экспертов
» Поиск на портале
» Статистика
» Партнёры и ссылки
» Обратная связь

Последние новости портала

31.07.2007
Создана и запущена система личных сообщений.
Личными сообщениями могут обмениваться любые участники. Для доступа к сообщениям требуется авторизация на сайте. Принцип работы, в целом, стандартный. Все сообщения находятся в трёх папках - "Входящие", "Отправленные" и "Корзина". Срок хранения сообщений составляет 3 месяца (+ 15 дней в корзине). Ссылки для отправки личных сообщений другим участникам находятся на странице личной информации каждого участника, а также на некоторых других страницах. Чтобы найти участников, можно воспользоваться поиском. Ссылка на папку "Входящие" находится вверху страницы.
http://expert.delphi.int.ru/mail/


31.07.2007
∙ Реализованы возможности редактирования и удаления собственных сообщений на мини-форумах;
∙ Добавлена возможность отказа от уведомлений о новых сообщениях для любого из мини-форумов;
∙ На страницу личных настроек добавлено поле для изменения e-mail, на который отправляются все письма с сайта.


29.07.2007
Введена под-система медалей для участников портала. Медали подразделяются на два типа: почётные и позорные. Вручение медалей осуществляется только администраторами по собственному усмотрению.

Подробное описание находится в информационном разделе на странице "Общая информация".

http://expert.delphi.int.ru/help/general/#medals


29.07.2007
В информационный раздел добавлена новая страница - Общая информация. В данный момент на странице находится следующая информация:
∙ Мини-форумы
∙ Оценки ответов экспертов
∙ Рейтинги экспертов
∙ Медали

http://expert.delphi.int.ru/help/general/


28.07.2007
Введена поддержка тега <quote>. Использование тега доступно участникам, которым разрешено использование html-разметки. Тег служит для выделения цитат - выдержек из других сообщений, статей, и т.д.

Также в краткое руководство по Html добавлена информация об html-эквивалентах для частоиспользуемых символов (знаки ">", "<", "&" и др.)
http://expert.delphi.int.ru/help/html/

28.07.2007

На сайте изменена система авторизации. С сегодняшнего дня учётные записи участников перестают быть привязанными к e-mail адресу. Такая привязка создавала некоторые неудобства, главное из которых - изменить адрес, на который отправляются письма с сайта, было вручную невозможно.

Данные для авторизации зарегистрированным участникам

Для зарегистрированных участников практически ничего не меняется. В качестве логина продолжает использоваться адрес e-mail, на который зарегистрирован аккаунт. Пароль, соответственно, не меняется.

Чтобы изменить логин для входа и/или пароль, авторизируйтесь на сайте, затем зайдите на страницу Личных настроек и перейдите по ссылке Изменить логин / пароль. Изменять логин вовсе не обязательно - текущий (в форме e-mail) будет продолжать работать, однако в случае изменения e-mail адреса желательно изменить и логин, дабы просто не запутаться.

Внимание! Всем участникам нужно заново авторизироваться на сайте. Несмотря на то, что данные для входа не изменились, немного изменилась техническая часть авторизации.

Регистрация новых участников

Соответственным образом изменилась и система регистрации на сайте.

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

Во-вторых, при регистрации теперь необходимо выбрать логин. Существует возможность быстрой проверки логина (используется ли кем-либо).
Возможность изменения e-mail адреса станет доступна в самое ближайшее время. Она будет располагаться на странице личных настроек, где указывается вся остальная информация.

Что касается публикации вопросов и ответов... Для данного выпуска было решено публикацю отложить, а продолжить её после завершения отпуска. Кроме того, возможно, имеет смысл публиковать вопросы не в том порядке, в каком они были заданы на сайте, а порциями по тематическим разделам. В новой версии Delphi.int.ru Expert все вопросы разделяются по тематикам. Такой подход упростит чтение - не придётся переключаться с одной темы на другую, а можно сконцентироваться на какой-то одной. К примеру, в одном выпуске опубликуются вопросы, связанные с графикой в приложениях, а в другом - вопросы по программированию баз данных. Если у Вас есть свои соображения по этому поводу - пишите.


Статьи  >>

Скачиваем файлы из интернета

Автор: Вадим К

Задача: скачать файл по http в указанную папку с использованием потока.

Делаем форму

Бросаем на форму два TEdit, TProgressBar, одну кнопку и TSaveDialog.

Делаем форму

Для кнопки пишем маленький обработчик:

//Этой строкой мы скопируем имя файлаSaveDialog1.FileName:=copy(Edit1.Text,LastDelimiter('\⁄',Edit1.Text)+1,maxint);
if SaveDialog1.Execute then
  Edit2.Text:=SaveDialog1.FileName;

Теперь на форму добавим IdHTTP и кнопку (Button2) с надписью "начать закачку".

Делаем поток

С обработчиком пока повременим, а напишем самое сложное – класс для потока.

{$R *.dfm}
//---------------------------------------
type
  TDownLoader = class(TThread)
  protected
    procedure Execute; override;
  public
    property URL:string read FURL write FURL;
    property ToFolder:string read FToFolder write FToFolder;
end;

Первые две строки сделаны для того, чтобы было видно, где вписать код. И нажимаем Ctrl+Shift+C. Delphi допишет немного кода. Он теперь будет выглядеть так:

type
  TDownLoader = class(TThread)
  private
    FToFolder: string;
    FURL: string;
  protected
    procedure Execute; override;
  published
  public
    property URL:string read FURL write FURL;
    property ToFolder:string read FToFolder write FToFolder;
  end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SaveDialog1.FileName:=copy(Edit1.Text,LastDelimiter('\⁄',Edit1.Text)+1,maxint);
  if SaveDialog1.Execute then
    Edit2.Text:=SaveDialog1.FileName;
end;

{ TDownLoader }

procedure TDownLoader.Execute;
begin
  //здесь мы начнём писать код работы
end;

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

Главный код потока

Итак, код обработчика:

procedure TDownLoader.Execute;
var
  http:TIdHTTP;
  str:TFileStream;
begin
  //Создим класс для закачки
  http:=TIdHTTP.Create(nil);
  //каталог, куда файл положить
  ForceDirectories(ExtractFileDir(ToFolder));
  //Поток для сохранения
  str:=TFileStream.Create(ToFolder, fmCreate);
  try
    //Качаем
    http.Get(url,str);
  finally
    //Нас учили чистить за собой
    http.Free;
    str.Free;
end;

end;

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

Запускаем поток

И наконец, обработчик для кнопки:

procedure TForm1.Button2Click(Sender: TObject);
var d:TDownLoader;
begin
  //Создадим класс потока.
  //Поток для начала будет остановлен
  d:=TDownLoader.Create(true);
  //Передадим параметры потоку
  d.URL:=Edit1.Text;
  d.ToFolder:=Edit2.Text;
  //Поток должен удалить себя по завершению своей работы
  d.FreeOnTerminate:=true;
  //И запустим его на закачку.
  d.Resume;
  //Теперь с процедуры мы выйдем, но поток работает
  //и живёт своей жизней
end;

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

Дополнительные возможности

Добавим для начала уведомление о закачке. Добавим в public часть формы добавим строку:

public
  { public declarations }
  procedure thrTerminate(Sender:TObject);
end;

и нажмём Ctrl+Shift+C.

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

procedure TForm1.thrTerminate(Sender: TObject);
begin
  ShowMessage('Готово');
end;

И добавим её вызов в обработчике кнопки запуска:

//Поток должен удалить себя по завершению своей работы
d.FreeOnTerminate:=true;
d.OnTerminate:=thrTerminate;

Делаем прогресс

Теперь у нас осталась ещё одна проблема – оживить прогресс-бар. Но здесь нас подстерегает один момент: с потока нельзя просто так обращаться к компонентам формы. Точнее, правило звучит так: с одного потока нельзя обращаться к данным другого потока (переменным, коду) без специальных методов. Таких методов есть два. Первый – мы останавливаем один поток, а второй на это время получает доступ к его переменным. Либо второй поток просит первый исполнить какой-то код, а сам на это время засыпает.

Способ два, которым мы и воспользуемся – это посредник. Мы шлём сообщение посреднику, чтобы он сообщил другому потоку (а может и группе), чтобы он что-то сделал. Этот способ хорош тем, что поток может обрабатывать сообщения не по принуждению, а по возможности. То есть сообщения стают в очередь. В качестве посредника мы выберем саму среду Windows.

Итак, Windows при посылке сообщения позволяет передавать два целочисленных параметра. Первый мы будем использовать как идентификатор действий, второй – как дополнительный параметр.

Поехали дальше. После uses перед Type вставим строку:

const
  MY_MESS = WM_USER + 100;

А в объявлении формы добавим новый метод:

procedure MyProgress(var msg:TMessage);message MY_MESS;

И заветное Ctrl+Shift+C

В свежесозданном обработчике пишем такое:

procedure TForm1.MyProgress(var msg: TMessage);
begin
  case msg.WParam of
    0: begin ProgressBar1.Max:=msg.LParam;ProgressBar1.Position:=0; end;
    1: ProgressBar1.Position:=msg.LParam;
  end;
end;

То-есть, если передали тип операции 0 – значит нужно инициализировать прогресс. Передали 1 – нужно выставить позицию. Как именно – указано в другом параметре (msg.LParam).

А теперь возвращаемся к нашим обработчикам IdHTTP, которые мы оставили без реализации. Туда нужно вписать всего по строчке. Ниже приведена реализация.

procedure TDownLoader.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Integer);
begin
  PostMessage(Application.MainForm.Handle,MY_MESS,1,AWorkCount);
end;

procedure TDownLoader.IdHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;
AWorkCountMax: Integer);
begin
  PostMessage(Application.MainForm.Handle,MY_MESS,0,AWorkCountMax);
end;

Заключение

Естественно, есть ещё несколько способов всё синхронизировать. Но такой способ мне кажется очень простым и надёжным, так как не будет блокировок, сообщения будут обрабатываться по мере возможности (по мере сил :-)).

В сопутствующем архиве вы найдёте полный рабочий пример. Он будет компилироваться на Delphi 2006 и Indy 10. На 7 Delphi сходу может не скомпилироваться, но если вы будете делать вручную и немного думать, то всё заработает. Причина – с Delphi 7 поставляется более старая версияIndy.

Вы можете отправить свои статьи по адресу info@delphi.int.ru и они будут опубликованы в ближайших выпусках рассылки и на сайте.


Файловый архив  >>

Разделы: Статьи | Компоненты | Plug-in's | Документация | Исходники | Программы | Игры | Изображения

Уважаемые читатели! Отправляйте полезные компоненты/модули, интересные исходники, собственные программы/игры, книги, ученики и они будут размещены на сайте. Отправить можно здесь »

Название
Описание
Раздел
Объём
Ссылки
HashLib
HashLib - быстрая и гибкая библиотека для Delphi, в которой реализованы наиболее основные алгоритмы хеширования. Библиотека была написана из-за того, что другие ищеющиеся написаны достаточно плохо. Данная библотека тестировалась на Delphi 5, 6, 7, а также работает на C++ Builder 4. По заявлению разработчиков она будет работать и на более новых версиях Delphi. Исходный код включен и может быть модифицрован безо всяких ограничений.
153 Кб
F_Text
Модуль предоставляет обширные возможности по выводу текста в DOS (для Turbo Pascal). Настраиваемые рамки, многостраничный вывод и многое другое.
10 Кб
New Audio Components

Бесплатный пакет компонент, предназначенных для записи звука, воспроизведения, преобразования и редактирования.

Основные возможности:
- Кодирование и декодирование аудио-данных различных форматов (WAV, MP3, Ogg Vorbis, FLAC, Monkey Audio);
- Воспроизведение и "граб" CD;
- Фильтрация звука, изменение частоты;
- Микширование звуковых потоков.

Основная цель New Audio Components - объединение различных библиотек и кодеков для удобной работы с ними в Delphi.

498 Кб
Edit listbox
Listbox с возможностью редактирования строк:
- редактирование (BeginEdit, EndEdit);
- вставка строк (InsertBefore, Insert After);
- удаление строк (автоматический перенос выделения после удаления).
2.5 Кб
SendEmail
Компонент для отправки электронной почты. Прост и удобен в использовании. Создан на основе библиотеки Indy. Работает только с POP3-протоколом.
2.5 Кб
HTTP Download
Программа-пример к статье "Скачиваем файлы из интернета".
8 Кб
 
Всего новых файлов: 6  
0.68 Мб
 

Отправить файл »   

Юмор

Ведущий раздела: Bruder

Офис, утро, на работе
От чего переполох
Сервер вроде бы в порядке
И Инет совсем не сдох
Не жует листочки ксерокс
Принимает звонки факс
Ноутбук у секретарши
Загрузился в первый раз
Не кричит главбух как вепрь
Что отчет вдруг не идет
Тем не менее весь офис
Странно так себя ведет
Возле маленькой каморки
Тихо все они стоят
Ждут когда они проснутся
Эти несколько ребят
Те что ночью не бухали
Не рубились в контрстрайк
Порносайт не посещали
Не писали копирайт
Те что круглый год трудились
Незаметно как "жуки"
С праздником вас сисадмины
Ящик пива мужики !!!

:))

Прислал: Feniks.

Присылайте компьютерные анекдоты, рассказы и истории по этой ссылке и они будут опубликованы в ближайших выпусках рассылки.
Ведущий рассылки, Ерёмин Андрей.

В избранное