среда, 22 июня 2011 г.

Урок 15 . Финальные штрихи. Сжатие исполняемого файла




Привет.
С Вами Веселов Александр.
В предыдущем уроке я завершил тему создания программы бытового таймера вводом  в проект формы для задания настроек программы.
Сегодняшний урок я хочу посвятить финишной обработке (сжатию) скомпилированного выполняемого файла. В принципе, можно было бы этого и не делать, не обсуждать, мне возразят “зачем? Объемы ОЗУ современных вычислительных машин настолько велики, а скорости работы процессоров на столько высоки, что мегабайтную программу компьютер проглотит за мгновение!” Но, я из мезозойской эры... Я не только слышал, не только видел издалека, но и работал на БЭСМ-6 (О!!! БЭСМ-6!!! - Большая Электронно Счетная Машина - “О!!!” означает “очень” большая...). И принцип “освободи ОЗУ, если не надо” соблюдать привык, чего и Вам желаю.
Итак, откройте любой поисковик в интернет браузере и наберите в строке поиска “UPX.exe скачать”. Поройтесь в результатах и скачайте эту программу, например, с какого-нибудь торрента в папку с проектом. Конечно, если программа платная, не обижайте авторов.
Здесь же, в папке с проектом, с помощью блокнота создайте текстовый файл с расширением “bat” следующего содержания:
upx mytimer.exe
Закройте блокнот, сохраните файл, и выполните его.
В результате сжатия исполняемого файла, объем файла MyTimer.exe уменьшится в два раза.
Подведем итог, выбрав из папки с проектом файлы, необходимые для работы программы:
  • MyTimer.exe - собственно программа,
  • Clock.ico - файл с иконкой программы (необходим для работы формы “О программе”, но Вы можете переделать или доработать компонент, тогда подобные файлы Вам в будущем не понадобятся),
  • MyTimer.ini - файл, в котором хранятся настройки программы,
  • MyTimer.wav - звуковой файл, воспроизводимый таймером в качестве сигнала.
Скопируйте эти фалы в отдельную папку и приступайте к тестированию программы.
Подведем итог:
в этом уроке Вы научились
  • Обрабатывать (сжимать) исполняемый (exe) файл,
  • Отбирать из папки с проектом файлы, необходимые для работы программы,
Что же дальше?
для себя, любимого, можно написать массу полезных программ, но вряд ли можно извлечь много пользы, рассказывая об одних и тех же компонентах, приемах и т.п. Поэтому, начиная со следующего урока, я буду рассказывать о программе, работающей с базой данных.
Удачи.
До новых встреч.
* * *

понедельник, 20 июня 2011 г.

Урок 14. Сохранение настроек программы


Прежде всего предлагаю выбрать на палитре компонентов Pro Delphi Lib компонент PrDAboutBox, о создании которого я рассказывал на предыдущем уроке, и установить его на форме проекта “Таймер”, изменив соответствующим образом свойства в инспекторе объектов.
О том, как это сделать и как назначить соответствующему Action команду выполнения этого компонента, смотрите в видео приложении к этому уроку.
Затем в проект добавляется форма, позволяющая задавать и сохранять настройки программы. Как это сделать, вы найдете в предыдущих уроках.
Форма заранее подготовлена. Обращаю Ваше внимание, что в этой форме используются компоненты из библиотеки EhLib, об установке которой я говорил ранее. Ниже я приведу текст программы, который содержит форма:
unit FixedBtnsSetUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OK_CANCEL, StdCtrls, Buttons, MyLabels, ExtCtrls, MyPanel, Mask,
iniFiles, DBCtrlsEh;
const CR=#13#10;
type
TForm2 = class(TForm)
MyOkButton1: TMyOkButton;
MyCancelButton1: TMyCancelButton;
MyPanel1: TMyPanel;
MyLabel1: TMyLabel;
Btn1Capt: TEdit;
Btn1Hint: TEdit;
MyLabel2: TMyLabel;
MyLabel3: TMyLabel;
MyLabel4: TMyLabel;
MyLabel5: TMyLabel;
Btn1Min: TDBNumberEditEh;
Btn1Sec: TDBNumberEditEh;
MyLabel6: TMyLabel;
Btn2Capt: TEdit;
Btn2Min: TDBNumberEditEh;
Btn2Sec: TDBNumberEditEh;
Btn2Hint: TEdit;
Btn3Capt: TEdit;
Btn3Min: TDBNumberEditEh;
Btn3Sec: TDBNumberEditEh;
Btn3Hint: TEdit;
Btn4Capt: TEdit;
Btn4Min: TDBNumberEditEh;
Btn4Sec: TDBNumberEditEh;
Btn4Hint: TEdit;
Btn5Min: TDBNumberEditEh;
Btn5Sec: TDBNumberEditEh;
Btn5Capt: TEdit;
Btn5Hint: TEdit;
MyLabel7: TMyLabel;
MyLabel8: TMyLabel;
MyLabel9: TMyLabel;
MyLabel10: TMyLabel;
Btn6Capt: TEdit;
Btn6Min: TDBNumberEditEh;
Btn6Sec: TDBNumberEditEh;
Btn6Hint: TEdit;
procedure MyCancelButton1Click(Sender: TObject);
procedure MyOkButton1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
Uses
MyTimerUnit;
procedure TForm2.FormCreate(Sender: TObject);
begin
// Присвоить имеющиеся значения
Btn1Capt.Text:=FixedBtns.B1_Caption;
Btn2Capt.Text:=FixedBtns.B2_Caption;
Btn3Capt.Text:=FixedBtns.B3_Caption;
Btn4Capt.Text:=FixedBtns.B4_Caption;
Btn5Capt.Text:=FixedBtns.B5_Caption;
Btn6Capt.Text:=FixedBtns.B6_Caption;
Btn1Min.Value:=FixedBtns.B1_Min;
Btn2Min.Value:=FixedBtns.B2_Min;
Btn3Min.Value:=FixedBtns.B3_Min;
Btn4Min.Value:=FixedBtns.B4_Min;
Btn5Min.Value:=FixedBtns.B5_Min;
Btn6Min.Value:=FixedBtns.B6_Min;
Btn1Sec.Value:=FixedBtns.B1_Sec;
Btn2Sec.Value:=FixedBtns.B2_Sec;
Btn3Sec.Value:=FixedBtns.B3_Sec;
Btn4Sec.Value:=FixedBtns.B4_Sec;
Btn5Sec.Value:=FixedBtns.B5_Sec;
Btn6Sec.Value:=FixedBtns.B6_Sec;
Btn1Hint.Text:=FixedBtns.B1_Hint;
Btn2Hint.Text:=FixedBtns.B2_Hint;
Btn3Hint.Text:=FixedBtns.B3_Hint;
Btn4Hint.Text:=FixedBtns.B4_Hint;
Btn5Hint.Text:=FixedBtns.B5_Hint;
Btn6Hint.Text:=FixedBtns.B6_Hint;
end;
procedure TForm2.MyCancelButton1Click(Sender: TObject);
begin
Form1.MyMessenger1.MessageString:='Изменения не будут сохранены'
+CR
+'Продолжить редактирование?';
Form1.MyMessenger1.TitleString:='Внимание!!!';
Form1.MyMessenger1.MessageType:=mtWarning;
Form1.MyMessenger1.Buttons:=[mbYes]+[mbNo];
If Not (Form1.MyMessenger1.ShowMessage=6)
then
close;
end;
procedure TForm2.MyOkButton1Click(Sender: TObject);
Var
ErrKod: Integer;                              // Код ошибки
ErrMes: String;                               // Описание ошибки
Label
ErrorsLab;                                      // Метка, после которой начинается текст обработчика ошибок
begin
// Стартовые значения
ErrKod:=0;
ErrMes:='Операция завершена успешно'
+CR
+'Изменения вступят в силу при следующем запуске программы';
// Первая из возможных проверок
If (Btn1Capt.Text='') //OR (Btn1Capt.Text='-')
then
begin
ErrKod:=1;
ErrMes:='Одно из полей <Подпись> осталось пустым'+CR+'Пожалуйста, заполните это поле';
GoTo ErrorsLab;
end;
If (VarIsEmpty(Btn1Min.Value)) //OR (Btn1Capt.Text='-')
then
begin
ErrKod:=1;
ErrMes:='Одно из полей <Минуты> осталось пустым'+CR+'Пожалуйста, заполните это поле';
GoTo ErrorsLab;
end;
If (VarIsEmpty(Btn1Sec.Value)) //OR (Btn1Capt.Text='-')
then
begin
ErrKod:=1;
ErrMes:='Одно из полей <Секунды> осталось пустым'+CR+'Пожалуйста, заполните это поле';
GoTo ErrorsLab;
end;
If (Btn1Hint.Text='') //OR (Btn1Capt.Text='-')
then
begin
ErrKod:=1;
ErrMes:='Одно из полей <Подсказка> осталось пустым'+CR+'Пожалуйста, заполните это поле';
GoTo ErrorsLab;
end;
// После успешного прохождения всех проверок - занесение данных в ini файл
ini:=TiniFile.Create(GetCurrentDir + '\MyTimer.ini');
Ini.WriteString('FixedBtns','B1Capt',Btn1Capt.Text);
Ini.WriteInteger('FixedBtns','B1Min',Btn1Min.Value);
Ini.WriteInteger('FixedBtns','B1Sec',Btn1Sec.Value);
Ini.WriteString('FixedBtns','B1Hnt',Btn1Hint.Text);
Ini.WriteString('FixedBtns','B2Capt',Btn2Capt.Text);
Ini.WriteInteger('FixedBtns','B2Min',Btn2Min.Value);
Ini.WriteInteger('FixedBtns','B2Sec',Btn2Sec.Value);
Ini.WriteString('FixedBtns','B2Hnt',Btn2Hint.Text);
Ini.WriteString('FixedBtns','B3Capt',Btn3Capt.Text);
Ini.WriteInteger('FixedBtns','B3Min',Btn3Min.Value);
Ini.WriteInteger('FixedBtns','B3Sec',Btn3Sec.Value);
Ini.WriteString('FixedBtns','B3Hnt',Btn3Hint.Text);
Ini.WriteString('FixedBtns','B4Capt',Btn4Capt.Text);
Ini.WriteInteger('FixedBtns','B4Min',Btn4Min.Value);
Ini.WriteInteger('FixedBtns','B4Sec',Btn4Sec.Value);
Ini.WriteString('FixedBtns','B4Hnt',Btn4Hint.Text);
Ini.WriteString('FixedBtns','B5Capt',Btn5Capt.Text);
Ini.WriteInteger('FixedBtns','B5Min',Btn5Min.Value);
Ini.WriteInteger('FixedBtns','B5Sec',Btn5Sec.Value);
Ini.WriteString('FixedBtns','B5Hnt',Btn5Hint.Text);
Ini.WriteString('FixedBtns','B6Capt',Btn6Capt.Text);
Ini.WriteInteger('FixedBtns','B6Min',Btn6Min.Value);
Ini.WriteInteger('FixedBtns','B6Sec',Btn6Sec.Value);
Ini.WriteString('FixedBtns','B6Hnt',Btn6Hint.Text);
ini.Free;
//    exit;                           // Нужен, если нет необходимости выводить сообщение об успешном завершении операции
// Вывод сообщений обработчика ошибок
ErrorsLab:
case ErrKod of            // Start Case
0:
begin
// Сообщение об успешном завершении
Form1.MyMessenger1.TitleString:='...';
Form1.MyMessenger1.MessageType:=mtInformation;
end;
else
begin
// Сообщения об ошибках
Form1.MyMessenger1.TitleString:='Ошибка ('+IntToStr(ErrKod)+')';
Form1.MyMessenger1.MessageType:=mtError;
end;
End;                   // End case
Form1.MyMessenger1.MessageString:=ErrMes;
Form1.MyMessenger1.Buttons:=[mbOk];
Form1.MyMessenger1.ShowMessage;
end;
end.
После изменения некоторых свойств формы (если Вы создавали ее заново, то это необходимо), нужно настроить вызов формы “Настройка быстрых кнопок” из основной формы приложения, для чего:
  • дайте описание модуля формы в разделе Implementation
  • перенесите оператор создания формы из кода проекта в процедуру Service_SpeedBtnsExecute
implementation
Uses
FixedBtnsSetUnit;
procedure TForm1.Service_SpeedBtnsExecute(Sender: TObject);
begin
// Настройка быстрых кнопок
Application.CreateForm(TForm2, Form2);
Form2.ShowModal;
Form2.Free;
end;
Третьим шагом в данном уроке будет добавление в главную форму проекта возможности выбора и прослушивания звукового файла. Для этого нужно расположить на форме компонент TOpenDialog (палитра Dialogs) и добавить в процедуру обработки соответствующего действия (Action) Service_SoundExecute следующий код:
procedure TForm1.Service_SoundExecute(Sender: TObject);
begin
// Выбор звукового файла для сигнала
OpenDialog1.Title:='Выбор звукового файла...';                   // Назначение заголовка окна диалога
OpenDialog1.InitialDir := ExtractFilePath(Application.ExeName);   // Задание стартовой папки
// Настройка фильтра типов файлов
OpenDialog1.Filter := 'Звуковые файлы (*.wav)|*.wav|Файлы (*.mp3)|*.mp3|Файлы (*.midi)|*.mid|Все файлы (*.*)|*.*';
OpenDialog1.FilterIndex := 1;                                    // Выбор  файлов wav - стартовый тип фильтра
if OpenDialog1.Execute                                           // Открытие окна выбора файла
then
begin
// Прослушивание
MyMessenger1.MessageString:='Хотите прослушать?';
MyMessenger1.TitleString:='?';
MyMessenger1.MessageType:=mtConfirmation;
MyMessenger1.Buttons:=[mbYes]+[mbNo];
If MyMessenger1.ShowMessage=6
then
begin
SetRecBtnStatus(2);
SetBtnStatus;
MediaPlayer1.FileName:=OpenDialog1.FileName;
MediaPlayer1.Open;
MediaPlayer1.Play;
end;
// Запись пути файла в INI
MyMessenger1.MessageString:='Установить данную мелодию как сигнал?';
MyMessenger1.TitleString:='?';
MyMessenger1.MessageType:=mtConfirmation;
MyMessenger1.Buttons:=[mbYes]+[mbNo];
If MyMessenger1.ShowMessage=6
then
begin
ini:=TiniFile.Create(ExtractFilePath(Application.ExeName) + '\MyTimer.ini');
ini.WriteString('Sound', 'SoundFullPath', OpenDialog1.FileName);
ini.Free;
end;
end;
SetRecBtnStatus(1);
SetBtnStatus;
end;
И последнее, что нужно сделать, чтобы завершить работу над проектом бытового таймера - научить собственно таймер подсчитывать интервал срабатывания на основе выбираемых или вводимых данных.
Для этого нужно создать целочисленную функцию:
Function TForm1.CalcInterval(): Integer;
begin
Result:=(Minutes.Value*60+Secunds.Value)*1000;
end;
Данная функция на основе значений полей Minutes и Secunds вычисляет интервал срабатывания таймера, переводя его в значение миллисекунд (*1000). А о том, где в программе используется данная функция, смотрите наглядный видео урок.

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

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

пятница, 10 июня 2011 г.

Урок 13. Компонент “О программе”


В предыдущем уроке я рассказал как добавить в приложение форму “О программе”. Несколько форм в одном приложении - дело повсеместное и привычное. Но что делать, если разрабатывается большая система, состоящая из множества программ? Пусть даже не система, пусть Вы написали уже много программ, и Вам хочется, чтобы такая форма как “О программе” или какой-то общий справочник, кодификатор, были одинаковыми во всех программах. Копировать каждый раз файл формы *.pas из папки с одним проектом в папку с другим? Или каждый раз добавлять в новый проект из какого-то одного директория? И первый, и второй способы неудобны, хотя и они приемлемы. Гораздо удобнее на случай раз и навсегда отлаженной формы, сделать на ее основе компонент, зарегистрировать его в панели Tools рабочей среды, и пользоваться.
Проведите эксперимент по удалению формы из проекта, рассмотренного на предыдущем уроке. После компиляции и запуска программы, форма “О программе” будет вызвана на экран как ни в чем не бывало. Поскольку я руками прописал в uses ссылку на модуль формы About, я должен это описание руками же и удалить, не забыв удалить и операторы создания и вызова этой формы из соответствующей процедуры.
Затем создайте модуль компонента:
unit PrDAbout;
interface
Uses SysUtils
, WinTypes
, WinProcs
, Messages
, Classes
, Graphics
, Controls
, Forms
, aboutLes                                       // Объявление о намерении
// использовать модуль
// About
;
Type TPrDAbout = class(TComponent)                // Новый класс
Public
Constructor Create (AOwner: TComponent); override;    // Объявление конструктора
Function Execute: Boolean;                      // Объявление функции, реализующей
// метод "выполнить"
end;
Procedure Register;                               // Объявление процедуры регистрации
implementation
Constructor TPrDAbout.Create (AOwner: TComponent);// Конструтор компонента
Begin
Inherited Create(AOwner);                       // Оператор, устанавливающий
// наследование всех свойств
// и методов от предка TComponent
end;
Function TPrDAbout.Execute: Boolean;              // Текст метода
Begin
AboutFrm:=  TAboutFrm.create( Application);     // Создание формы, описанной
// в модуле About
Try
Result:= (AboutFrm.ShowModal = IDOK);         // Оценка возвращаемого результата
// и передача его в результат
// работы функции (тип Boolean)
finally
AboutFrm.Free;                                // Создалась форма или нет,
// память надо очищать
end;
end;
Procedure Register;                               // Регистрация компонента TPrDAbout
// на закладке  Pro-Delphi Lib
Begin
RegisterComponents('Pro-Delphi Lib',[TPrDAbout]);
end;
end.
И сохраните его.
Создайте новый пакет, добавьте в него новый модуль, инсталлируйте пакет в среду разработки Delphi. Обратите внимание, что при создании формы About я использовал ранее созданные компоненты (например: компонент гиперссылку), поэтому в процессе инсталляции пакета, на экран будет выведено окно с информацией о безусловном включении модулей этих компонентов в пакет, как необходимых для создания данного компонента.
Вообще-то, я не склонен делать одни новые компоненты на основе других, разработанных ранее. Во-первых, даже при всей моей любви только к параллельным и перпендикулярным направлениям, легко запутаться, что где хранится и откуда берется. Во-вторых, изменения, вносимые в логику работы более ранних компонентов, никак не отразятся на более поздних. В-третьих, если Вам необходимо избавиться навсегда от какого-то компонента (скажем, разработали другой, более крутой), а он “завязан”  на кучу других, то это становится настоящей проблемой.
Наглядный видео урок Вы можете посмотреть или скачать.

Что же дальше?
На следующем уроке я планирую рассказать о создании и добавлении в проект “Таймер” еще одной формы. С помощью этой формы можно будет задать настройки программы и сохранить их.
А через урок я завершу цикл, посвященный проекту “Таймер” рассказом о том, как можно обработать уже готовый exe-файл.
Затем нас ждет знакомство с разработкой более сложного проекта, в работе которого будет использовано подключение к базе данных и работа с записями, хранимыми в ней.
Удачи всем!

Урок 12. Добавление в проект формы “О программе”


В предыдущем уроке я обещал рассказать о том, как добавить в проект, состоящий из одной формы, еще одну и из нее сделать форму “О программе”.
Наберитесь терпения, этот урок Delphi будет не таким простым, как предыдущий.
Приступим.
Откройте проект с программой “Таймер”, и выберите пункт меню
File - New - Form Delphi For Win 32. В проект будет добавлена новая форма.
В Инспекторе объектов измените свойства формы:
Caption - О программе,
Position - poScreenCenter (при открытии форма будет всегда выводиться в центре экрана).
Name - AboutFrm.
Visible - False (после создания форма будет оставаться невидимой)
KeyPreview - True (форма будет реагировать на нажатие клавишей).
Расположите на форме панель, несколько меток, гиперссылку и кнопку.
Сохраните модуль формы под именем About.pas.
Перейдите в раздел Implementation главной формы таймера, добавьте ключевое слово Uses и дайте описание модуля About в нем. В принципе, Вы вправе дать это описание выше, в разделе interface Uses, но... О разнице двух объявлений читайте в учебниках.
Откройте код проекта, воспользовавшись меню Project - View Source.
Найдите в тексте строчку:
Application.CreateForm(TAboutFrm, AboutFrm);.
выделите ее и вырежте (Ctrl-X) для того, чтобы новая форма, добавленная в проект, не создавалась и не выводилась на экран сразу после старта программы.
Перейдите в главную форму таймера, найдите заготовку процедуры, обрабатывающей вызов справки и вставьте этот оператор в тело данной процедуры.
Добавьте ниже два оператора:
AboutFrm.ShowModal;                        // Вывод формы на эран
// в модальном окне (другие окна недоступны)
AboutFrm.Free;                                   // Освобождение памяти
// после окончания работы с  формой
На этом урок можно закончить. Но! В наглядном видео уроке, который Вы можете посмотреть или скачать , показан еще один момент - удаления формы из проекта.
PS Полный текст модуля формы “О программе” приведен ниже:
unit about;
interface
uses Windows, Classes, Graphics, Forms, Controls, StdCtrls,
Dialogs, Buttons, ExtCtrls, SysUtils, OK_CANCEL, MyLabels, SHELLAPI,
MyLinkLabel, PrDLinkLabel;
type
TAboutFrm = class(TForm)
Panel1: TPanel;
ProgramIcon: TImage;
ProductName: TLabel;
Version: TLabel;
Copyright: TLabel;
MyVersion: TLabel;
Label1: TLabel;
MyOkButton1: TMyOkButton;                    // Кнопка с рисунком, 
// можно заменить на стандартную
PrDLinkLabel1: TPrDLinkLabel;
procedure MyOkButton1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure FormActivate(Sender: TObject);
private
{ Private declarations }
Function CurrentFileInfo(AFileName: string): string;      // Источник - База знаний Delphi
// Как вариант, можно взять здесь:
// http://www.delphisources.ru/pages/faq/base/versioninfo.html
public
{ Public declarations }
end;
var
AboutFrm: TAboutFrm;
implementation
{$R *.dfm}
Function TAboutFrm.CurrentFileInfo(AFileName: string): string;
{функция для того чтоб получить версию файла программы}
{запускать функцию с такими параметрами, если нужна версия своей программыFileVersion(Paramstr(0));}
// Компиллятор выдает некритическую ошибку при использовании этой функции
var
szName: array[0..255] of Char;
P: Pointer;
Value: Pointer;
Len: UINT;
GetTranslationString: string;
FFileName: PChar;
FValid: boolean;
FSize: DWORD;
FHandle: DWORD;
FBuffer: PChar;
begin
try
FFileName := StrPCopy(StrAlloc(Length(AFileName) + 1), AFileName);
FValid := False;
FSize := GetFileVersionInfoSize(FFileName, FHandle);
if FSize > 0 then
try
GetMem(FBuffer, FSize);
FValid := GetFileVersionInfo(FFileName, FHandle, FSize, FBuffer);
except
raise;
end;
Result := '';
if FValid then
VerQueryValue(FBuffer, '\VarFileInfo\Translation', p, Len)
else
p := nil;
if P <> nil then
GetTranslationString := IntToHex(MakeLong(HiWord(Longint(P^)),
LoWord(Longint(P^))), 8);
if FValid then
begin
StrPCopy(szName, '\StringFileInfo\' + GetTranslationString +
'\FileVersion');
if VerQueryValue(FBuffer, szName, Value, Len) then
Result := StrPas(PChar(Value));
end;
finally
try
if FBuffer <> nil then
FreeMem(FBuffer, FSize);
except
end;
try
StrDispose(FFileName);
except
end;
end;
end;
procedure TAboutFrm.FormActivate(Sender: TObject);
begin
MyVersion.Caption:=CurrentFileInfo(Paramstr(0));
ProductName.Caption:=Application.Title;
Label1.Caption:='Москва - 2010 год';
icon:=Application.Icon;
ProgramIcon.Picture.LoadFromFile('Clock.ico');
end;
procedure TAboutFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:= caFree;
end;
procedure TAboutFrm.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case Key of            // Start Case
VK_ESCAPE:
begin
if MessageDlg('Закрыть?',mtConfirmation, [mbYes]+[mbNo], 0)=6
then
close;
end;
else
End;                   // End case
end;
procedure TAboutFrm.MyOkButton1Click(Sender: TObject);
begin
close;
end;
end.

Что же дальше?
еще раз вернемся к вопросу удаления формы из проекта и  на основе формы “О программе” создадим компонент.

пятница, 3 июня 2011 г.

Урок 11. Создание компонента гиперссылки


Для полного счастья :-), чтобы закончить предварительный разговор о создании собственных компонентов, начатый в уроках 9 и 10, мне не хватает только одного - рассказать о том, как создать компонент гиперссылку. Вообще-то, темами последних уроков я постепенно подводил моего читателя к теме создания формы “О программе”, разговор о которой уже близок, а затем и компонента на ее основе.
Поскольку, на предыдущих уроках, я подробно рассказал и показал, как создаются модули компонентов, как создаются пакеты, компилируются и инсталлируются, то мне ничего не остается сделать, как привести в этом уроке исходный текст модуля компонента гиперссылки, который Вы можете выделить и скопировать в файл, открытый в среде разработки Delphi.
Вот он, выделен цветом для удобства:
unit PrDLinkLabel;                 // дайте файлу имя PrDLinkLabel.pas
interface                                // Область объявлений
uses
SysUtils
, Classes
, Controls
, StdCtrls
, Windows
, Messages
, Variants
, Graphics
, Forms
, Dialogs
, SHELLAPI
;
type
TPrDLinkLabel = class(TLabel)         // Объявление нового класса, предком которого
// выбран компонент TLabel
private
procedure PrDLinkLabelClick(Sender: TObject); // Тем и хороши объекты, 
// что инкапсулируют в себе данные и методы
protected                                       // В этой области ничего не объявлено
public
Constructor Create( AOwner: TComponent); override; // Конструктор компонента, 
// как  и в предыдущих случаях, устанавливается 
// общий предок - предок визуальных компонентов
// TComponent.
published                                      // В этой области ничего не объявлено
end;                                                // Окончание объявления класса
procedure Register;                       // Объявление процедуры Register, которая 
// установит компонент в среду разработки Delphi
implementation                              // Область, где расположены
// тексты процедур и функций
constructor TPrDLinkLabel.Create( AOwner: TComponent );
begin
inherited Create(AOwner);         // Оператор, создающий компонент на основе предка
AutoSize:=False;                       // Перекрытие свойства AutoSize
Cursor:=crHandPoint;               // Назначение вида курсора
Font.Color:=clNavy;                  // Изменения цвета надписи
Font.Style:=[fsBold];                  // Перекрытие стиля надписи (шрифт станет жирным)
onClick:=PrDLinkLabelClick;     // Назначение метода PrDLinkLabelClick; событию onClick
Hint:='http://pro-delphi.ru/';         // Всплывающая подсказка
Caption:='http://pro-delphi.ru/';   // Текст надписи в метке
// Последние два свойства будут иметь эти значения по
// умолчанию, однако, Вы можете их не задавать
// или указать свои значения
end;
procedure TPrDLinkLabel.PrDLinkLabelClick(Sender: TObject);
// Процедура, обрабатывающая клик по надписи
begin
If (Sender is TLabel) then
with (Sender as Tlabel) do
ShellExecute(Application.Handle,PChar('open'),  PChar(Hint), PChar(0),nil,SW_NORMAL); //  -
// функция, вызывающая открытие приложения (браузера)
end;
procedure Register;
begin
RegisterComponents('Pro-Delphi Lib', [TPrDLinkLabel]);  // Процедура, 
// регистрирующая компонент компонент TPrDLinkLabel 
// на вкладке Pro-Delphi Lib в среде разработки Delphi
end;
end.
Следующим шагом Вы должны создать пакет, добавить в него файл данного компонента, и установить его.
* * *
Наглядный видео урок Вы можете посмотреть или скачать.

Что же дальше?
В следующих уроках разговор пойдет о:
  • создании формы “О программе”,
  • создании компонента на основе формы “О программе”,
  • мы вернемся к проекту “Таймер” и напишем обработчики тех пунктов меню, которые еще остались пустыми (речь пойдет о задании и сохранении настроек программы),
  • научимся сжимать готовый exe файл,
  • создадим новый проект “Учет расходов”, в котором будем знакомиться с базами данных и всем, что с ними связано,
но, похоже, я сильно забежал вперед... :-)