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

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

  Все выпуски  

Программирование на DELPHI в вопросах и ответах #10


Информационный Канал Subscribe.Ru

Программирование на Delphi в вопросах и ответах.


Добрый день, уважаемые читатели! Перед вами выпуск №10 от 18.12.04.

Итак, это уже десятый выпуск рассылки. Надеюсь, вас радует то, что рассылка выходит достаточно часто (как минимум раз в неделю), ведь есть такие рассылки, которые хоть и объявили частую периодичность выхода, но выходят в несколько раз реже, а то и не выходят вообще. Наша рассылка постоянно совершенствуется. Особенно стал замечательным сайт. Думаю, что его переработка прошла не зря. Ждём, кстати, ваших мнений о нём. Приносим также свои извинения за возможные неудобства 12 декабря, когда обновлённый сайт был запущен - некоторые страницы не работали или работали неправильно. На следующий день всё было исправлено. Опрос читателей насчёт того, есть ли у них собственный сайт, скоро подойдёт к концу. Его результаты будут опубликованы в следующем выпуске рассылки. Но теперь голосование будет проводиться более "естественным" способом. Отправка писем на e-mail - не самый удачный вариант. Отныне опросы проводятся через наш сайт. Они будут находиться на его главной странице (http://www.delphi-faq.fatal.ru/), а также в выпусках рассылки (см. ниже). Ссылки с вариантами ответа будут приводить уже на сайт и голос сразу будет учтён, что гораздо удобнее. Также частично изменён дизайн рассылки. Оценивать как всегда вам...

Есть ли у вас собственный сайт?
>>>> Да, есть.
>>>> Нет.
>>>> Нет, но хочу его открыть!

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

Правила нашей рассылки:
1. Не присылайте ответов на вопросы вроде "да я не знаю" или "да/нет". Такие ответы не публикуются.
2. Вопросы, не касающиеся Delphi, не принимаются (для этого существуют другие рассылки).
3. Запрещено присылать вложенные файлы, размером более 100 Кб, без предварительной связи с администратором.
4. Письма с "неправильной" темой не публикуются!

 


Статья по Delphi.

Написание инсталлятора на Delphi (часть 3)
Запугивание пользователя законами об авторских правах

Да, есть и такой этап. Если вы пишете программу, которая будет распространяться как freeware, вам всё равно придётся вывести небольшое окно и поставить пользователя в известность о том, что вы не отвечаете за все неприятности, которые могут с ним произойти во время использования вашей программы.

Как это делается? Если вы не знаете, как сделать диалоговое окно, то, по моему, вам ещё рано писать инсталляции. Если знаете, то выведите окно и поместите в нём нужный текст.

Примечание:
Поместить несколько строк текста можно разными способами. Во-первых, вы можете обрабатывать событие OnPaint диалоговой формы и рисовать многострочный текст на ней с помощью функции Windows API, которя называется DrawText. Во-вторых, вы можете вывести текст через компонент TRichEdit, предварительно установив у него свойство Border в bsNone, свойство Color — в clBtnFace,а свойство Enabled — в False. Запрещённый (disabled) компонент TRichEdit выглядит не так, как запрещённый компонент TMemo; и отличие заключается в том, что он не меняет цвет текста на серый (что нам, собственно, и нужно).

Зачем делать компонент запрещённым? Дело в том, что в этом случае он выглядит просто как многострочный TLabel, например, его нельзя редактировать, из него нельзя выделить текст, ему не передаётся фокус, если вы пробегаете по компонентам с помощью клавиши TAB — несомненно, это то, что нам нужно.

Получение важных системных данных

На этом этапе нам потребуются некоторые системные данные: имя пользователя и организация, путь, куда потребуется инсталлировать программу и некоторые другие. Сейчас мы разберёмся, как и откуда эти данные можно получить.

Имя пользователя и организация

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

Как правило, программа инсталляции берёт эти данные из Windows (поскольку при установке Windows пользователь их уже вводил) и просит всего лишь изменить их, если это необходимо.

Наш вопрос звучит так: где Windows хранит имя пользователя и организацию? В реестре есть всего два местп, где записаны эти данные:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\
RegisteredOwner = 'Имя'
RegisteredOrganization = 'Организация'

В "обычных" версиях Windows, эти значения хранятся в ключе Windows, а в Windows NT — Windows NT.

Поскольку "единства" здесь нет, можно проверить версию Windows с помощью функции GetVersionEx или проверять оба вышеописанных ключа.

Куда копировать программу

Можно сформулировать наш вопрос и по другому: где находиться каталог Program Files? Некоторые инсталляции считают, что это C:\Program Files . В действительности, конечно, он может находиться на другом диске, поэтому мы попробуем поискать его по другому... в реестре.

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\
ProgramFilesDir = 'D:\Program Files'

Можно воспользоваться функцией SHGetSpecialFolderLocation (это даже более корректно с точки зрения Microsoft).

Для изменения каталога вы можете вызывать функции SelectDirectory или SHBrowseForFolder . Можно также создать собственное окно диалога "Выбор каталога" с помощью компонента DirectoryListBox . Подробнее о выборе каталога мы поговорим позднее, когда будем рассматривать тонкости процесса инсталляции.

Сколько осталось свободного места на диске

Программа инсталляции перед копированием файлов обязана проверить, сколько на целевом диске осталось свободного дискового пространства. Это делается при помощью функции GetDiskFreeSpace (из модуля Windows ) или функции DiskFree (из модуля SysUtils ). Вторая функция — это надстройка Delphi над Win API (в смысле, она вызывает GetDiskFreeSpace ), но у неё значительно меньше параметров.

Группы программ

Обычно программа инсталляции создаёт для новой программы новую группу. Как правило, когда вы вводите название группы, рядом присутствует список, в котром перечислены все существующие группы. Получить такой список можно двумя способами. Один из них — работа с DDE-сервером, который называется Program Manager . Этот способ мы подробно рассмотрим чуть позже . Второй способ не очень сложен и основан на том факте, что всё меню "Программы" находиться в одном из каталогов вашего диска. Все подменю являются на самом деле подкаталогами, а пукнты — обычными ссылками (файлами с расширением .lnk).

Путь к папке, содержащей меню "Программы", вы можете найти в реестре:

HKEY_CURRENT_USER\Software\Microsoft\Windows\ CurrentVersion\Explorer\Shell Folders\
Programs = 'D:\WINNT\Profiles\Mark\Главное меню\Программы'

Не очень сложно прочитать содержимое этого каталога с помощью функций FindFirst / FindNext . Далее мы и об этом поговорим подробнее, поскольку чтение содержимое каталогов потребуется нам при написании универсальной процедуры копирования файлов.

Далее нас ждёт самый сложный процесс инсталляции - копирование. Там много всяких нюансов и на нём мы остановимся подробнее.

Присылайте свои статьи по адресу delphi-faq@list.ru с темой 'Clause' (без кавычек), и они будут опубликованы в ближайших выпусках рассылки. Большая просьба: статью оформляйте в -txt или -doc формате и используйте -zip или -rar сжатие (без самораспаковки).


Новые вопросы:

24. Скажите, где можно найти компоненты типа DelphiX, но (и это важно!), работающие с последней версией DirectX. Заранее благодарен! [Ответить].

25. Помогите рисунки JPG засунуть в DLL, а потом использовать в Delphi. И еще как сохранить параметры о цветах в ini файл. [Ответить].

26. Добрый вечер всем. Пишу сейчас программу на стыке графики и баз данных. В последних почти не шарю совсем, поэтому спрошу :)
1. Есть БД DB2. И есть набор файлов (txt, xls) да и сама програма выдет много данных. Мне нужно всеми этими даными заполнить соответствующие поля в данной базе. Короче говоря нужно передать данные в базу. Вопрос, естественно, как это сделать? Один из предложенных вариантов - это настроить драйвер ODBC. Но говорят, что это довольно медленный вариант. Подскажите, пожалуйста, как это сделать. Может быть уже есть готовые компоненты для данных целей.
2. Второй вопрос проще. Как из дельфи (D7, XP) создать xls файл (проверить на существование) сохранить туда данные из массива и потом их считать. Все. Спасибо за внимание. [Ответить].

27. Пишу сейчас прогу "Домашний поисковик", типа Google Desktop Search, но с поддержкой туевой хучи типов файлов и не могу найти путного описания устройства HLP и CHM файлов. Можете ли поделиться? А может сами библиотеку напишете? К проге прицепляются плагины (ДЛЛ), которые возвращают ей словарь встреченных в файле осмысленных буквосочетаний, та их заносит в базу, ну и вторая функция - по запросу возвратить осмысленную цитату из файла (опять же типа поисковика в нете). Шаблон библиотеки могу кинуть, программой тож понятно, поделюсь, хотя она и так пишется Open Source - цепляй свои плагины и вперед... [Ответить].

28. Здравствуйте. Пишу тут игру на WinAPI. Мне нужно воспроизводить фоновую музыку и звуки (выстрел, столкновение?), использую функцию PlaySound(address, 0, SND_ASYNC or SND_MEMORY), но при воспроизведении звуков фоновая музыка останавливается и больше не воспроизводится. Подскажите, как нормально воспроизводить фоновую музыку!!! Заранее благодарен. [Ответить].

29. Индикатор загрузки процессора в кнопке "Пуск" - как фон, т.е. между буквами и цветом кнопки. Реально? Если да, то как. [Ответить].

Вопросы, ждущие ответа:

12. Привет. Может, кому-нибудь из читателей, удалось написать утилиту, показывающую все активные TCP/IP соединения (аналог Netstat) на Delphi без использования Fnugry Netstat Components. Поделитесь пожалуйста исходником, а то дядька Google мне отказался с этим помочь. [Ответить].

14. Скажите, как узнать занятость принтера и передать задачу на другой принтер сети! [Ответить].

15. Здраствуйте.Можете сказат как я могу выбрат компоненть из другого Application? Например в другом App. я использвал с одного Edit-a ( у него ест OnChange(), OnKeyPress() и.др ) или он может бьт не визуальным. И хочу что добавить код в новую Application( первому Form-у OnCreate ) чтобы он автоматически выбрал ту Component-у какую я дам в коде. Заранее блогодорен!!! [Ответить].

21. Задача состоит в следующем: необходимо непрерывно получать изображения со сканера (по крайней мере настолько, насколько это возможно, но без выгрузки основной программы). До сих пор, я работал под twain-библиотекой. Там все идет нормально, но на n-ном BITMAP'е у сканера происходит "крейз" и до перезагрузки WIDOWS, достучаться до него невозможно. Помогите, пожалуйста, решить эту проблему. P.S. Насколько я знаю, при работе со стандартными программами windows (Imaging & Kodak Image), а также при использовании ActiveX TImgScan (кроме того, он очень неудобен), возникают подобные же проблемы. [Ответить].

22. Господа - программисты, расскажите как проще всего вывести на экран Delphi - программы готовую таблицу базы данных Microsoft Access? Заранее благодарен. [Ответить].

 


Поступившие ответы:

20. (Работа с Word-документами из Delphi-программы). [Отвечает: SysLine]: Как раз пишу этакую вещь для одного препода. Он хочет формировать билеты из списка вопросов. Как допишу до более-менее дельного варианта могу исходники дать.
От ведущего: как только SysLine предоставит исходники, вы сразу же узнаете об этом через рассылку, а скачать их сможете с нашего сайта.
16.12 исходники были получены. Вот прямая ссылка для их закачки:
http://www.delphi-faq.fatal.ru/answers/1000/100/20/comb.rar.

4. (Изменение разрешения экрана). [Отвечает: Dron]: Вот пример процедуры, которая изменяет разрешение экрана:
procedure ChangeDisplayResolution(x, y : word);
var
dm : TDEVMODE;
begin
ZeroMemory(@dm, sizeof(TDEVMODE));
dm.dmSize := sizeof(TDEVMODE);
dm.dmPelsWidth := x;
dm.dmPelsHeight := y;
dm.dmFields := DM_DISPLAYFLAGS;
ChangeDisplaySettings(dm, 0);
end;

