Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Создание CGI счётчика в Delphi


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

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

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

Для начала давайте посмотрим - как этот счётчик может выглядеть:

Вызывается счётчик тэгом IMG примерно так:


<img src="http://ww5.borland.com/ scripts/CounterCGI.exe?FileName=Article">

CGI скрипт так же может получать определённый набор параметров:

  • Txt e.g. "You are visitor %d today, and %d ever."
  • FontName e.g. "Courier"
  • FontColor e.g. "clGreen" or "$404040"
  • BackgroundColor e.g. "clYellow" or "$808080"

А вот так выглядит вызов скрипта с несколькими параметрами:


http://ww5.borland.com/scripts/CounterCGI.exe?FileName=Article&BackgroundColor=$808080&FontColor=$404040&FontName=Courier

Итак, давайте разбираться с кодом.

Начать создавать новое CGI приложение следует с выбора File | New | Web Server Application | CGI stand-alone executable. После этого Вы получите чистый Web модуль. Добавьте новый TWebActionItem в подсвеченном свойстве действий (Actions) в TWebModule, нажав на Add Item. Затем двойным щелчком на событие OnAction создайте обработчик действия.

Изображение JPEG, получается как снимок изображения с TPanel, с TMemo внитри него. Таким способом легче придать 3D вид счётчику. Для начала нам необходимо добавить следующую строку в раздел implementation:


implementation

uses
  ExtCtrls, StdCtrls, Controls, Forms, Graphics, JPEG;

Теперь, мы определим некоторые основные процедуры, которые будут использоваться в коде. GetPaths будет обеспечивать нас двумя жизненно важными путями. Первый путь будет указывать где хранится сам скрипт по отношению к корневой директории web сервера (т.е. относительный путь). Скорее всего это будет "scripts" или "cgi-bin" в зависимости от того, куда Вы его положите. Второй - это локальный путь в Windows. Он может выглядеть как "C:\InetPub". Для нас важны оба пути, чтобы обеспечить переносимость CGI скрипта из директории в директорию и с одного сервера на другой.


procedure GetPaths(Request: TWebRequest; var ScriptPath, LocalPath: string);
var
  ScriptFileName: string;
begin
  ScriptPath := Request.ScriptName;
  ScriptFileName := ExtractFileName(ParamStr(0));
  // Убираем EXE/DLL имя, чтобы получить путь
  Delete(ScriptPath, Pos(ScriptFileName, ScriptPath) - 1, Length(ScriptFileName) + 1);
  // Убираем главную косую
  Delete(ScriptPath,1,1);

  LocalPath := ExtractFilePath(ParamStr(0));
  // Удаление ScriptPath даёт нам корневой путь
  Delete(LocalPath, Pos(ScriptPath, LocalPath) - 1, Length(ScriptPath) + 1);
end;

Процедура SetVariable будет использоваться для инициализации нужных нам переменных.


procedure SetVariable(var S : string; const Value, default: string);
begin
  S := Value;
  if S = '' then
    S := default;
end;

Вся суть CGI скрипта заключается в событие OnAction. Давайте рассмотрим его по шагам.


procedure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);

Сперва объявим некоторые локальные переменные.


var
  ScriptPath, LocalPath, FileName, Txt, FontColor,
  BackgroundColor, FontName, FontSize: string;
  Today, LastEver, Ever, LastToday: Integer;
  LastDate: TDate;
  MS: TMemoryStream;
  Panel: TPanel;
  Memo: TMemo;
  Bitmap: TBitmap;
  Form: TForm;
  fp: TextFile;

Теперь вызовем GetPaths, чтобы выяснить путь к скрипту, а так же локальный путь. В данном примере мы будем помещать наши счётчики в директорию "counters". Физический путь будет выглядеть примерно так "C:\InetPub\counters".


begin
  GetPaths(Request, ScriptPath, LocalPath);
  LocalPath := LocalPath + 'counters\';

Затем, мы получаем все параметры, переданные вместе с вызовом скрипта. Параметры поступают к нам через свойство Request.QueryFields. Обратите внимание, что если какой-то параметр не был передан, то SetVariable устанавливает его по умолчанию.


