В предыдущий статье, когда мы загружали файл вы наверное замечали что форма зависала. Что бы избавится от этой проблемы, мы добавим к программе многопоточность. Давайте сначала сделаем дизайн, а потом преступим к кодингу.
Дизайн не многим отличается от предыдущего, но мы добавили компонент Gauge он будет отображать прогресс(%) и добавили информацию сколько закачено и, размера файла. Кнопка Скопировать URL наверняка вам уже понятно что тут подразумевается(копирование ссылки на файл).
Дизайн не многим отличается от предыдущего, но мы добавили компонент Gauge он будет отображать прогресс(%) и добавили информацию сколько закачено и, размера файла. Кнопка Скопировать URL наверняка вам уже понятно что тут подразумевается(копирование ссылки на файл).
Создайте новый проект, далее создайте объект потока File - New - Other - Thread Object объект потока назовем NewThread. Теперь посмотрим на код созданного потока.
unit Unit2; interface uses Classes; type NewThread = class(TThread) private { Private declarations } protected procedure Execute; override; end; implementation { Important: Methods and properties of objects in visual components can only be used in a method called using Synchronize, for example, Synchronize(UpdateCaption); and UpdateCaption could look like, procedure NewThread.UpdateCaption; begin Form1.Caption := 'Updated in a thread'; end; } { NewThread } procedure NewThread.Execute; begin { Place thread code here } end; end.
В процедуре Execute должен быть написан наш код который мы хотим добавить в многопоточность. У меня получился такой код:
procedure NewThread.Execute; var Data: TIdMultiPartFormDataStream; // Сюда будут загружаться данные, которые нужно заполнить Http: TidHTTP; begin // Денамически создаем компонент IdHTTP Http := TIdHttp.Create(Nil); Http.HandleRedirects := True; Http.Request.Referer := 'http://realfile.ru/'; Http.Request.UserAgent := 'Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.7.62 Version/11.01'; Http.OnWork := HttpWork; Http.OnWorkBegin := HttpWorkBegin; Http.OnWorkEnd := HttpWorkEnd; // Добавили события к созданому денамическому компоненту idHTTP Data := TIdMultiPartFormDataStream.Create; Data.AddFile('file', Form1.FilePath.Text, 'multipart/form-data'); // Заполняем файлом Data.AddFormField('descr', form1.FileDescr.Text); // Описание Data.AddFormField('password', form1.password.Text); // Пароль S := Http.Post('http://realfile.ru/', Data); // ссылка и отправляем пос запрос S := Copy(S, Pos('value="',S)+7, Pos('" size="36">',S) - Pos('value="',S)-7); Synchronize(ShowUrl);//Чтобы передавать какие то значения в процедуру, она должна вводится методом Synchronize Data.Free; // Удалаем переменную, (освобождаем память) end;
Код немного различается от предыдущего. Мы создали динамически компонент idHTTP и создали к нему события, но нужно прописать процедуры событий, и добавить в uses модули.
uses Classes, IdMultiPartFormData,IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, SysUtils; type NewThread = class(TThread) private S: String; // Тут будет результат отправки запроса protected procedure Execute; override; procedure ShowUrl; procedure HTTPWorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer); procedure HTTPWork(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer); procedure HTTPWorkEnd(Sender: TObject; AWorkMode: TWorkMode); end;
Мы добавили переменную S в раздел private для того что бы можно было работать с ней в дальнейшем, так как у нас процедура ShowUrl передает результат на основную форму(программу). Процедура ShowUrl выглядит так:
procedure NewThread.ShowUrl; begin Form1.Url.Text := S; end;
Основу программы мы сделали, нам осталось добавить (сколько программа загрузила КБ, сколько всего КБ). В процедурах HTTPWorkBegin, HTTPWork, HTTPWorkEnd. Напишим следуещий код:
procedure NewThread.HTTPWork(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer); begin Form1.Gauge1.Progress := AWorkCount; // Сколько уже загрузили КБ form1.Label5.Caption := 'Закачено: ' + IntToStr(AWorkCount div 1024) + ' КБ'; end; procedure NewThread.HTTPWorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer); begin Form1.Gauge1.MaxValue := AWorkCountMax; // Получаем размер загружаемого файла, и добавляем в максимальное значения Gauge1 form1.Label6.Caption := ' из ' +IntToStr(AWorkCountMax div 1024)+ ' КБ'; end; procedure NewThread.HTTPWorkEnd(Sender: TObject; AWorkMode: TWorkMode); begin form1.Caption := 'Загрузка завершена!'; end;
Вроде все, код для многопоточности мы написали:
unit Unit2; interface uses Classes, IdMultiPartFormData,IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, SysUtils; type NewThread = class(TThread) private S: String; // Тут будет результат отправки запроса protected procedure Execute; override; procedure ShowUrl; procedure HTTPWorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer); procedure HTTPWork(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer); procedure HTTPWorkEnd(Sender: TObject; AWorkMode: TWorkMode); end; implementation uses Unit1; { Important: Methods and properties of objects in visual components can only be used in a method called using Synchronize, for example, Synchronize(UpdateCaption); and UpdateCaption could look like, procedure NewThread.UpdateCaption; begin Form1.Caption := 'Updated in a thread'; end; } { NewThread } procedureNewThread.Execute; var Data: TIdMultiPartFormDataStream; // Сюда будут загружаться данные, которые нужно заполнить Http: TidHTTP; begin Http := TIdHttp.Create(Nil); Http.HandleRedirects := True; Http.Request.Referer := 'http://realfile.ru/'; Http.Request.UserAgent := 'Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.7.62 Version/11.01'; Http.OnWork := HttpWork; Http.OnWorkBegin := HttpWorkBegin; Http.OnWorkEnd := HttpWorkEnd; // Добавили события к созданому денамическому компоненту idHTTP Data := TIdMultiPartFormDataStream.Create; Data.AddFile('file', Form1.FilePath.Text, 'multipart/form-data'); // Заполняем файлом Data.AddFormField('descr', form1.FileDescr.Text); // Описание Data.AddFormField('password', form1.password.Text); // Пароль S := Http.Post('http://realfile.ru/', Data); // ссылка и отправляем пос запрос S := Copy(S, Pos('value="',S)+7, Pos('" size="36">',S) - Pos('value="',S)-7); Synchronize(ShowUrl);//Чтобы передавать какие то значения в процедуру, она должна вводится методом Synchronize Data.Free; // Удалаем переменную, (освобождаем память) end; procedure NewThread.HTTPWork(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer); begin Form1.Gauge1.Progress := AWorkCount; form1.Label5.Caption := 'Скачано: ' + IntToStr(AWorkCount div 1024) + ' КБ'; end; procedure NewThread.HTTPWorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer); begin Form1.Gauge1.MaxValue := AWorkCountMax; form1.Label6.Caption := ' из ' +IntToStr(AWorkCountMax div 1024)+ ' КБ'; end; procedure NewThread.HTTPWorkEnd(Sender: TObject; AWorkMode: TWorkMode); begin form1.Caption := 'Загрузка завершена!'; end; procedure NewThread.ShowUrl; begin Form1.Url.Text := S; end; end.
Переходим на основную форму, на кнопку 'Загрузить' пишем следующий код:
Var Potok: NewThread; begin Potok := NewThread.Create(True); // Создаем поток Potok.Resume; // Запускаем Potok.Priority := tpLower; // Приоритет низкий end;
Кнопка Копировать URL:
ClipBoard.SetTextBuf(PChar(Url.Text));
Не забываем добавить в uses модуль, ClipBrd.
Ну вот и пожалуй все, не буду описывать кнопку выбрать и т.п так как в предыдущий статьи это было описано! Еще не подписался на RSS feed? Подпишись, и всегда будете в курсе!
Комментариев нет:
Отправить комментарий
Сделай автору приятно - оставь комментарий!