Рассылка закрыта
При закрытии подписчики были переданы в рассылку "Интернет: Образование, Работа и Бизнес" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
← Декабрь 2004 → | ||||||
3
|
4
|
|||||
---|---|---|---|---|---|---|
6
|
7
|
8
|
10
|
11
|
||
13
|
14
|
15
|
16
|
17
|
19
|
|
20
|
21
|
22
|
23
|
24
|
26
|
|
27
|
28
|
30
|
31
|
Статистика
-1 за неделю
Программирование на DELPHI в вопросах и ответах #12
Информационный Канал Subscribe.Ru |
Программирование на Delphi в вопросах и ответах.
|
|||||
Выпуск №12 от 29.12.04. |
|||||
Это последний выпуск нашей рассылки в этом году! Поздравляю всех вас с Новым Годом, желаю приятно провести праздники. Удачи вам и счастья в Новом 2005 Году! Отдельно хочется сказать о нашем проекте. Он существует чуть больше двух месяцев, но за это время очень успел развиться. Вышло 12 выпусков рассылки, на сайте много полезного, сайт очень преобразился по сравнению с начальной версией. Регулярно приходят новые вопросы и ответы на уже заданные. Количество подписчиков скоро подойдёт к 1500! Однако результаты работы всё равно не очень хорошие. К примеру, на просьбу проголосовать, из 1400 человек откликнулись только 45... Обидно конечно... Но я искренее надеюсь, что это всего лишь "раскачка". Начинается другой год, а значит будет много всего интересного. Также приношу свои извинения за предыдущий выпуск рассылки. Туда не попали некоторые присланные ответы. Сегодня всё на месте. Теперь, наверное, будут выходить спец-выпуски рассылки, в которых будут публиковаться только вопросы, на которые не пришло ответов, а раздел "Вопросы, ждущие ответа" в обычных выпусках будет убран. Но периодичность этих выпусков будет предельно мала - наверное, раз в месяц. Позже решим. В голосовании насчёт публикации лидеров по количеству баллов приняли участие 19 человек. Итак, В общем, что делать, - неизвестно. Некоторые в письмах подписывали также "Да, обязтальено публикуйте", а некоторые - наоборот - "Ни в коем случае". Я принял решение. Публиковать лидеров мы будем, но только начиная со следующего выпуска. Кроме того, при публикации каждого из трёх лидеров будет учтён ваш голос, который вы недавно отдали (если голосовали вообще). Таким образом, если вы попадаете в тройку лидеров, то ваше имя опубликовано не будет - будет только стоять прочерк. Напомню, что хотелось бы открыть какой-нибудь новый разделы (или разделы), посвящённые Delphi. Вот такие пришли письма с советами: Считаю, крайне нужная вещь. Однако появление новых компонентов, Темой для новостей должны стать события, относящиеся к фирме Раздел "Новости из мира Delphi" не помешал бы. :)) Ну что же, вот такие предложения. Хочу сообщить: один новый раздел мы точно откроем в ближайшем будущем. И находится в этом разделе будут разные "вещи": компоненты для Delphi, plug-in'ы, исходники программ. Этот раздел будет открыт как в рассылке, так и на сайте. Соответственно, в рассылке будет публиковаться описание новых поступлений, а сами файлы будут находиться на сайте. Этот раздел мы откроем сразу же после Нового Года! Оставляю вас наедине с рассылкой, приятного чтения. До встречи в Новом 2005 Году!!! Правила нашей рассылки: |
|||||
Написание инсталлятора на Delphi (Часть 5). Копирование - 2, Сжатие Существует такая штука, как сжатие данных. Хорошо, если вы инсталлируете свою программу с компакт-диска. Как правило, в такой ситуации вы не знаете, что ещё записать на эту бездонную болванку и несколько лишних мегабайт вам в данной ситуации совсем не помешают :) Совершенно по другому обстоят дела с дискетами. На дискеты надо помещать сжатую информацию — в этом случае вся ваша программа возможно (только возможно) влезет всего лишь на тридцать четыре дискеты. Вот как делать сжатие — это вопрос. Я расскажу вам о нескольких методах сжатия данных, которыми вы можете воспользоваться. Метод номер раз — это сжатие файлов стандартными утилитами, разработанными фирмой Microsoft. Когда-то это была программа compress.exe, сейчас — cabarc.exe. Метод номер два — сжатие файлов с помощью библиотеки ZLib, которая поставляется вместе с Delphi (она находится в каталоге \Info\Extras\ZLib оригинального диска с Delphi). Она предоставляет вам два класса, которые являются наследниками TStream. Вы можете воспользоваться кодом функции копирования при помощи TFileStream из предыдущей статьи для того, чтобы реализовать как сжатие, так и распаковку произвольного потока (в том числе и файла). Ещё один метод — использование динамической библиотеки unrar.dll, разработанной Евгением Рошалом. Существуют и другие библиотеки (даже компоненты), вы можете свободно найти их, если будете достаточно долго шляться по Интернету. Примечание: Отдельно стоит поговорить о тех файлах, которые могут использоваться сразу несколькими программами. Для этих файлов существует даже специальное название — разделяемые (поскольку несколько программ делят их между собой). Обычно они записываются в системный каталог Windows (для Windows 98 это как правило \WINDOWS\SYSTEM, для Windows NT — \WINNT\SYSTEM32). Если системный каталог доступен только для чтения, то эти файлы необходимо записывать в каталог Windows (\WINDOWS и \WINNT соответственно), который всегда доступен для записи. Если разделяемый файл уже существует в целевом каталоге, то необходимо сравнить версии, языки и др. характеристики двух файлов и на основании этого сравнения решать — копировать файл или не надо. При копировании разделяемых файлов требуется уведомить Windows о том, что одним разделением стало больше. Это делается через реестр. При замещении файлов, которые в момент инсталляции используются Windows требуется определённая техника, поскольку перезаписать занятый файл нельзя. Эти вопросы в ближайшее время будут освещены в следующей статье. Поистине, копирование файлов — тема неисчерпаемая :) Напоследок, исследуем вопрос о том, куда копировать файлы? В соответствии с рекомендациями Microsoft, каталог вашей программы должен иметь форму <Program Files>\<Название вашей фирмы>\<Название продукта>. Вы можете также включить в название каталога информацию о версии продукта, например C:\Program Files\Borland\Delphi 7, хотя возможен и вариант C:\Program Files\Borland\Delphi\7 (реально фирма Borland использует первый вариант). Бывают и исключения, в частности FAR Евгения Рошала ставится в C:\Program Files\FAR. Разделяемые файлы следует копировать в системный каталог Windows, а если он защищён от записи — в каталог Windows. Дальше мы пойдём по реестру... Обход дерева каталогов с прерыванием и возобновлением Недавно занимаясь интересной задачкой по написанию службы индексации, столкнулся с интересным вопросом: " А как бы нам поиск заморозить и продолжить после (через минуту, завтра, через месяц)?". Да конечно можно сказать - что у тебя за машина такая, вот у меня дерево каталогов обходит за 3 минуты... Согласен, это не вопрос. Но когда нужно не просто обходить, а еще и выполнять некоторые действия с файлами, да если их на диске 150 тыс. и больше, да еще не загружая процессор на 100%, то время может затянуться до нескольких суток, вот тогда - как быть? Вот этой теме я и решил посвятить статью. Как оказалось, в Интернете информации по этой теме нет. Либо это слишком просто, либо никому не нужно. Как выяснилось - ни то ни другое. Со стандартной процедурой обхода дерева сталкивались очень многие procedure FileFind(path:string); var sr:Tsearchrec;// Описываем структуру, которую использует для поиска система found:integer; // найдено или нет begin found:=FindFirst(path + '\*.*', FaAnyfile, sr); {по команде FindFirst программа создает структуру следующего типа TsearchRec = record Time: Integer; // время создания Size: Integer; // его размер Attr: Integer;// атрибуты Name:TFileName // = TString; собственно имя файла ExcludeAttr: Integer; найденные атрибуты FindHandle: THandle; // !!! указатель на структуру поиска, которую создает система, а не наша программа. Вот для чего обязательно в конце поиска указывать FindClose - это высвобождает память FindData: TWin32FindData; // собственно эта структура end;} while (found = 0) do // если хоть чтото найдено begin if (sr.name <> '.') and (sr.name <> '..') then begin // если это не указатели на корневые каталоги, то чтото нашли if (sr.attr and FaDirectory) = FaDirectory then // ага вот поддиректория - вызываем себя рекурсивно, но с поиском уже в этой директории FileFind(path+'\'+sr.name) else begin // вот тут выполняем чтото с найденным файлом ...... mainform.memo1.lines.append(path+'\'+sr.name); end end; found:=findnext(sr); // есть ли еще файлы или каталоги end; FindClose(sr); // поиск закончен - нужно освободить память end; Казалось бы сохранить состояние процедуры поиска просто - достаточно сохранить структуру - sr:TsearchRec, а потом ее восстановить и поиск продолжится. И так попробуем решить эти проблемы. Проше всего разбор начать в обратном порядке... (не подумайте превратно, я знаю через что рвут гланды в России...) Третий вопрос - как сохранить , а потом восстановить SearchRec, если он состоит непонятно из чего. А давайте сделаем свой SearchRec, как нам нужно. А именно так type // этот тип почти полностью переписывается со стандартного TSearchRec TMysearchRec = record Time: Integer; Size: Integer; Attr: Integer; Name: string[250];//вот тут обрабатывалось неверно при типе TString, как длина ? ExcludeAttr: Integer; FindHandle: THandle; // в принципе не нужен, но не будем сильно пугать читателей // сильными отличиями, да и бог с ними - с восемью байтами FindData: TWin32FindData; end; но нам еще требуется сохранять несколько переменных самой программы, а именно Found - найдено чтото или нет и Path - с каким параметром нас вызывали, поэтому на основе этого типа делаем еще один TMyRec_Sea = record Rec_Sea:TMySearchRec; // наша структура поиска path:String[250]; // откуда начинали found:integer; // при остановке нашли чтото или нет end; Второй вопрос после первого решается не очень красиво, но довольно легко. Да система генерит структуру: FindHandle: THandle; FindData: TWin32FindData. FindData - собственно сама структура и FindHandle - указатель на нее. Пусть система генерит что угодно, если с умом, то можно обойти и это. Многие ли помнят такое INT21h->INT 13H. Думаю вспомнили. При восстановлении поиска дадим команду FindFirst, а потом подменим FindData и остальные поля, не трогая FindHandle, иначе сразу после окончания поиска (!!! ???) получим обращение к недопустимому адресу и вылет программы. ...... // создаем запись для поиска FindFirst(path+'\'+mask, FaAnyfile, sr); delfile:=false; found:=buffer.found; // загоняем в SEARCHREC все кроме FINDHANDLE (он создается системой) sr.Time:=buffer.rec_sea.Time; sr.Size:=buffer.rec_sea.Size; sr.Attr:=buffer.rec_sea.Attr; sr.Name:=buffer.rec_sea.Name; sr.ExcludeAttr:=buffer.rec_sea.ExcludeAttr; sr.FindData:=buffer.rec_sea.FindData; Первый вопрос - как же сохранять состояние процедуры при рекурсии?. Давайте сохранять SearchRec в файл и используем принцип магазина (не продуктового, а от автомата калашникова) - последний вошел - первый вышел. Вот примерная структура процедуры при выполняющемся поиске ( при нескольких рекурсивных вызовах) Findfile('c:\') Findfile('c:\Docs') FindFile(c:\Docs\Delphi') ...... При получении сигнала на остановку процедуры начинают писать в файл в обратном порядке, а именно - FindFile(c:\Docs\Delphi'),Findfile('c:\Docs'),Findfile('c:\'). Примерно так Findfile('c:\')------------------------------------+ Findfile('c:\Docs')---------------------+ ! FindFile(c:\Docs\Delphi') ---+ ! ! v v v [файл сохранений состояния] [rec1] [rec2] [rec3] Ну а когда нужно восстановить состояние поиска смотрим не пустой ли файл сохранений, и читаем записи начиная с конца, после прочтения их удаляем. Таким образом поиск по дереву автоматом развернется на столько рекурсивных вызовов, сколько надо, и продолжит поиск. Да, едва не забыл, как мы узнаем что надо приостановить поиск ? Давайте заведем глобальную переменную Process. Как она станет False - пора останавливаться Ниже приведена часть модуля с использованием описанных алгоритмов
Unit unit1;
......
var
....
process:boolean; // вот глобальная переменная она и управляет поиском true - можно
// false - стоп с запоминанием состояния
.....
procedure FileFind(path:string;resume:boolean);
{ сканирует диск (вернее дерево каталогов) при вызове PATH - начальный каталог для обхода
RESUME - если TRUE - то продолжать сохраненный поиск (тогда значение PATH игнорируется,
кроме случая, когда не обнаружен файл сохранения поиска)
при установке глобальной переменной PROCESS в false останавливается
с запоминанием предыдущего состояния,внимание - РЕКУРСИЯ !!! }
const
save_ext='.rec'; // в каталоге приложения создает SAVE файл с именем приложения и указанным расширением
mask='*.*';
type
TMysearchRec = record
// пришлось написать свой тип SEARCHREC с NAME фиксированной длины
Time: Integer; Size: Integer; Attr: Integer;
Name: string[250]; //вот тут обрабатывалось неверно при типе TString, как длина ?
ExcludeAttr: Integer; FindHandle: THandle; FindData: TWin32FindData;
end;
TMyRec_Sea = record
Rec_Sea:TMySearchRec;
path:String[250]; found:integer; delfile:boolean;
end;
var
sr:TSearchRec;
RecFile:TFileStream;
buffer:tMyRec_Sea;
sp,save_file_name:string; found:integer; delfile:Boolean;
delfile:Boolean;
begin
if resume then
// возобновить поиск или начать новый
begin
save_file_name:=ChangeFileExt(ParamStr(0),save_ext);
if FileExists(save_file_name) then
begin
RecFile:=TFileStream.Create(save_file_name,fmOpenReadWrite);
// чистим буфер, не важно, необходимо для отладки
fillchar(buffer,sizeof(buffer),#0);
// читаем сохранение начиная с конца файла
RecFile.Seek(-1*sizeof(buffer),soFromEnd);
RecFile.Readbuffer(buffer,sizeof(buffer));
path:=buffer.path; sp:=path;
// создаем запись для поиска
FindFirst(path+'\'+mask, FaAnyfile, sr);
delfile:=false; found:=buffer.found;
// загоняем в SEARCHREC все кроме FINDHANDLE (он создается системой)
sr.Time:=buffer.rec_sea.Time; sr.Size:=buffer.rec_sea.Size;
sr.Attr:=buffer.rec_sea.Attr; sr.Name:=buffer.rec_sea.Name;
sr.ExcludeAttr:=buffer.rec_sea.ExcludeAttr; sr.FindData:=buffer.rec_sea.FindData;
// режем кусок уже прочитали свои данные - другим они не понадобятся
RecFile.Seek(-1*sizeof(buffer),soFromEnd); recfile.Size:=RecFile.Position;
// дорезались - дозагружаться неоткуда
if RecFile.Size=0 then delfile:=true;
RecFile.Free;
if delfile then sysutils.DeleteFile(save_file_name);
end
else
// нет сохраненных поисков
begin
// начинаем новый
sp:=path; resume:=false;
// тут исправляется разница между C:\ и C:\DOCS - убираем последний слэш
if sp[length(sp)]='\' then sp:=copy(sp,1,length(sp)-1);
found:=FindFirst(sp + '\'+mask, FaAnyfile, sr);
end
end
else
begin
// новый поиск - пристрелить старые записи
save_file_name:=ChangeFileExt(ParamStr(0),save_ext);
if fileExists(save_file_name) then sysutils.DeleteFile(save_file_name) ;
sp:=path;
if sp[length(sp)]='\' then sp:=copy(sp,1,length(sp)-1);
found:=FindFirst(sp + '\'+mask, FaAnyfile, sr);
end;
// закончена подготовка - вперед поиск
while (found = 0) and process do
begin
application.ProcessMessages;
if (sr.name <> '.') and (sr.name <> '..') then
begin
if (sr.attr and FaDirectory) = FaDirectory
then
begin
FileFind(sp+'\'+sr.name,resume);
end
else
begin
// ну тут разные действия с найденым файлом
mainform.label1.caption:=('начат разбор '+sp+'\'+sr.name) ;
................
// закончили действия
Application.ProcessMessages; // а вот без этого мы никогда не узнаем что пора поиск
// закончить
end;
end;
if process then found:=findnext(sr);
end;
if not process then
// получили сигнал на остановку сканирования нужно запомнить состояние
begin
save_file_name:=ChangeFileExt(ParamStr(0),save_ext);
if not FileExists(save_file_name) then RecFile:=TFileStream.Create(save_file_name,fmCreate)
else RecFile:=TFileStream.Create(save_file_name,fmOpenReadWrite);
RecFile.Seek(0,soFromEnd);
// заполняем буфер текущим состоянием
buffer.rec_sea.Time :=sr.Time; buffer.rec_sea.Size :=sr.Size ;
buffer.rec_sea.Attr :=sr.Attr ; buffer.rec_sea.Name :=sr.Name ;
buffer.rec_sea.ExcludeAttr :=sr.ExcludeAttr ; buffer.rec_sea.FindHandle :=sr.FindHandle ;
buffer.rec_sea.FindData :=sr.FindData ; buffer.path:=sp; buffer.found:=found;
RecFile.Writebuffer(buffer,sizeof(buffer));
RecFile.Free;
end;
Application.ProcessMessages;
sysutils.FindClose(sr);
end;
Данная статья не претендует на оригинальность и призвана помочь в разработке своих программ,
если есть замечания, усовершенствования, пишите: Звягинцев Павел.
[Статью прислал: Звягинцев Павел, получив за это 10 баллов]. Присылайте свои статьи по адресу delphi-faq@list.ru с темой 'Clause' (без кавычек), и они будут опубликованы в ближайших выпусках рассылки. Большая просьба: статью оформляйте в -txt или -doc формате и используйте -zip или -rar сжатие (без самораспаковки). |
|||||
34. Здравствуйте все! Меня интересует вот какой вопрос: какие принципы и средства в Delphi можно использовать для написания программы по озвучиванию текста. Заранее благодарен. [Ответить]. 35. Учуся работать с базами данных. Можно ли использовать в TTable в свойстве DataBazeName каталог программы??? А то при переносе базы на другой комп приходится изменять исходник. Я конечно могу написать сложный алгоритм, но не хочется. [Ответить]. 36. Вопрос такой: как сделать вместо обычного курсора песочные часы, так чтобы они были над всей формой, а не над отдельными компонентами. Т.е. можно изменять форму курсора для каждого компонента, находящегося на форме, но это неудобно. Наверняка есть простой способ изменения формы курсора, как это сделано в виндах когда что-то грузится. [Ответить]. 37. Как отправить текст из переменной на сайт в интернете в текстовой или HTML файл? [Ответить]. 38. Доброго времени суток всем! При создании отчета главный-детальный при вызове Preview программа виснет. Связано ли это с данными (dBase таблицы) или я чего не того делаю? Заранее спасибо. С уважением, Александр! [Ответить]. 39. У меня два вопроса: 1. Как сделать, чтобы в ComboBox список открывался не вниз, а вверх? Может, есть другие компоненты? 2. Как открыть в Memo или RichEdit (или еще в чем-то) Text DOS? [Ответить]. |
|||||
26. (Работа с xls-файлами). [Отвечает: Feniks]: Для экспорта данных в Excel я рекомендую библиотеку VtkExport от компании VtkTools. У них есть еще и другие полезные компоненты для формирования отчетов. Библиотека экспорта бесплатная, с большими возможностями, кидает данные не в Excel, а сразу в файл xls без использования OLE, DDE, т.е. для ее работы вообще не нужен MS Office. Плюс отличный хелп на русском. 30. (Редактирование реестра из командной строки). [Отвечает: Igor]: Для редактирования системного реестра из командной строки используйте reg.exe(он у меня находится в папке Windows/System32). Для справки запустите reg /?, там все подробно описано. [Отвечает: Звягинцев Павел]: Ну, положим, одним батником не отделаешься. Поступим так: 1 создаем REG файл с информацией о том, что нужно занести в реестр например 1.REG: [Отвечает: Юрий]: Не очень понял вопрос, но поробую ответить... Создаешь файл *.reg (допустим 1.reg) в котором задаешь чего надо изменить... А далее зависит от системы, сети и т.д. Так для 2000(ХР, 2003) создаешь файл *.cmd (допустим 1.cmd) и пишеш в нем regedit [путь]1.reg и ставишь его в автозагрузку ... При этом пользователь должен быть администратором рабочей станции Если сеть построена на домене, то есть возможность его поставить применять в групповых политиках... В 98 и ниже тоже но через бат файл... Это если я верно понял суть вопроса. 31. (Управление приложениями MS Office). [Отвечает: Звягинцев Павел]: Да также, как и из-под любой Дельфи - используй модули EXCEL_TLB.PAS, OFFICE_TLB.PAS. Вот с модулем WORD_TLB.PAS сложнее - там часто и густо используется Application, что приводит к пересечению со стандартным типом приложения, и ошибкам. Этот модуль нужно переписать, заменив Application на MyApplication. После все работает нормально. Другой вариант - в Дельфе же есть встроенные классы TWordApplication,..., которые делают тоже самое. 25. (Ресурсы в DLL). [Отвечает: Feniks]: Если ты хочешь сохранить (хранить) некие файлы внутри своего ЕХЕ или DLL и их от туда вытягивать и работать с ними, могу посоветовать следующие на Делфи (на Билдере будет тоже самое, но другой синтаксис): создаешь текстовый файл с расширением .RC и пишешь в нем<имя ресурса> <тип хранимого ресурса> <имя файла> например: Тут перечислены стандартные типы ресурсов. так же можно использовать свои, наприме MYGIF. но лучше использовать стандартные, так тогда проще их вытягивать будет. Так как для GIF и JPG нет стандартных типов, необходимо использовать RCDATA. Потом все это сохраняешь под именем myres.rc Далее, компилируешь его с помощью утилиты brcc32 в файл .RES brcc32 myres.rc В результате получаешь myres.res Вот его потом присоединяешь в свое проект или в отдельный модель. {$R myres.res} Тот файл RES, который сама Делфя используем по умолчания для каждого проекта, лучше не использовать, получишь много головной боли хлопот. Я это сам на своей шкуре испытал. После присоединения его к проекты надо проект перебилдить (Build), а не перекомпилировать, т.к. при компиляции он не компилит файл RES в Что бы вытянуть эти ресурсы из ЕХЕ файла и сохранить их в файлы: Смотри в Хелпе: TResourceStream, LoadImage, LoadFromResourceName, LoadFromResourceID, LoadIcon, PlaySound, FindResource, FindResourceEx и т.д. и т.п.
32. (Вывод времени в строке состояния). [Отвечает: Dron]: Лично я не вижу в этом ничего неправильного. Сам делаю точно также. Более простого решения нет. Есть только специальные компоненты - навороченные статусбары, в которых есть автоматический вывод текущего времени, даты, а также отображение состояния клавиш Num, Caps и Scroll Lock'ов. Но это особо не нужно и легко сделать самому. Так что спокойно можешь так и оставлять. Единственное, что хочу добавить, - Timer должен иметь частоту срабатывания РОВНО 1000 миллисекунд (т.е. 1 секунду). Если поставить больше или меньше, то вывод времени с точностью до секунд будет колебаться, подобно синусоиде Если непонятно, почему - поставь Interval = 750 и посмотри. Разница очевидна. [Отвечает: Vasiliy Gorshkov]: var dt:TDateTime; ... dt:=now; statusbar.value:=DateTimeToStr(dt); Быстрые ответы Как видите, появился ещё один новый раздел - "Быстрые ответы". Его пришлось создать по очень простой причине: на нашу рассылку подписаны также и новички в программировании. И вот пришёл простейший вопрос, публиковать который просто нет смысла. Такие вопросы будут публиковаться в этом разделе, а отвечать на них будет администратор (т.е. я :) ). -1. (Какой функцией проверить файл на наличие???). [Отвечает: Администратор]: Это функция FileExists('путь_к_файлу'): Boolean. True - существует, False - нет. Также скажу, что если у вас есть подобные, простые вопросы, то всё равно их присылайте - программированию нужно не только учиться, но запоминать многие вещи.Вы также можете ответить на предыдущие вопросы. Поскольку на них уже ответили как минимум раз, они больше не публикуются в рассылке. Но если вы можете что-то добавить к ответам других, пожалуйста, отвечайте - ответы будут опубликованы. Найти предыдущие вопросы вы можете на нашем сайте: http://www.delphi-faq.fatal.ru/. |
|||||
Здесь представлены ссылки на дружественные сайты нашего портала. Если вы тоже хотите стать нашим другом, разместите баннер на главной странице своего сайта. Подробнее о том, как стать другом, можно прочитать здесь: http://www.delphi-faq.fatal.ru/banner.htm, а узнать о всех наших друзьях - на странице http://www.delphi-faq.fatal.ru/friends.htm http://www.x-program.narod.ru/ - На нашем сайте Вы найдёте некоторые наши программы.
Также мы занимаемся создание ПО для любой версии ОС Windows под заказ. |
|||||
CONNECT приходит и уходит, - 'Не' с глаголами пишется слитно или раздельно? На уроке литературы с углубленным изучением компьютерных технологий: Житель крайнего севера в компьютерном магазине: В ходе судебного разбирательства с 'Microsoft' были предложены четыре варианта решений: Присылайте свои "компьютерные" анекдоты по этой ссылке: 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 |
Отписаться |
В избранное | ||