5. (Добавление к программам поддержки ХР-стиля). [Отвечает: Dron]: Сделать программам XP-стиль в Delphi очень просто. Если ты используешь Delphi 7, то там на вкладке Win32 есть компонент XPManifest. Помести его на форму и запусти программу. Она станет в XP-стиле. Однако вкратце объясню смысл работы этого компонента. На самом деле, этот компонент есть смысл поместить на форму только один раз - ХР-шным становится сразу всё приложение. При помещении этого компонента просто добавляется модуль XPMan.pas в раздел uses. А сам этот модуль не делает ничего, кроме подключения WindowsXP.res. В этом WindowsXP.res "зашит" .manifest-файл. Файл манифеста имеет следующий текст:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity processorArchitecture="*" version="5.1.0.0" type="win32" name="Microsoft.Windows.Shell.shell32"/> <description>Windows Shell</description> <dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*" /> </dependentAssembly>
</dependency>
</assembly>

Иными словами, он просто указывает программе, что нужно использовать Windows Common Controls версии 6.0, а не 5.x, которые "старые".

Между прочим, подключить манифест можно АБСОЛЮТНО К ЛЮБОЙ ПРОГРАММЕ. Создай файл с текстом, приведённым выше и именем {имя приложения}.exe.manifest и помести в каталог с программой. Программа станет в XP-стиле, в какой бы среде она не была написана! Очень удобно, кстати. Пример: если твоя программа имеет экзешник prog.exe, то файл-манифест должен называться prog.exe.manifest (manifest - расширение!).

Как видишь, всё очень просто.

17. (Копирование URL в TMemo). [Отвечает: Dron]: Не совсем понял вопроса... Какой URL? Откуда? Если так, покажу, как двойным кликом по URL одного TMemo скопировать этот URL в другое TMemo. Сначала убедись, что в твоём "исходном" TMemo гиперссылки выделяются (синий цвет, курсор hand). Насколько помню, когда кликнешь, url выделяется весь. Как его перенести в другой TMemo? Да через буфер обмена конечно! Такой незатейливый код, как

keybd_event(VK_CONTROL,0,0,0);
keybd_event($43,0,0,0);
keybd_event($43,0,KEYEVENTF_KEYUP,0);
keybd_event(VK_CONTROL,0,KEYEVENTF_KEYUP,0);

делает глобальное виртуальное нажатие комбинации клавиш <Ctrl>+<C>, т.е. текст будет скопирован в буфер обмена. Дальше - вставляем его в другое Memo: Memo2.PasteFromClipboard;
Ты можешь использовать подобный код и для "взятия" URL из других приложений. Только тебе нужно ловить, кога происходит двойной клик мышью. Если есть проблема с выделением URL в TMemo, как гиперссылка - возьми специальные компоненты, которые это умеют делать автоматически. Например, в JediVCL есть такой редактор. Или специальный RichEdit - RichEditWithLinks (на http://www.torry.net есть). Также ты можешь послать своему RichEdit'у сообщение WM_USER + 91; (это EM_AUTOURLDETECT) через SendMessage() и гиперссылки будут выделяться автоматически.

17. (Индикатор загрузки процессора). [Отвечает: Dron]: Не совсем понял сути запроса. Так что нужно сделать - графический индикатор или получать % загрузки процессора? Насчёт граф. индикатора - даже и говорить не буду. Наверняка, есть такие компоненты, да и вручную легко сделать - TShape's в два столба помести, да раскрашивай их. Если нужен график, который в Диспетчере Задач зовётся Хронологией загрузки ЦП - используй TChart. Там это можно сделать. Но я приведу код, узнающий загрузку ЦП:

unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Gauge1: TGauge;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}
const
SystemBasicInformation = 0;
SystemPerformanceInformation = 2;
SystemTimeInformation = 3;

type
TPDWord = ^DWORD;

TSystem_Basic_Information = packed record
dwUnknown1: DWORD;
uKeMaximumIncrement: ULONG;
uPageSize: ULONG;
uMmNumberOfPhysicalPages: ULONG;
uMmLowestPhysicalPage: ULONG;
uMmHighestPhysicalPage: ULONG;
uAllocationGranularity: ULONG;
pLowestUserAddress: Pointer;
pMmHighestUserAddress: Pointer;
uKeActiveProcessors: ULONG;
bKeNumberProcessors: byte;
bUnknown2: byte;
wUnknown3: word;
end;

type
TSystem_Performance_Information = packed record
liIdleTime: LARGE_INTEGER; {LARGE_INTEGER}
dwSpare: array[0..75] of DWORD;
end;

type
TSystem_Time_Information = packed record
liKeBootTime: LARGE_INTEGER;
liKeSystemTime: LARGE_INTEGER;
liExpTimeZoneBias: LARGE_INTEGER;
uCurrentTimeZoneId: ULONG;
dwReserved: DWORD;
end;

var
NtQuerySystemInformation: function(infoClass: DWORD;
buffer: Pointer;
bufSize: DWORD;
returnSize: TPDword): DWORD; stdcall = nil;
liOldIdleTime: LARGE_INTEGER = ();
liOldSystemTime: LARGE_INTEGER = ();

function Li2Double(x: LARGE_INTEGER): Double;
begin
Result := x.HighPart * 4.294967296E9 + x.LowPart
end;

procedure GetCPUUsage;
var
SysBaseInfo: TSystem_Basic_Information;
SysPerfInfo: TSystem_Performance_Information;
SysTimeInfo: TSystem_Time_Information;
status: Longint; {long}
dbSystemTime: Double;
dbIdleTime: Double;
Inf: integer;
bLoopAborted : boolean;

begin
if @NtQuerySystemInformation = nil then
NtQuerySystemInformation := GetProcAddress(GetModuleHandle('ntdll.dll'),
'NtQuerySystemInformation');

// get number of processors in the system

status := NtQuerySystemInformation(SystemBasicInformation, @SysBaseInfo, SizeOf(SysBaseInfo), nil);
if status <> 0 then Exit;

{ // Show some information
with SysBaseInfo do
begin
ShowMessage(
Format('uKeMaximumIncrement: %d'#13'uPageSize: %d'#13+
'uMmNumberOfPhysicalPages: %d'+#13+'uMmLowestPhysicalPage: %d'+#13+
'uMmHighestPhysicalPage: %d'+#13+'uAllocationGranularity: %d'#13+
'uKeActiveProcessors: %d'#13'bKeNumberProcessors: %d',
[uKeMaximumIncrement, uPageSize, uMmNumberOfPhysicalPages,
uMmLowestPhysicalPage, uMmHighestPhysicalPage, uAllocationGranularity,
uKeActiveProcessors, bKeNumberProcessors]));
end; }

bLoopAborted := False;
while not bLoopAborted do
begin

// get new system time
status := NtQuerySystemInformation(SystemTimeInformation, @SysTimeInfo, SizeOf(SysTimeInfo), 0);
if status <> 0 then Exit;

// get new CPU's idle time
status := NtQuerySystemInformation(SystemPerformanceInformation, @SysPerfInfo, SizeOf(SysPerfInfo), nil);
if status <> 0 then Exit;

// if it's a first call - skip it
if (liOldIdleTime.QuadPart <> 0) then
begin

// CurrentValue = NewValue - OldValue
dbIdleTime := Li2Double(SysPerfInfo.liIdleTime) - Li2Double(liOldIdleTime);
dbSystemTime := Li2Double(SysTimeInfo.liKeSystemTime) - Li2Double(liOldSystemTime);

// CurrentCpuIdle = IdleTime / SystemTime
dbIdleTime := dbIdleTime / dbSystemTime;

// CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors
dbIdleTime := 100.0 - dbIdleTime * 100.0 / SysBaseInfo.bKeNumberProcessors + 0.5;

// Show Percentage
Inf:= StrToInt(FormatFloat('0',dbIdleTime));
Form1.Gauge1.Progress:=Inf-1;
Application.ProcessMessages;

// Abort if user pressed ESC or Application is terminated
bLoopAborted := (GetKeyState(VK_ESCAPE) and 128 = 128) or Application.Terminated;

end;

// store new CPU's idle and system time
liOldIdleTime := SysPerfInfo.liIdleTime;
liOldSystemTime := SysTimeInfo.liKeSystemTime;

// wait one second
Sleep(1000);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
GetCPUUsage ;
end;

end.

19. (Размещение ProgressBar в StatusBar). [Отвечает: Dron]: Разместить ProgressBar в StatusBar очень легко. Почти все сторонние компоненты-статусбары позволяют класть на себя всё, что угодно. Но можно и вручную сделать. Пишешь: StatusBar1.ControlStyle := StatusBar1.ControlStyle + [csAcceptsControls]; После этого на данном статус-баре можно размещать любые компоненты и они не будут от него "отскакивать".


Вы также можете ответить на предыдущие вопросы. Поскольку на них уже ответили как минимум раз, они больше не публикуются в рассылке. Но если вы можете что-то добавить к ответам других, пожалуйста, отвечайте - ответы будут опубликованы. Найти предыдущие вопросы вы можете в архиве рассылки: http://subscribe.ru/archive/comp.soft.prog.delphifaq/, либо на сайте рассылки (http://www.delphi-faq.fatal.ru/).

 


Друзья:

Здесь представлены ссылки на дружественные сайты нашего портала. Если вы тоже хотите стать нашим другом, разместите баннер на главной странице своего сайта. Подробнее о том, как стать другом, можно прочитать здесь: http://www.delphi-faq.fatal.ru/banner.htm.

http://www.x-program.narod.ru/ - На нашем сайте Вы найдёте некоторые наши программы. Также мы занимаемся создание ПО для любой версии ОС Windows под заказ.
http://www.basic.webhost.ru/ - Программирование на языках Basic и Visual Basic.
http://www.sashook.nm.ru/ - Игры, флешки, обои, компьютерные приколы.
http://infomania2004.webhost.ru/ - Этот сайт создан для того, чтобы вы могли получить интересующую вас информацию с минимальными затратами сил и времени. Если вы не нашли здесь нужной информации, вы можете оставить заявку на ее поиск. Как только информация будет найдена, она появится на сайте, а вам сообщат об этом.

 


Юмор:

Приходит программист к пианисту посмотреть на новый рояль. После продолжительного обзора с презрительным взглядом заявляет:
- Клава неудобная - всего 84 клавиши, половина функциональных, ни одна не подписана, хотя: shift ногой нажимать - оригинально...

Звонок в компьютерную контору:
- С моим компьютером проблемы, он не включается:
- Как не включается?
- Да пишет все время: 'Вставьте дискету, вставьте дискету:'
- А вы вставляли?
- Нет: Как-то не догадался...

Определили астрологи, что через 5 дней конец света. Собирает директоров Клинтон:
- Есть две новости, одна хорошая: Бог все-таки есть, вторая плохая: через 5 дней конец света.
Собирает директоров Билл Гейтс:
- Есть две радостные новости: Бог все-таки есть, через 5 дней умрет UNIX.

CPU not found! Starting software emulation.

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


Присылайте свои "компьютерные" анекдоты по этой ссылке: delphi-faq@list.ru и они обязательно будут опубликованы!

 

Товарищи программисты! Проявляйте свою активность. Давайте помогать друг другу!
Если вы не нашли ответа на свой вопрос, не отчаивайтесь! Ведь количество подписчиков постоянно растёт и, наверняка, найдётся тот человек, который поможет вам!
На сегодня всё. До встречи через неделю!

Сайт рассылки: http://www.delphi-faq.fatal.ru E-mail: Delphi-FAQ@list.ru


http://subscribe.ru/
http://subscribe.ru/feedback/
Подписан адрес:
Код этой рассылки: comp.soft.prog.delphifaq
Отписаться

В избранное