with Request.QueryFields do
begin
  FileName := LocalPath+Values['FileName']+'.txt';
  SetVariable(Txt,Values['Txt'],'You are visitor %d today, and %d ever.');
  SetVariable(FontName,Values['FontName'],'Arial');
  SetVariable(FontSize,Values['FontSize'],'10');
  SetVariable(FontColor,Values['FontColor'],'clWhite');
  SetVariable(BackgroundColor,Values['BackgroundColor'],'clBlack');
end;

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


try
  // Write a new empty counter file if it doesn't exist
  if not FileExists(FileName) then
  begin
    AssignFile(fp, FileName);
    Rewrite(fp);
    WriteLn(fp, 0);
    WriteLn(fp, Date);
    WriteLn(fp, 0);
    CloseFile(fp);
  end;

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


// Читаем старые значения счётчика
AssignFile(fp,FileName);
Reset(fp);
ReadLn(fp,LastEver);
Ever := LastEver+1;
ReadLn(fp,LastDate);
ReadLn(fp,LastToday);
if Date = LastDate then
  Today := LastToday+1
else
  Today := 1;
CloseFile(fp);

И в заключении, надо записать новые значения в файл, содержащий данные счётчика.


// Записываем новые значения счётчика
AssignFile(fp, FileName);
Rewrite(fp);
WriteLn(fp, Ever);
WriteLn(fp, Date);
WriteLn(fp, Today);
CloseFile(fp);

Теперь приступим к созднию того, что в конечном итоге будет называться JPEG. Для начала сделаем невидимым TForm которая содержит TPanel и TMemo. Так же устанавливаем FontName и FontSize.


Form := TForm.Create(nil);
with Form.Font do
begin
  name := FontName;
  Size := StrToInt(FontSize);
end;

Удостоверимся в том, что текст, который мы помещаем в memo контрол, содержит значения счётчика, считанные из файла.


Txt := Format(Txt, [Today, Ever]);

Далее мы создаём панель. Ширина и высота будут определяться шириной текста, который мы помещаем в неё. Так же устанавливаем скашивание для 3D эффекта.


Panel := TPanel.Create(nil);
with Panel do
begin
  BevelInner := bvRaised;
  BevelOuter := bvLowered;
  Parent := Form;
  Width := Form.Canvas.TextWidth(Txt) + 9;
  Height := Form.Canvas.TextHeight(Txt) + 9;
end;

Помещаем memo в панель, и устанавливаем её ширину и высоту, а так же цвет, который указан в BackgroundColor.


Memo := TMemo.Create(nil);
with Memo do
begin
  Top := 2;
  Left := 2;
  Width := Panel.Width-5;
  Height := Panel.Height-5;
  Alignment := taCenter;
  Color := StringToColor(BackgroundColor);
  BorderStyle := bsNone;
  Parent := Panel;
end;

Теперь необходимо сделать изображение эелемента управления, который мы создали. Для этого создаём TBitmap и закрашеваем его панелью. За одно рисуем текст на битмапе.


Bitmap := TBitmap.Create;
with Bitmap do
begin
  Width := Panel.Width-1;
  Height := Panel.Height-1;
  Canvas.Lock;
  Panel.PaintTo(Canvas.Handle,0,0);
  Canvas.Unlock;
  Canvas.Brush.Style := bsClear;
  with Canvas.Font do
  begin
    name := FontName;
    Size := StrToInt(FontSize);
    Color := StringToColor(FontColor);
  end;
  Canvas.TextOut(4,3,Txt);
end;

Затем преобразовываем bitmap в JPEG. JPEG будет записан в memory stream. Этот поток будет связан с браузером и передаваться посетителю странички в виде картинки.


with Response do
begin
  MS := TMemoryStream.Create;
  with TJPEGImage.Create do
  begin
    CompressionQuality := 75;
    Assign(Bitmap);
    SaveToStream(MS);
    Free;
  end;
  ContentType := 'image/jpeg';
  MS.Position := 0;
  SendResponse;
  SendStream(MS);
end;

Освобождаем ресурсы:


Panel.Free;
Bitmap.Free;
Form.Free;

На всякий случай обрабатываем исключительные ситуации


except
  on E: Exception do
    Response.Content := E.message;
  end;
  Handled := True;
end;

Вот собственно и всё. Наслаждайтесь счётчиком, сделанным в Delphi 5 :)

Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay