Статьи по Делфи
Меню сайта


Категории каталога
Мои статьи [2]
Функции и процедуры Win Api [20]
Работа с мышью [10]
Реестр и Делфи [11]
Работа с файлами [38]
Делфи и Хакер [10]
Инсталлятор собственными руками [6]
Хитрости в делфи [3]
Работа с системой [19]


Форма входа


Поиск по каталогу


Друзья сайта


Наш опрос
Понравились ли вам треки
Всего ответов: 156


Приветствую Вас, Гость · RSS 2024-03-28, 2:17 PM
Начало » Статьи » Хитрости в делфи

Delphi: заметки программиста. Часть 1
Известно, что Delphi создает множество файлов с расширениями pas, dfm, dpr и т.д. Обычно программиста интересуют файлы кода (pas) и описания форм (dfm), а остальные остаются вне его поля зрения, а зря — они несут важную информацию, которую можно (а в ряде случаев — нужно) изменять.

Начнем с файла проекта (dpr). Фактически он содержит собственно программу, в то время как связанные с проектом многочисленные файлы форм и DLL представляют собой подпрограммы.

Структура файла проекта, содержащего единственную форму, такова, как показано в листинге 1.
Листинг 1
program Project1;

uses
Forms,
Unit1 in 'Unit1.pas' {Form1};

{$R *.RES}

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

Проект (программа) начинается обращением к методу Initialize глобального объекта Application и заканчивается после завершения его метода Run. Этот метод — центральный: он визуализирует главную форму приложения и осуществляет диспетчеризацию сообщений Windows. От того, какая работа выполняется строками кода, расположенными перед обращением к нему, зависят время загрузки приложения, и вид экрана до появления главного окна.

Метод Initialize предусмотрен, как говорится, на всякий случай и по умолчанию ничего не осуществляет. Чтобы заставить его работать, следует поместить указатель на соответствующую процедуру без параметров в глобальную переменную InitProc. Это можно сделать в секции инициализации любого модуля (код этих секций активизируется до начала работы основной программы) или непосредственно в теле главного проекта (листинг 2):
Листинг 2
procedure Init;
begin
// Выполняет какую-то работу;
end;

begin
InitProc := @Init;
Application.Initialize; // Обращение к Init
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

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

В реальном проекте со множеством форм между обращениями к Initialize и Run обычно расположены многочисленные вызовы метода CreateForm, с помощью которого создаются используемые в проекте формы. Каждый вызов этого метода увеличивает время загрузки приложения. В начальный момент на экране будет видно только одно окно главной формы приложения (оно создается первым обращением к CreateForm), а остальные объекты-окна можно создавать в ходе работы программы перед визуализацией соответствующего окна.

По умолчанию в переключателе Auto create forms (вызывается с помощью опции Project|Options среды Delphi) на закладке Preference окна Tools|Environment установлен флажок, что заставляет Delphi помещать любую новую форму в список Auto-create forms и формировать соответствующий оператор обращения к CreateForm в файле проекта. Если очистить этот переключатель перед началом работы над проектом или перенести ненужные формы в список Available forms окна Project|Options, можно существенно (иногда — в десятки раз) сократить время загрузки приложения.
Вид экрана до появления главного окна

В приводимом ниже листинге 3 (пример заимствован из справочной системы Delphi) в программе создается 5 окон. В форме Form5 имеется индикатор ProgressBar1, с помощью которого визуализируется процесс загрузки программы, точнее — создания остальных окон.
Листинг 3

begin
with TForm5.Create(nil) do
try
ProgressBar1.Max := 100;
Show; // Показываем форму Form5 с индикатором ProgressBar1
Update; // Прорисовываем форму Form5
Application.CreateForm(TForm1, Form1);
ProgressBar1.StepBy(25);
Application.CreateForm(TForm2, Form2);
ProgressBar1.StepBy(25);
Application.CreateForm(TForm3, Form3);
ProgressBar1.StepBy(25);
Application.CreateForm(TForm4, Form4);
ProgressBar1.StepBy(25);
finally
Free; // Разрушаем ненужную форму Form5
end;
Application.Run;
end.


Защита программы паролем

Как видно из примера, программист может поместить любой код до обращения к методу Application.Run. В частности, он может показать диалоговое окно с запросом пароля и блокировать вызов Application.Run, если введенный пользователем пароль неверен. В следующем примере (листинг 4 — Password.dpr) в проекте используются две формы: стандартная форма InputQuery и главная форма MainForm. Форма InputQuery создается при обращении к одноименной функции, определенной в модуле Dialogs. Она представляет собой небольшое диалоговое окно с однострочным редактором TEdit и двумя кнопками — ОК и Cancel. В окне пользователь должен ввести пароль (Delphi) и нажать Enter.
Листинг 4
program Password;

uses
Forms,
Dialogs, // В этом модуле определена функция InputQuery
Unit1 in 'Unit1.pas' {MainForm};

{$R *.RES}
var
Passwrd: String;
begin
// Запрашиваем пароль:
if InputQuery('Окно ввода пароля','Введите пароль:',Passwrd) then
// Проверяем его:
if Passwrd = 'Delphi' then
begin // Все в порядке, пароль верен
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end else
ShowMessage('Пароль не верен!');
end.

Пробные версии программ

Вышеописанным способом можно создавать пробные версии программ, которые будут функционировать только до определенной даты или до исчерпания заданного количества запусков. В листинге 5 представлен файл проекта (Trial.dpr), в котором пробная версия программы может запускаться не более 5 раз. Для запоминания номера очередного прогона используется системный реестр.
Листинг 5
program Trial;

uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
Registry, Dialogs; // Для TRegistry и ShowMessage

{$R *.RES}
var
Reg: TRegistry;
N: Integer;
begin
Reg := TRegistry.Create;
with Reg do
begin
OpenKey('software', True);
OpenKey('TrialProg', True);
if ValueExists('MaxRun') then // Первый запуск?
begin // - Нет
N := ReadInteger('MaxRun')-1;
if N>=0 then
WriteInteger('MaxRun', N)
end else begin // -Да, первый запуск
N := 5;
WriteInteger('MaxRun', N)
end;
Free
end;
if N>0 then
begin
Application.CreateForm(TForm1, Form1);
Application.Run;
end else
ShowMessage('Исчерпано максимальное количество запусков'+
' пробной версии программы')
end.

Здесь следует дать небольшой комментарий. Модуль Registry декларирует класс TRegistry, который представляет программисту доступ к системному реестру Windows. С помощью двух обращений к функции TRegistry.OpenKey создается и/или открывается ключ HKEY_CURRENT_USERSoftwareTrialProg системного реестра. Функция TRegistry.ValueExists возвращает True, если этот ключ содержит параметр с именем MaxRun и для него определено значение. При первом запуске приложения это не так, поэтому процедурой WriteInteger создается параметр и для него указывается начальное значение 5 (максимальное количество прогонов программы). При каждом следующем запуске этот параметр уменьшается на 1 и в момент, когда он становится равен 0, приложение блокирует создание и отображение главного окна.
Вставка поясняющих комментариев к именам форм

Обратите внимание на предложение uses в тексте проекта. При перечислении нестандартного модуля Uni1 с помощью зарезервированного слова in указывается имя файла с текстом модуля ('Unit1.pas'), а следующий за именем комментарий {Form1} именует объект-окно, создаваемый модулем Unit1. Такого рода объявления Delphi автоматически создает для каждого включенного в проект модуля. Delphi считает входящими в проект только перечисленные в этом предложении модули, и их алфавитный список появляется при выборе опции View | Units; а при выборе View | Forms показывается список всех перечисленных в комментариях объектов.

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

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

Если вы захотите перенести проект в другую папку и при этом сохранить его работоспособность, вам нужно сначала с помощью опции File|Save Project As скопировать в эту папку файл проекта, а затем с помощью опции File|Save As перенести туда все связанные с проектом модули: только тогда Delphi сумеет внести необходимые коррекции в файл проекта. Но если все файлы хранятся в единственной папке, то в предложении uses не указываются маршруты доступа, и поэтому вы сможете безболезненно скопировать разом все файлы в другую папку.

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

Все богатство изобразительных возможностей Windows вовсе не исчерпывается набором свойств и методов класса TCanvas: этот класс инкапсулирует лишь наиболее популярные приемы работы с чертежными инструментами. В табл. 1 перечислены некоторые функции Windows, которые не инкапсулирует класс TCanvas и способны значительно разнообразить текстовый вывод (именно он наиболее обеднен узкими рамками TCanvas).

Таблица 1. Некоторые текстовые функции Windows API type TLogFont = record

lfHeight: Integer; lfWidth: Integer; lfEscapment: Integer; lfOrientation: Integer; lfWeight: Integer; lfItalic: Byte; lfUnderline: Byte; lfStrikeOut: Byte; lfCharSet: Byte; lfOutPrecision: Byte; lfClipPrecision: Byte; lfQuality: Byte; lfPitchAndFamily: Byte; lfFaceName: PChar;

end;

function CreateFont(Font: TLogFont): hFont; Создает новый шрифт на основе данных в параметре Font (назначение полей структуры TLogFont см. в тексте после таблицы)
function DrawText(DC: hDC; pText: PChar; var Rect: TRect; Format: Wodr): Integer; В прямоугольнике Rect выводит многострочный текст, на который указывает pText. Параметр Format используется для форматирования (см. ниже)
function ExtTextOut(DC: hDC; X, Y: Integer; Options: Integer; Rect: TRect; pText: PChar; Count: Integer; PX: PInteger): Bool; Выводит текст с нестандартными межсимвольными расстояниями: X, Y — верхняя левая точка текста; Options — параметр, управляющий выводом (см. ниже); Rect — ограничивающий прямоугольник; pText — указатель на строку вывода; Count — количество выводимых символов; PX — указатель на массив целочисленных значений, определяющих межсимвольные расстояния: 1-й параметр — расстояние от 1-го до 2-го символа; 2-й параметр — расстояние от 2-го до 3-го символа и т.д.; если какой-то параметр равен 0, используется умалчиваемое межсимвольное расстояние
function GetBkColor(DC: hDC): TColor; Возвращает цвет фона
function GetBkMode(DC: hDC): Integer; Возвращает режим прорисовки фона: Opaque — фон прорисовывается заново при выводе текста; Transparent — фон не прорисовывается.
function GetTextAlign(DC: hDC): Integer; Возвращает выравнивание текста
function GetTextCharacterExtra(DC: hDC): Integer; Возвращает межсимвольное расстояние
function SetBkColor(DC: hDC; Color: TColor): TColor; Устанавливает новый цвет фона и возвращает старый, если обращение успешно
function SetBkMode(DC: hDC; Mode: Integer): Integer; Устанавливает новый режим прорисовки фона и возвращает старый, если операция успешна
function SetTextAlign(DC: hDC; Flags: Integer): Integer; Устанавливает новое выравнивание текста и возвращает старое, если вызов успешен
function SetTextCharacterExtra(DC: hDC; CharExtra: Integer): Integer; Устанавливает новое межсимвольное расстояние и возвращает старое, если вызов успешен

Отдельные поля структуры TLogFont для функции CreateFontIndirect имеют следующий смысл:

lfHeight — высота шрифта в пунктах (1 пункт = 1/72 дюйма); если больше 0 — определяет высоту «знакоместа» (с учетом выступающих над заглавным символом элементов в буквах Ё, Й); если меньше 0 — определяет высоту «чистого» символа, если равно 0 — высоту выбирает Windows;

lfWidth — средняя ширина символа; если равно 0 — ширину устанавливает Windows;

lfEscapment — угол наклона базовой линии текста в десятых долях градуса относительно горизонтального направления; положительные значения — поворот по часовой стрелки; в Windows 95/98 совпадает с lfOrientation;

lfOrientation — угол наклона символов по отношению к базовой линии; в Windows NT для шрифтов True Type может отличаться от lfEscapment; для этого следует установить режим устройства отображения равным gm_Advanced (по умолчанию устанавливается gm_Compatible);

lfWeight — плотность шрифта (fm_DontCare=0 — плотность выбирает Windows; fm_Thin=100 — очень тонкий шрифт; fm_ExtraLight=200 — очень светлый; fm_Light=300 — светлый; fm_Normal=400 — нормальный; fm_Medium=500 — утолщенный; fm_SemiBold=600 — полужирный; fm_Bold=700 — жирный; fm_ExtraBold=800 — усиленный; fm_Heavy=900 — тяжелый);

lfItalic, lfUnderline, lfStrikeOut — ненулевое значение означает соответственно наклонный, перечеркнутый и подчеркнутый шрифт;

lfCharSet — набор символов (ANSI_CharSet=0; Default_CharSet=1; Symbol_CharSet=2; ShiftJis_CharSet=128; OEM_CharSet=255);

lfOutPrecision — точность представления шрифта; рекомендуется Out_TT_Prec (выбирает True Type и векторные шрифты, если есть несколько разновидностей одноименных шрифтов) или Out_TT_Only_Prec (только True Type);

lfClipPrecision — определяет точность отсечения надписи границами области прорисовки (Clip_Character_Precis, Clip_Embedded, Clip_Mask, Clip_TT_Always, Clip_Default_Precis — рекомендуется, Clip_LH_Angles, Clip_Stroke_Precis);

lfQuality — определяет качество прорисовки (Default_Quality, Draft_Quality, Proof_Quality);

lfPitchAndFamily — в четырех младших разрядах указывается тип шрифта, в четырех старших — его семейство;

lfFaceName — имя гарнитуры шрифта.

Как реализован этот пример, показано в листинге 6.
Листинг 6
procedure TForm1.FormPaint(Sender: TObject);
var
X: Integer;
LF: TLogFont;
Fnt: HFont;
const
Text = 'Лучшая в мире система программирования';
begin
// Определяем параметры нового шрифта
FillChar(LF, SizeOf(LF), 0);
with LF do
begin
lfHeight := 20;
lfWeight := fw_Normal;
lfUnderline := 1;
lfEscapement := 450;
StrPCopy(lfFaceName, 'Courier New Cyr');
end;
with Form1.Canvas do
begin
// Создаем шрифт
Fnt := CreateFontIndirect(LF);
// Присваиваем его дескриптор шрифту канвы
Font.Handle := Fnt;
// Выводим текст под углом +45 градусов
TextOut(0, 300, Text);
X := TextWidth(Text);
DeleteObject(Fnt); // Удаляем ненужный шрифт
// Изменяем параметры шрифта
with LF do
begin
lfHeight := 90;
lfEscapement := -900;
lfWeight := fw_Heavy;
StrPCopy(LF.lfFaceName, 'Arial Cyr');
end;
Fnt := CreateFontIndirect(LF); // Создаем новый шрифт
Font.Handle := Fnt;
Font.Color := clRed;
// Выводим с наклоном -90 градусов
TextOut(X-10, 10, 'Delphi 5');
DeleteObject(Fnt); // Удаляем ненужный шрифт
end;
end;

Параметр Format функции DrawText может содержать один или несколько флагов (табл. 2).

Таблица 2. Возможные значения параметра Format функции DrawText Флаг Назначение
dt_Bottom Текст прижимается к нижней части области Rect
dt_CalcRect Разрешает динамически изменять размеры области Rect
dt_Center Текст центрируется по горизонтали
dt_EditControl Функция дублирует свойства отображения многострочного тестового редактора. В частности, таким же способом вычисляется средняя ширина символа и не показывается частично видимая последняя строка
dt_ExpandTabs Символы табуляции заменяются пробелами
dt_ExternalLeading В высоту строки включается высота межстрочного интервала
dt_Left Текст прижимается к левой части области Rect
dt_NoClip Текст не отсекается границами Rect
dt_NoPrefix Символы & не заменяются подчеркиванием
dt_Right Текст прижимается к правой части области Rect
dt_SingleLine Весь текст выводится единственной строкой, символы EOLN игнорируются
dt_TabsStop Символы табуляции не заменяются пробелами
dt_Top Текст прижимается к верхней части области Rect
dt_VCenter Текст центрируется по вертикали
dt_WordBreak Разрешает переход на новую строку при достижении правой границы Rect; разрыв строки — на границе слова; символы EOLN также переводят вывод на следующую строку

Если установлен флаг dt_CalcRect, функция изменяет высоту и ширину прямоугольника таким образом, чтобы вывести весь текст. Если выводится несколько строк, ширина вывода не меняется. Функция возвращает истинную высоту прямоугольника вывода.

Параметр Options функции ExtTextOut может быть комбинацией следующих значений:

eto_Clipped — текст будет отсекаться границами Rect;

eto_Gliph_Index — блокирует обработку языковым драйвером;

eto_Opaque — фон перерисовывается заново;

eto_RTLReading — вывод для чтения справа налево.

При выводе текста стандартными методами TCanvas всегда заново прорисовывается фон символов (цвет фона возвращает функция GetBkColor). Если цвет фона символов отличается от фона канвы, вывод сопровождается неприятными побочными эффектами.

Конечно, с помощью функции SetBkColor можно установить, чтобы цвет формы совпадал с цветом канвы, однако это не всегда возможно. Фон на таком экране не остается постоянным, а плавно переходит от интенсивного синего к черному. Ясно, что установить переменный цвет функцией SetBkColor невозможно. Более того, заглавные надписи программ Setup.exe также традиционно выводятся утолщенным наклонным шрифтом Times New Roman белыми буквами с черной тенью. Реализовать подобный эффект достаточно просто. Так, нужно вообще отказаться от прорисовки фона, установив с помощью функции SetBkMode режим Transparent, и вывести надпись дважды: первый раз черным цветом, а второй — белым, сместив вторую надпись немного влево и вверх относительно первой. Листинг 7 иллюстрирует сказанное (Setup.dpr):
Листинг 7
procedure TForm1.FormPaint(Sender: TObject);
var
Y: Integer;
Blue: Byte;
const
Text = 'Фон для программы Setup.exe';
begin
with Form1.Canvas do
begin
// Создаем фон:
for Y := 0 to Form1.Height-1 do
begin
// Уменьшаем интенсивность цвета с ростом ординаты Y
Blue := Round($FF*(Form1.Height-Y)/Form1.Height);
// Формируем цвет
Pen.Color := RGB(0, 0, Blue);
// Чертим линию
MoveTo(0, Y);
LineTo(Form1.Width-1, Y);
end; // for Y := 0 to Form1.Height-1 do
Font.Size := 32;
Font.Style := [fsBold, fsItalic, fsUnderline];
Font.Name := 'Times New Roman Cyr';
// Это обращение накладывает текст на фон:
SetBkMode(Handle, Transparent);
// Сначала выводим тень надписи
Font.Color := clBlack;
TextOut(40, 30, Text);
// Теперь саму надпись
Font.Color := clWhite;
TextOut(36, 26, Text)
end; // with Form1.Canvas do
end;


Включение в библиотеку форм

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

В следующих примерах (TestDLLForm.dpr) иллюстрируется техника включения в DLL формы и использования ее в вызывающей программе (листинги 8, 9 и 10).
Листинг 8. Текст DLL
library DLLWithForm;

uses
SysUtils,
Classes,
DLLFormU in 'DLLFormU.pas' {DLLForm};

{$R *.RES}

exports
ShowModalForm, ShowForm, FreeForm;

begin
end.
Листинг 9. Текст формы в DLL
unit DLLFormU;

interface

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

type
TDLLForm = class(TForm)
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
CallForm: THandle; //Дескриптор вызывающей формы
public
{ Public declarations }
end;

// Объявление экспортируемых подпрограмм
function ShowModalForm: Integer;
procedure ShowForm(Appl, Form: THandle);
procedure FreeForm;

var
DLLForm: TDLLForm;

implementation

{$R *.DFM}

function ShowModalForm: Integer;
// Модальный вызов
begin
DllForm := TDllForm.Create(Application);
Result := DLLForm.ShowModal;
DLLForm.Free;
end;

procedure ShowForm(Appl, Form: THandle);
// Немодальный вызов
begin
Application.Handle := Appl; // Замена объекта Application
DllForm := TDllForm.Create(Application);
// Запоминаем дескриптор вызывающего окна для посылки
// ему сообщения о закрытии
CallForm := Form;
DLLForm.Show
end;

procedure FreeForm;
// Уничтожение формы
begin
DLLForm.Free
end;

procedure TDLLForm.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
if CallForm<>0 then
SendMessage(CallForm, wm_User, 0, 0)
end;

end.
Листинг 10. Текст вызывающей программы
unit TestMainU;

interface

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

type
TTestMain = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
// Следующая процедура обрабатывает сообщение WM_USER,
// которое посылает форма из DLL в момент своего закрытия
procedure WMUser(var Msg: TMessage); message WM_USER;
end;

var
TestMain: TTestMain;

implementation

{$R *.DFM}

function ShowModalForm: Integer; External 'DLLWithForm';
procedure ShowForm(Appl, Form: THandle); External 'DLLWithForm';
procedure FreeForm; External 'DLLWithForm';

procedure TTestMain.Button1Click(Sender: TObject);
// Модальный вызов
begin
Button2.Enabled := False;
label1.Caption := 'ModalResult = '+IntToStr(ShowModalForm);
label1.Show; // Показываем результат вызова
Button2.Enabled := True
end;

procedure TTestMain.Button2Click(Sender: TObject);
// Немодальный вызов
begin
Button1.Enabled := False;
Button2.Enabled := False;
Button3.Enabled := True;
label1.Hide;
ShowForm(Application.Handle, Self.Handle);
end;

procedure TTestMain.Button3Click(Sender: TObject);
// Закрыть форму
begin
FreeForm;
Button1.Enabled := True;
Button2.Enabled := True;
Button3.Enabled := False;
end;

procedure TTestMain.WMUser(var Msg: TMessage);
// Сообщение из формы DLL о ее закрытии
begin
Button3.Click
end;

end.

Модуль формы DLLForm, помещенной в DLL, ссылается на стандартный модуль Forms и, таким образом, получает свой глобальный объект Application, который ничего «не знает» о глобальном объекте вызывающей программы. В режиме модального вызова это не имеет особого значения, поскольку модальное окно блокирует работу вызывающей программы. В режиме немодального вызова следует синхронизовать действия объектов, в противном случае минимизация главного окна, например, не приведет к минимизации окна DLL. Синхронизация достигается тем, что дескриптор объекта Application DLL заменяется соответствующим дескриптором вызывающей программы.

При показе формы в немодальном режиме она может быть закрыта либо вызвавшей ее программой, либо щелчком по собственной системной кнопке Закрыть. В последнем случае она должна каким-то образом известить вызывающую программу об этом событии. Для этого используется стандартный механизм посылки Windows-сообщения. Сообщение должно иметь адрес — дескриптор окна, для которого оно предназначено. Вот почему вторым параметром обращения к функции ShowForm в DLL передается и в поле CallForm запоминается дескриптор окна вызывающей программы. Обработчик события OnClose формы проверяет это поле и, если оно определено, посылает вызвавшему окну сообщение с индексом WM_USER. В вызывающей программе предусмотрен обработчик этого сообщения, в котором реализуются необходимые действия.

Категория: Хитрости в делфи | Добавил: Admin (2006-12-18)
Просмотров: 10545 | Комментарии: 26 | Рейтинг: 5.0 |

Всего комментариев: 211 2 3 »
21 FartRu  
0
Добро пожаловать на наш игровой веб-сайт! У нас можно поиграть онлайн в многопользовательские игры: дурак, преферанс, покер, тысяча, нарды, шахматы, домино, буркозел, бильярд, шашки, деберц и многие другие. Играйтесь в наши онлайн игры с конкурентами со итого мира! В наших многопользовательских онлайн играх Вы сможете поиграть с друзьями в наилучшие настольные и логические игры, которые всем знакомы с самого детства. Желаем приятной игры! Сайт Фарт.ру

20 Hosterms  
0
Нынешний хостинг файлов (выложить фото на хостинг файлов, скачать лучший хостинг файлов, хостинг файлов 2, хостинг файлов) с высочайшей скоростью загрузки и неограниченным местом под файлы. Стремительная загрузка файлов размером до 100 Гб, отправка, получение и управление файлами в личном кабинете. Быстрое скачивание файлов в несколько потоков. Скорость передачи файлов доходит до 1 Гб/сек. Место под хранение файлов не ограничено. Вероятна загрузка файлов чрез браузер, по FTP и нескольких файлов сходу. Сайт хостинг файлов.ру

19 Failoobmen  
0
Нынешний файлообменник (заработок на файлообменниках, файлообменник порно 3gp, мультима файлообменник, хостинг файлов) с высокой скоростью загрузки и неограниченным местом под файлы. Быстрая загрузка файлов размером до 100 Гб, отправка, получение и управление файлами в личном кабинете. Быстрое скачка файлов в несколько потоков. Скорость передачи файлов доходит до 1 Гб/сек. Точка под хранение файлов не ограничено. Вероятна загрузка файлов сквозь браузер, по FTP и нескольких файлов сразу. Сайт Файлообменник.ру

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

17 SexyTelefo  
0
Секс по телефону (секс игры на телефон) - сумеет исполнить все ваши сексапильные фантазии. У нас вы найдете сексуальных женщин на любой вкус. Блондинок и брюнеток, худых и полненьких, зрелых дам и неопытных девственниц. Только у нас весь диапазон секс услуг по телефону. Только у нас тема на телефон секс и секс на сотовый телефон! Тел: 8(809)505-45-74. 55 руб/мин + НДС. Сайт Секс-Телефон.ру

16 SteroidyBiz  
0
Уважаемые спортсмены! Тут можно заказать и купить steroid ENANTEST (Энантат), PARABOLIQ (Тренболон), OXANATABS (Оксандролон), PHENODEC (Фенил), ANASTROTABS (Анастрозол) и TURINOTABS (Туринабол) с доставкой по России и Белорусии. Мы продаём только качественные стероиды и анаболики! Сайт Стероиды.биз

15 SexTelefon  
0
Секс по телефону (секс по телефону уфа) - сумеет исполнить все ваши сексуальные фантазии. У нас вы найдете сексуальных женщин на хоть какой вкус. Блондинок и брюнеток, худых и полненьких, зрелых дам и неопытных девственниц. Всего-навсего у нас полный спектр секс услуг по телефону. Только у нас секс видео смотреть по телефону и телефоны женщин для секса! Тел: 8(809)505-45-74. 55 руб/мин + НДС. Сайт Секс-Телефон.ру

14 ChatyEbalo  
0
Секс видео чатом именуют виртуальный сервис (он-же эротический видеочат майл и вэб видео чат), демонстрирующий в реальном времени стриптиз и эротику, а так-же позволяющий разговаривать с девушками моделями. В отличие от обычного чата, секс видео-чат дает возможность не только разговаривать, приятельствовать, флиртовать и заигрывать с женщиной на другом конце монитора, да и созидать ее. Найти самый лучший видеочат можно на сайте Отзывы.Ебало.ру

13 ChatsEbalo  
0
Секс видео чатом называют виртуальный сервис (он-же эро видеочат без регистрации бесплатно и видеочат всемирный эротический), демонстрирующий в реальном времени стриптиз и эротику, а так-же позволяющий общаться с девушками моделями. В отличие от обычного чата, секс видео-чат дает возможность не только лишь общаться, приятельствовать, флиртовать и заигрывать с девушкой на другом конце монитора, но и созидать ее. Найти видеочат darsik ru можно на сайте Чат.Ебало.ру

12 ChatsEbalo  
0
Секс видео чатом называют виртуальный сервис (он-же видеочат р и видеочат с незнакомцем), демонстрирующий в реальном времени стриптиз и эротику, а так-же позволяющий разговаривать с девушками моделями. В отличие от простого чата, секс видео-чат дает возможность не только разговаривать, дружить, флиртовать и заигрывать с женщиной на другом конце монитора, но и видеть ее. Найти видеочат hjnbxtcrbq можно на сайте Чат.Ебало.ру

1-10 11-20 21-21
Имя *:
Email *:
Код *: