I-1: Версия от 27.04.2002

Конференция: fido7.ru.delphi.chainik.

I-2: Введение

FAQ для конференции fido.ru.delphi.chainik, основано на вопросах в данной конференции.

I-3: Авторские права

Copyright (C) Anatoly Podgoretsky, 2001

I-4: Преамбула

Пожалуйста, не задавайте вопросы в этой конференции, до того, как прочтете этот документ, правила конференции, ознакомитесь со списком рекомендованной литературы и проведете самостоятельные исследования вопроса. Желательно также ознакомиться с архивом конференции за два-три последних месяца.
Это поможет всем вам сохранить конференцию интересной и полезной.

I-5: О поле Subject:

Правилами конференции, в частности, регламентируется содержание поля Subject: ваших писем. Дело в том, что многие из тех, кто мог вы вам помочь, читают эхи методом "по сабджектам", сознательно не тратя время на письма под заголовком "Help!", "Проблема" или "Вопрос чайника". Подумайте об этом.

Отсутствие же заголовка вообще дезоринентирует остальных подписчиков конференции и потому считается явным неуважением к ним и может вызвать ядовитый вопрос "ТЫ МЕНЯ УВАЖАЕШЬ". На какой ответ может расчитывать тот, кто даже поленился сформулировать свой вопрос.

I-6: Здесь не приветствуется

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

* не уважительное отношение к участникам конференции. Как правило это в основном люди делающие свои первые шаги в программировании.

* Ответы типа RTFM, рекомендуется приводить небольшой кусок кода демонстрирующий решение проблемы. В случае же ссылки на хелп, желательно указывать название темы.

I-7: Доступность этого FAQ

Этот документ регулярно изменяется по результатам обсуждения в конференции. Вы можете поучаствовать в составлении документа, прислав по адресу faq@podgoretsky.com сформулированный вариант вопроса, ответ или дополнение или исправление к ответу. Большие куски кода неуместны в FAQ. В любом случае, вы можете обратиться к авторам сопутствующих проектов, список которых приведен ниже.

Разрешается свободное распространение и использование этого документа при соблюдении определенной вежливости по отношению к автору и читателям, основной составляющей чего является соблюдение целостности документа. Hе очень приветствуется выкладывание копий этого документа на WWW: подумайте, нужны ли вам непрерывные усилия по синхронизации?

Если же вы вынуждены использовать этот документ на сайте, для того, чтобы создать его содержимое, подумайте, нужен ли вообще ваш сайт?

Свежая версия этого документа находится на домашней странице автора http://www.podgoretsky.com (доступен движок FaqMaker.exe с его исходными тексты и последними версиями баз).
Альтернативный источник http://faq.delphiplus.org - более быстрый канал, плюс FAQ доступен не только в dBase формате, но и в HTML формате.

Остерегайтесь подделок.

I-8: Источники информации

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

Список литературы на все интересующие темы, рекомендованный к прочтению, находится в неофициальном FAQ. эхоконференции RU.BOOKS.COMPUTING. Свежие версии этого FAQ. регулярно публикуются в соответствующей эхоконференции, а также доступны на домашней странице автора.

Учтите, что кроме книг по Delphi вас могут интересовать также издания, посвященные программированию под Windows и проектированию баз данных. Delphi, в сущности, является обычным компилятором для Windows, и довольно большое количество вопросов, которые у вас возникнут, будут не столь уж сильно ориентированы именно на Delphi.

В данный момент в FAQ введен пункт "Список рекомендуемой литературы", конечно он не полный, но может служить как отправная точка.

Само собой, хотелось бы увидеть у активного участника конференции определенные знания языка программирования Object Pascal, являющегося основой Delphi, а также знаний в области программирования вообще, программирования под Windows в частности, а также предметной области своей собственной задачи. Без всякого сомнения, вы можете общаться и задавать вопросы на любом уровне, но ожидайте соответствующей реакции извне.

Hаучитесь также пользоваться системой помощи, поставляемой вместе с Delphi. Как это ни прискорбно, весьма ощутимый процент задаваемых в эхе вопросов легко снимается нажатием кнопки F1 и поиском примерного перевода вопроса на английский язык. Примером тому может являться сакраментальный вопрос о получении короткого имени файла из длинного и ответ: GetShortPathName. Да, скорее всего вам придется восполнить свои пробелы в школьном образовании и изучить некоторое подмножество английского языка, без коего вы имеете не столь много шансов успешно функционировать в выбранной области.

Учтите наличие в поставке Delphi большого количества разнообразных примеров. Возможно, ознакомившись с ними, вы приобретете дополнительные знания. Изучите исходные тексты Visual Component Library, поставляемой вместе с Delphi Professional и Delphi Client/Server, а также хорошие образцы кодирования и проектирования, например, исходники rxLib.
Кроме того исходные тексты дельфи являются не только пособием по VCL, но и 2-3 килограмма легкоусвояемого WinAPI.

По мере освоения Дельфи, возможно, вам следует приобрести тем или иным способом ту часть Microsoft Developer Network (MSDN), что содержит в себе документацию. Это диски с названиями "Platform SDK", "Additional SDKs and Tools" и "DDKs". В них содержится более свежая, более полная и обширная информация по всем аспектам программирования под Windows. Подписка на эту часть MSDN (это первый уровень) стоит не столь дорого и вы имеете все шансы купить ее, например, для своей организации. Более того, на http://msdn.microsoft.com можно получить доступ к львиной доле документации из MSDN.

Традиционно обитатели RU.DELPHI питают заслуженную любовь и уважение к библиотеке rxLib. Это большая библиотека компонент для Delphi всех версий и C++Builder, распространяемая по системе freeware с полными исходными текстами и файлами помощи на русском языке. Выяснено, что эта библиотека способна покрыть очень большое количество запросов программистов на Delphi самого разного уровня, и в частности, именно на нее будут даваться обильные ссылки далее по тексту. Дополнительную информацию вы можете получить по адресу http://www.rxlib.com.

По возможности фидошные обитатели RU.DELPHI помещают интересные файлы в так называемые файлэхи. Официальной файлэхой RU.DELPHI является WDEVDELPHI. Ценным ресурсом являются файлэхи группы FED* (модератор -- Акжан Абдулин, 2:5040/55). Если вы читаете RU.DELPHI из Фидо, то подпишитесь на эти файлэхи и научитесь пользоваться файловыми запросами (FReq'ами), так как многие узлы хранят файлы, проходившие по
файлэхам, в течение довольно долгого времени. Обратитесь к вашему боссу в случае затруднений. Если же вы из Интернета, то поисковые машины, такие как http://www.altavista.com, http://ftpsearch.lycos.com, а также крупнейший архив ньюсгрупп http://www.dejanews.com, станут вашими лучшими помощниками. Вам следует также заметить, что существует определенное количество FTP-архивов, содержащих вышеупомянутые файлэхи, например, ftp://bbs.ogo.ru.

Само собой, Интернет переполнен ресурсами, посвященными Borland Delphi. Для начала хороший список ссылок можно найти на официальной странице rxLib: http://www.rxlib.com.
В данный момент проект закрыт и источники получения весьма неопределены. Подробности в статье по RxLib из FAQ конференции ru.delphi

Приведенные источники со временем могут пропадать, это судьба всех проектов.

Q-9: Каким именно релизом Delphi вообще стоит пользоваться для каждой конкретной версии?

Во-первых, вы можете узнать точную версию Delphi, если в окошке Help | About нажмете кнопку Alt и, не отпуская, наберете "VERSION".

Delphi 1 следует апгрейдить до версии 1.02 с помощью патчей.

Delphi 2 следует апгрейдить до версии 2.01. Это полноценный дистрибутив. Эту версию можно, в частности, узнать по странице "Internet" в палитре компонентов. Ее точная версия 2.0.76.0.

Delphi 3 следует взять версии 3.02. Это полноценный дистрибутив 3.01 и патчи до 3.02.

Delphi 4 же должна быть обновлена вторым, а затем третьим Service Pack'ами, которые можно взять на сайте Inprise.
Версии Delphi 4.3 и 4.5 являются обманными версиями. В действительности это ранние беты Delphi 4.0.

Delphi 5 же должна быть обновлена первым и вторым (обновление справочной системы) Service Pack'ами, которые можно взять на сайте Inprise.
Версия Delphi 5.5 также является обманной версией.

Q-10: Delphi 2 и 3 не отображают русские TTF под Windows NT WorkStation + ServicePack#3

(AlPe): Попробуй сделать в

[HKLM\Software\Microsoft\Windows NT\CurrentVersion\FontMapper]
DEFAULT=0xcc (204) вместо 0x00 (Именно DEFAULT, а не (Default) :-)

получше маленько будет...

Q-11: Как установить компонент от Delphi одной версии под Delphi другой версии, если имеется только .DCU

Hикак. Фирма Borland всегда поддерживала несовместимость .DCU-файлов между разными версиями. Ищите исходник или .DCU, скомпилированный для соответствующей версии Delphi.

Q-12: Delphi 4 виснут при запуске. Видеокарта S3 Virge.

REGEDIT4
[HKEY_CURRENT_CONFIG\Display\Settings]
"BusThrottle"="on"

Если не помогает, то попробуйте добавить в system.ini:

[Display]
"BusThrottle"="On"

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

Q-13: Можно ли скомпилировать на Delphi 2/3/4 программу, работающую под Windows 3.1?

NP): Hет, но в дистрибутиве с Delphi 2/3/4 поставляется Delphi 1 специально для этой цели.

Q-14: Как мне вывести какое-нибудь окошко с картинкой, пока программа грузится?

Смотрите пример в X:\DELPHI\DEMOS\DB\MASTAPP\mastapp.dpr.

Удобно использовать функцию ShowSplashWindow из rxLib.

Q-15: Как мне перекодировать строки из Win-кодировки в Dos-кодировку и наоборот?

CharToOEM, OEMToChar, CharToOEMBuff, OEMToCharBuff. Заметьте однако, что эти функции не умеют делать таких, например, вещей, как koi8-r в DOS и т. п.

Q-16: Как вывести диалог выбора каталога?

(DS): SelectDirectory, rxLib: TDirectoryEdit.

Из современных средств SHBrowseForFolder

Q-17: Не пересовываются окна во время длинного цикла

Моя программа довольно долго делает какую-то полезную работу, типа чтения дерева каталогов или обильных вычислений, и в этот момент почти не работают остальные программы. Как разрешить им это делать?

Application.ProcessMessages.

Q-18: Как мне запустить какую-нибудь программу

WinExec() или ShellExecute. Первая оставлена для совместимости с Win 3.1, у второй к тому же больше возможностей.

uses
ShellApi;

ShellExecute(Handle,'Open','c:\path\prog.exe',nil,nil,SW_SHOWNORMAL)

Последний параметр функции описан в Win32.hlp

Анатолий Подгорецкий

Q-19: Как сделать так, чтобы при щелчке по кнопке или по TLabel запускался браузер

uses
ShellApi;

В обработчике OnClick метки или клавиши ввести следующий код.

ShellExecute(Handle,'open','http://faq.delphiplus.org',nil,nil,SW_SHOWNORMAL);

Q-20: Как сделать так, чтобы при щелчке по кнопке или по TLabel отправить письмо

В разделе uses
ShellAPI.

В обработчике OnClick метки или клавиши ввести следующий код.

ShellExecute(Handle,'open','mailto:lalala@lala.ru',nil,nil,SW_SHOWNORMAL);

Q-21: Как использовать свои курсоры в программе?

{$R CURSORS.RES}

const
crZoomIn = 1;
crZoomOut = 2;

Screen.Cursors[crZoomIn] := LoadCursor(hInstance, 'CURSOR_ZOOMIN');
Screen.Cursors[crZoomOut] := LoadCursor(hInstance, 'CURSOR_ZOOMOUT');

С вашей программой должен быть слинкован файл ресурсов, содержащий соответствующие курсоры.

Q-22: Как объявлять переменные, что бы они были видны в других модулях проекта.

Лучше всего создать отдельный модуль для таких переменных, назвать его скажем ComVars.pas и подключать его в остальных модулях.

unit ComVars;

interface

var
MyVar : Integer

implementation
end.

Кроме этого модуля полезно создать еще два

ComConst - для общих констант
ComUtils - для общих процедур



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

Использовать для форматирования фунцию FormatFloat('0.00',Variable) для переменных типа Float

Для переменных типа Currency функцию CurrToStrF

Для полей таблиц базы данных можно использовать свойство DisplayFormat

Олег Степанов
------------------------
Можно использовать переменную CurrencyDecimals := 2;
Особенно помогает в Win95, где в установках по умолчанию обычно нет копеек (их в те времена и не было в России ;-).
Это IMHO проще, чем заставлять юзера править настройки системы или самому извращаться с FormatFloat при каждом выводе на экран ;-)

Q-24: Как сделать так, чтобы по Alt-F4 форма не просто закрывалась, а выдавала запрос на сохранение?

Обрабатывать OnCloseQuery.

CanClose := Application.MessageBox('Закрыть программу?', 'Запрос', MB_OKCANCEL + MB_DEFBUTTON1) <> IDOK;

-----------------------------------------------

procedure TForm1.WMQueryEndSession; // message WM_QUERYENDSESSION;
{расскоментировать // message .. в объявлении TForm1}
begin
FReason := 1; // поле формы : Longint;
msg.Result := LParam(True);
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if (FReason = 0) then
case Application.MessageBox( 'Сохранить данные?',
'Запрос',
MB_YESNOCANCEL + MB_DEFBUTTON1) of
mrYes: FReason := 2;
mrNo: ;
mrCancel: CanClose := False;
end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
case FReason of
0: {сохранение не требуется} ;
1: {завершение сессии} ;
2: DoSaveData (..) ;
end;
end;

Leonid Troyanovsky

Q-25: Кaк yзнaть кaкиe фyнкции нaхoдятcя в DLL и кaк их иcпoльзoвaть?

Леонид Трояновский

%delphi%\bin\tdump.exe
MS Quick View

Если без документации, в слепую - не получится.
Еще надо знать параметры и возвращаемый результат.

Если заголовок есть, он описывается в разделе implementation как external. Обычно библиотеки используют соглашение stdcall. (реже cdecl, дельфийские - register).

Q-26: Как выдвинуть дверцу CD-ROM'а?

mciSendString('Set cdaudio Door Open Wait', nil, 0, handle);

Q-27: Почему у меня record a : word; b : longint end; имеет размер восемь байт вместо шести?

Если не использовать ключевое слово packed, то Дельфи производит выравнивание структуры на определенную границу. В разных версиях Дельфи по разному.

Для того что избежать этого, надо описать структуру следующим образом:

aRec = packed record
a : Word;
b : LongInt;
end;

Также не стоит использовать фундаментальные типы, так как их размерность зависит от версии Дельфи.

Q-28: Как отследить "уход" курсора мыши с компонеНты?

Надо обрабатывать события CM_MOUSEENTER/CM_MOUSELEAVE.

Q-29: Можно ли сделать так, чтобы в исполняемом файле программы находился какой-нибудь звук в формате .wav

Anatoly Podgoretsky:

Для этого надо создать файл описания ресурса, например Waves, в который поместить следующие строки:

SOUND1 WAVE WMyWave1.wav
SOUND2 WAVE WMyWave2.wav

Затем запустить ресурс на компилияцию brcc32.exe Waves.rc, в результате получится файл ресурса Waves.res.

В своей программе подключаем ресурс (в любом модуле):

{$R Waves.res}

Для проигрывания звука можно использольвать функцию PlaySound

PlaySound('SOUND1', 0, SND_ASYNC or SND_RESOURCE);



Олег Степанов:

если Delphi 5, то можно .rc прямо в проект включать

Q-30: Я создал объект TStrings, но при попытке обращения к нему выдается ошибка.

TStrings -- это базовый класс. Вам нужен TStringList.

Q-31: Где достать процедуру типа "сумма прописью"?

(Vladimir Gaitanoff, 2:5020/880.5), http://www.tsinet.ru/~vg. Здесь лежит библиотека vgLib, содержащая еще массу полезных вещей.

Q-32: Мне нужно заниматься разбором математических выражений

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

В rxLib есть компонент TrxMathParser, достаточно мощный для большого количества применений.

Q-33: Где достать всяких иконок, картинок для кнопок, etc. для своей программы?

http://www.iconbazaar.com

Q-34: Как правильно создавать компоненты в run-time?

Как правильно создавать компоненты в run-time? Что задавать в качестве параметра Owner при создании компоненты? Как обрабатывать события от созданных компонент, типа нажатий на кнопки?

Hачнем с создания.

Сущность свойства Owner в том, что владелец перед смертью уничтожает (через Free) принадлежащие ему объекты. Таким образом, все зависит от того, кому вы хотите доверить уничтожение созданных форм/компонентов. В частности, если вы сами будете этим заниматься, то AOwner может быть, например, nil.

Для того, чтобы созданный компонент появился на экране, надо указать его родителя, заполнив свойство Parent, например,
NewButton.Parent := Form1;

Пример кода, обрабатывающего события от свежесозданных компонентов:

type
TForm1 = class(TForm)
{ ... }
private
{ эта процедура будет вызываться при нажатии на кнопку }
procedure ButtonClicked(Sender : TObject);

public
{ в этой процедуре происходит создание кнопки }
procedure CreateButton;

end;

{ ... }

procedure TForm1.CreateButton;
var
btn : TButton;
begin
btn := TButton.Create(Self); // Уничтожать кнопку будет форма
btn.Parent := Self; // Родителем кнопки будет форма
btn.OnClick := ButtonClicked; // Процедура, которая будет исполняться при
btn.Visible := true; // нажатии на кнопку
end;

Q-35: Как сделать так, чтобы запущенная программа не была видна на панели задач?

Во-первых, можно по примеру Back Orifice воспользоваться функцией RegisterServiceProcess (только для Win9x).

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

(EM, DS):

type
TForm1 = class(TForm)
Label1: TLabel;
RxTrayIcon1: TRxTrayIcon;
procedure FormCreate(Sender : TObject);
procedure RxTrayIcon1DblClick(Sender: TObject);
private
procedure ApplicationMinimize(Sender : TObject);
procedure ApplicationRestore(Sender : TObject);
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMinimize := ApplicationMinimize;
Application.OnRestore := ApplicationRestore;
ShowWindow(Application.Handle, SW_HIDE);
end;

procedure TForm1.ApplicationMinimize(Sender : TObject);
begin
ShowWindow(Application.Handle, SW_HIDE);
end;

procedure TForm1.ApplicationRestore(Sender : TObject);
begin
ShowWindow(Application.Handle, SW_RESTORE);
end;

procedure TForm1.RxTrayIcon1DblClick(Sender: TObject);
begin
Application.Restore;
Application.BringToFront;
end;

(AK):
Только сpазу предупреждаю про грабли, на которые я наступал -- будь готов к тому, что если пpи попытке закрытия приложения в OnCloseQuery или OnClose выводится вопрос о подтверждении, то могут быть проблемы с автоматическим завершением пpогpаммы пpи shutdown -- под Win95 просто зависает, под WinNT не завершается. Очевидно, что сообщение выводится, но его не видно (причем SW_RESTORE не сpабатывает). Решение -- ловить WM_QUERYENDSESSION и после всяких завеpшающих действий и вызова CallTerminateProcs выдавать Halt.

Q-36: Delphi 5.0 and Win2K

--- Vladimir Kladov

1. Если кто не читает readme-файлы до начала установки, то с интересом узнает, что в сопроводиловке от Борланд указывается на проблему неправильной работы инсталлятора, если используются кнопки Browse для смены каталогов установки. При этом рекомендуется набрать/подредактировать пути вручную. (Не проверял, просто действовал
как рекомендовано, хотя пути по умолчанию никогда не использую).

2. При установке с жесткого диска, весь дистрибутив вместе с папками Runimage и Install надо либо поместить в корень логического диска (что обычно неудобно), либо используя subst (или в сети - use net), сотворить букву для этого пути. Чтобы инсталлятор решил, что установка идет из корня диска. Иначе - облом-с.

3. При установке на машину, на которой предполагается наличие нескольких программеров, работающих посменно, сначала придется поставить из-под админа - для всех. А потом - из-под каждого аккаунта (хотя бы в режиме Registry + Custom). Иначе не будет компонентов на палитре.

4. Проверить переменные среды %TEMP% и %TMP%, рекомендуется короткий путь - C:\TEMP

5. Первичная установка под административным аккаунтом с АНГЛИЙСКИМ именем, например admin

--- Ruslan Fedoseev

Можно экспоpтиpовать y админа HKEY_CURRENT_USER/Software/Borland и пpосто
импоpтиpовать для каждого потом. Так несколько быстpее, чем инсталиpовать и уменьшается количество ошибок.

Q-37: String в PChar и обратно

Для этого достаточно приведения

StringVar := String(PCharVar);
PCharVar := PChar(StringVar);

Q-38: Как сделать печать формы из Дельфи?

Form.Print

Q-39: Где можно найти список с пpимеpов из каталога DEMOS?

Часть примеров кратко описана в delphiX.hlp в разделе What's new.

Также, можно заглянуть в readme.txt из директории Delphi.

При поиске интересующего примера, можно воспользоваться (прямо из D) Search-Find in files и искать слова в директории+субдир Demos.

Q-40: Как при наведении курсора на кнопку менять ее цвет?

type
TForm1 = class(TForm)
BitBtn1: TBitBtn;
procedure FormCreate(Sender: TObject);
private
procedure NewBtnWindowProc(var Msg:TMessage); // Это новый обработчик
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

var
OldBtnWindowProc : TWndMethod;

procedure TForm1.NewBtnWindowProc;
begin
case msg.Msg of
CM_MOUSELEAVE: BitBtn1.Font.Color := clGray;
CM_MOUSEENTER: BitBtn1.Font.Color := clBlack;
end;
OldBtnWindowProc(Msg);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
OldBtnWindowProc := BitBtn1.WindowProc;
BitBtn1.WindowProc := NewBtnWindowProc;
BitBtn1.Perform(CM_MOUSELEAVE,0,0); // Изначально серый
end;

Q-41: Как нажать кнопку в чужой программе?

Так можно нажать на кнопку OK диалога "About Notepad":

h1 {:HWND} := FindWindow(nil, 'About Notepad');
h2 {:HWND} := FindWindowEx(h1, 0, 'BUTTON','OK');
SendMessage(h2, BM_CLICK,0,0);
SendMessage(h2, BM_CLICK,0,0); // если Notepad был неактивен

Q-42: Как сделать индикатор прогресса для длительного запроса?

Так как оценить объем запроса до его выполнения сложно, то совсем непросто придумать (и сделать) что-то лучше, чем показать пользователю TAnimate.

Однако, чтобы показывать что-либо при большом запросе придется выполнять запрос в потоке. См. пример %delphi%\demos\db\bkquery

Q-43: Как получить набранный в Блокноте текст в свою пpогpаммку?

function GetWindText(AHandle: THandle): String;
var
cb : DWord;
begin
cb := SendMessage(AHandle, WM_GETTEXTLENGTH, 0, 0);
SetLength(Result, cb);
if cb > 0 then
SendMessage(AHandle, WM_GETTEXT, cb+1, LParam(@Result[1]));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
AHandle: THandle;
begin
AHandle := FindWindow('Notepad', nil);
Win32Check(AHandle <> 0);
AHandle := FindWindowEx(AHandle, 0, 'Edit', nil);
Win32Check(AHandle <> 0);
Memo1.Text := GetWindText(AHandle);
end;

Q-44: Как скопировать экран в буфер обмена?

keybd_event(VK_SNAPSHOT, 0, 0, 0);

Q-45: Как показать Hint для MenuItem?

Нint, назначенный Item, можно показать в Statusbar:

procedure TForm1.AppHint(Sender: TObject);
begin
StatusBar1.SimpleText := Application.Hint;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnHint := AppHint;
end;

Q-46: Как сделать прозрачным фон при выводе Canvas.TextOut?

Canvas.Brush.Style := bsClear;

Q-47: Как применить изменение в реестре без перезагрузки компьютера?

Многие программы могут откликнуться на:

SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, ..) в Win9х
SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, ..) в NT

Q-48: Как в Мемо установить карет в нyжнyю позицию?

with Memo do
SelStart := Perform(EM_LINEINDEX, LineIndex, 0) + CharIndex;

PS: карет - это специальный указатель позиции ввода следующего символа, не путать с курсором мышки.

Q-49: Как сделать в меню список последних открытых файлов?

Пусть список файлов хранится в FileList : TStringList, a mmReopen : TMenuItem - пункт меню, содержащий ссылки на файлы, тогда при изменениии списка файлов надо сделать:

{var NewItem: TMenuItem}

for I := mmReopen.Count -1 downto 0 do
begin
mmReopen.Delete(I);
end;

for I := 0 to lf.Count-1 do
begin
NewItem := TMenuItem.Create(mmReopen);
NewItem.Caption := '&'+IntToStr(I) + ' ' + FileList.Strings[I];
NewItem.OnClick := FileOpenProc;
mmReopen.Add(NewItem);
end;
...
procedure FormX.FileOpenProc(Sender : TObject);
var
Filename : String;
begin
Filename := FileList.Strings[mmReopen.IndexOf(TMenuItem(Sender))];
...
end;

Q-50: Какое событие происходит при минимизации окна?

OnResize
Для MainForm : Application.OnMinimize

Q-51: Как сохранить в ini файле настройки TFont?

uses
IniFiles;

procedure TForm1.Button1Click(Sender: TObject);
var
IniFile : TIniFile;
begin
IniFile := TIniFile.Create('myIni.ini');
with Edit1.Font do with IniFile do begin
Name := ReadString ('Font','Name','MS Mans Serif');
Charset := ReadInteger('Font','Charset',RUSSIAN_CHARSET);
Color := ReadInteger('Font','Color', clWindowText);
Height := ReadInteger('Font','Height',-11);
Size := ReadInteger('Font','Size',8);
Style := TFontStyles(Byte(ReadInteger('Font','Style',0)));
end;
IniFile.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
IniFile : TIniFile;
begin
IniFile := TIniFile.Create('myIni.ini');
with Edit1.Font do with IniFile do begin;
WriteString ('Font','Name', Name);
WriteInteger('Font','Charset', Charset);
WriteInteger('Font','Color', Color);
WriteInteger('Font','Height', Height);
WriteInteger('Font','Size', Size);
WriteInteger('Font','Style',Byte(Style));
end;
IniFile.Free;
end;

Q-52: Как закрыть внешнюю программу?

Например, Блокнот можно закрыть так:

procedure TForm1.Button1Click(Sender: TObject);
var
phandle : HWND;
begin
phandle := FindWindow('Notepad', nil);
if phandle = 0 then
RaiseLastWin32Error;
SendMessage(phandle, WM_CLOSE, 0, 0);
end;

Q-53: Как загрузить из ImageList иконку приложения?

ImageList1.GetIcon(Idx, Application.Icon);

Q-54: Как отловить нажатие Enter в TEdit?

IMHO, чтобы сделать в духе Windows, то добавь к Edit один TButton, с свойством default := True, обработчик OnClick которой будет делать нужную работу.

Другие варианты, чреваты тем, что может сработать не то, что ожидается.

Вот последовательность как будут вызываться обработчики при нажатии Enter
1. OnClick кнопки default
2. OnClick формы, если у нее KeyPreview := True;
3. OnKeyDown/KeyPress/KeyUp контрола имеющего фокус ввода.

Это особенность роли, которую этой клавише обычно назначают в win приложениях. Обрати также внимание на свойство TButton Cancel - оно заставляет срабатывать кнопку при нажатии Esc

Для того чтобы разобраться в этих моментах попробуй неколько вариантов, снимая комментарии:

procedure TForm1.Button1Click(Sender: TObject);
begin
//Button1.Default := True;
ShowMessage('Key1');
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
//KeyPreview := True;
if Key = #13 then
begin
ShowMessage('Key2');
Key := #0;
end;
end;

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if key = #13 then
ShowMessage('Key3');
end;

Q-55: В какой позиции Memo находится каретка?

var
LineNum, Charnum: Integer;
...

LineNum := Memo1.Perform(EM_LINEFROMCHAR, -1, 0);
CharNum := Memo1.Perform(EM_LINEINDEX, LineNum, 0);

Q-56: Почему после RichEdit1.Lines.SaveToFile(name) в файле, кроме моего текста, ещё всякий бред написан?

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

RichEdit1.PlainText := True;

Q-57: Как вставить картинку в TDrawGrid?

procedure TForm1.DrawGrid1DrawCell(Sender: TObject; Col, Row: Integer;
Rect: TRect; State: TGridDrawState);
begin
if (Sender is TDrawGrid) and
not (gdFixed in State) then
TDrawGrid(Sender).Canvas.Draw(Rect.Left, Rect.Top, Image1.Picture.Graphic);
end;

Q-58: Как дождаться завершения программы, запущенной ShellExecute?

uses
ShellAPI;

procedure TForm1.Button1Click(Sender: TObject);
var
ProcInfo: PShellExecuteInfo;
begin
(Sender as TControl).Enabled := False;
GetMem(ProcInfo, SizeOf(ProcInfo^));
with ProcInfo^ do begin
Wnd := Handle;
cbSize := SizeOf(ProcInfo^);
lpFile := PChar('notepad.exe');
lpParameters := nil;
lpVerb := 'open';
nShow := SW_SHOW;
fMask := SEE_MASK_DOENVSUBST or SEE_MASK_NOCLOSEPROCESS;
end;
try
Win32check(ShellExecuteEx(ProcInfo));
while not Application.Terminated and
(WaitForSingleObject(ProcInfo.hProcess, 100)=WAIT_TIMEOUT) do
Application.ProcessMessages;
finally
if ProcInfo.hProcess <> 0 then CloseHandle(ProcInfo.hProcess);
Dispose(ProcInfo);
(Sender as TControl).Enabled := True;
end;
end;

Q-59: Как в TMemo вставить дату в позицию каретки?

Memo1.SetSelTextBuf(PChar(DateToStr(Date)));

Q-60: Как отловить системную ошибку при операциях с файлами?

Для Паскаль функций, например, BlockWrite, можно использовать такую конструкцию:

try
BlockWrite(f, buf, count); //См.также хелп: параметр AmtTransferred
..
except
on E:EInOutError do
begin
ShowMessage('Произошла ошибка записи ' + E.Message);
..// пытаемся что-то поправить
if {не удалось} then
raise; //Повторно возбуждаем исключение, чтобы не удалить файл
end;
end;
..
CloseFile(..);
DeleteFile(..);

Q-61: Как узнать, была ли создана ли определенная форма?

function IndexOfForm (const AClassName: String; const FromIndex: Word):Integer;
var
i : Integer;
begin
Result := -1;
for i := FromIndex to Screen.FormCount-1 do
if (CompareText(Screen.Forms[i].ClassName, AClassName) = 0) then
begin
Result := i;
Break;
end;
end;

Q-62: Что такое Handle окна, и как его полyчить?

Handle - это число - уникальный идентификатор окна (в данном случае) в системе.
Получить его можно, например, так:

hwnd := FindWindow (nil, 'Form1'); //ищем окнo с заголовком "Form1"
if hwnd <> 0 then {нашлось};

Q-63: Как проиграть midi файл?

uses
MPlayer;

var
mp : TMediaPlayer;

procedure TForm1.Button1Click(Sender: TObject);
begin
with Sender as TButton do
case Tag of
0 :
begin
Tag := 1;
mp := TMediaPlayer.CreateParented(Handle);
mp.DeviceType := dtSequencer;
mp.FileName := 'c:\winnt\media\Canyon.mid';
mp.Wait:= True;
mp.Open;
mp.Play;
end;
1 :
begin
Tag := 0;
mp.Wait := True;
mp.Stop;
mp.Free;
end;
end;
end;

Q-64: Как обратиться к свойству по его имени?

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
f1 : Integer; // Это приватное поле хранит значение
published
{К свойству p1 мы будем обращаться по его имени}
property p1 : Integer read f1 write f1;
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

uses
TypInfo;

procedure TForm1.Button1Click(Sender: TObject);
var
PInfo : PPropInfo;
begin
p1 := GetTickCount; // Здесь свойству что-то присвоили

PInfo:= GetPropInfo(TForm1.ClassInfo, 'p1'); // Получаем описание свойства
// из описания класса
if PInfo = nil then
raise Exception.Create('Property not exist');
Caption := IntToStr(GetOrdProp(Form1, PInfo)); // Получаем значение свойства
end;

Q-65: Как нажать Ctrl+Del программным путем?

keybd_event(vk_control, 0, 0, 0);
keybd_event(vk_delete, 0, 0, 0);
keybd_event(vk_delete, 0, KEYEVENTF_KEYUP, 0);
keybd_event(vk_control, 0, KEYEVENTF_KEYUP, 0);

Q-66: Аналог Case для строк

Вопрос: Нужно определить с какой из заданных строк совпадает некая строковая переменная и в зависимости от этого перейти к соответсвующей процедуре. Как это выполнить без использования многочисленных if - then?

Вот способ, легко приспосабливаемый для загрузки списка из строки, файла или ресурса:

const
vlist = 'первый, второй, третий';

var
Values: TStringList;

procedure SetValues(VL : TStringList; S: String);
var
I : Integer;
begin
VL.CommaText := S;
for I := 0 to CL.Count-1 do
VL.Objects[I] := Pointer(I);
VL.Sorted := True;
end;

function GetValueIndex(VL : TStringList; Match: String): Integer;
begin
Result := VL.IndexOf(Match);
if Result >= 0 then
Result := Integer(VL.Objects[Result]);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
case GetValueIndex(Values, Edit1.Text) of
-1: {не найден} ;
0: Caption := '0';
1: Caption := '1';
2: Caption := '2';
end;
end;

initialization
VL := TStringList.Create;
SetValues(VL, vlist);

finalization
VL.Free;

Q-67: Как в TListBox пеpетаскивать итемы?

DragMode := dmAutomatic;

{OnDragOver}
procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := True;
end;

{OnDragDrop}
procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
NewIndex : Integer;
begin
with Sender as TListBox do begin
NewIndex := ItemAtPos(Point(X,Y), True);
Items.Move(ItemIndex, NewIndex);
ItemIndex:= NewIndex;
end;
end;

Q-68: Как отловить нажатие клавиш F1..F10?

procedure TForm1.AppMessage(var Msg:TMsg; var Handled: Boolean);
begin
case msg.wParam of
VK_F1..VK_F10 :
case Msg.message of
WM_KEYUP: ShowMessage('Key up');
WM_KEYDOWN: ShowMessage('Key down');
end;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage := AppMessage;
end;

Q-69: Как записать в файл несколько TImage?

procedure TForm1.Button1Click(Sender: TObject);
begin
with TFileStream.Create(FileName,fmCreate or fmOpenWrite) do begin
WriteComponentRes('IMAGE1', image1);
WriteComponentRes('IMAGE2', image2);
Free;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Image1.Free;
Image2.Free;
RegisterClass(TImage);
Image1 := TImage.Create(Self);
Image2 := TImage.Create(Self);
with TFileStream.Create(FileName, fmOpenRead) do begin
ReadComponentRes(Image1);
ReadComponentRes(Image2);
Free;
end;
Image1.Parent:= Self;
Image2.Parent:= Self;
UnregisterClass(TImage);
end;

Q-70: Как компьютеру узнать свое имя?

function GetCompName: String;
var
buffer : array [0..MAX_COMPUTERNAME_LENGTH] of Char;
cb : DWord;
begin
cb := SizeOf(buffer);
GetComputerName(buffer, cb);
Result := buffer;
end;

Q-71: Как узнать IP машины по имени?

uses
WinSock;

const
WINSOCK_VERSION = $0101;

function GetIPAddress(Name:String): string;
var
WSAData : TWSAData;
p : PHostEnt;
begin
WSAStartup(WINSOCK_VERSION, WSAData);
p := GetHostByName(PChar(Name));
Result := inet_ntoa(PInAddr(p.h_addr_list^)^);
WSACleanup;
end;

Q-72: Как показать текстовый файл в TLabel?

procedure TForm1.Button1Click(Sender: TObject);
var
fs : TFileStream;
s : String;
begin
fs := TFileStream.Create('unit1.pas', fmOpenRead or fmShareDenyNone );
SetLength(s, fs.Size);
fs.Read(s[1], Length(s));
fs.Free;
Label1.Caption := s;
end;

Q-73: Как вставить картинку в StatusPanel?

Image1.Parent := StatusBar1;

Q-74: Как показывать хинты для частично видимых элементов ListBox?

Написать для OnMouseMove:

procedure TForm1.ListBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
const
oldidx : Longint = -1;
var
idx : Longint;
begin
with Sender as TListBox do begin
idx := ItemAtPos(Point(x,y),True);
if (idx < 0) or (idx = oldidx) then Exit;
Application.ProcessMessages;
Application.CancelHint;
oldidx := idx;
Hint := '';
if Canvas.TextWidth(Items[idx]) > Width - 4 then Hint:=Items[idx];
end;
end;

Q-75: Чем отличаются TLabel и TStaticText?

TLabel is TGraphicControl
TStaticText is TWinControl

То есть у последнего есть окно, это дает возможность управлять этим контролом с помощью сообщений Windows.

Q-76: Как корректнее завершать приложение- Terminate или MainForm.Close?

Terminate очень грубый метод. Если вызывать Application.Terminate, то не сработают обработчики OnCloseQuery, OnClose главной формы.

Q-77: Как помигать Scroll Lock?

procedure TForm1.Timer1Timer(Sender: TObject);
begin
keybd_event(VK_SCROLL, 0, 0, 0);
keybd_event(VK_SCROLL, 0, vk_up, 0);
end;

Q-78: Как отобразить каталог?

ListBox1.Perform(LB_DIR, 0, LParam(PChar('*.*')));

Q-79: Как ввести текст в "чужой" Edit?

SendMessage(EditHandle, WM_SETTEXT, 0, LParam(PChar('MyText')));

Q-80: Как сделать программу без главной формы?

program Project1;

uses
Dialogs;

begin
ShowMessage('Is there anybody out there ?' );
end.

Q-81: Как показать диалог выбора директории?

из модуля FileCtrl.

1. function SelectDirectory(const Caption: string; const Root: WideString; out Directory: string): Boolean; overload;
2. function SelectDirectory(var Directory: string; Options: TSelectDirOpts; HelpCtx: Longint): Boolean; overload;

из RxLib
TDirectoryEdit

function GetDirectory(nFolder: Longint): String;
var
Bi : TBrowseInfo;
lpName: array [0..MAX_PATH] of Char;
ppidl, aItemLst : PItemIDList;
begin
SHGetSpecialFolderLocation(Application.Handle, nFolder, ppidl);
FillChar(Bi, SizeOf(bi), 0);
Bi.hwndOwner := Application.Handle;
Bi.pidlRoot := ppidl;
Bi.pszDisplayName := lpName;
Bi.lpszTitle := 'Open directory';
aItemLst := SHBrowseForFolder(Bi);
CoTaskMemFree(ppidl);
SHGetPathFromIDList(aItemLst, lpName);
CoTaskMemFree(aItemLst);
Result := lpName;
end;

Пример использования (иначе не поймут, что такое nFolder)

// значения nFolder можно найти в описании
// к SHGetSpecialFolderLocation
// из Win32 Programmer's Reference (win32.hlp)

procedure TForm1.Button1Click(Sender: TObject);
begin
Caption := GetDirectory(CSIDL_DRIVES);
end;

Q-82: Кaк искать oкнo по части eгo нaзвaния?

function FindNextWnd(StartHWND: HWND; AString : String): HWND;
var
Buffer : array [0..255] of char;
begin
Result := StartHWND;
repeat
Result := FindWindowEx(0, Result, nil, nil);
GetWindowText(Result, Buffer, SizeOf(Buffer));
if StrPos(StrUpper(Buffer), PChar(UpperCase(AString))) <> nil
then Break;
until (Result = 0);
end;

Q-83: Как yзнать текущую Ru/En pаскладкy клавиатypы?

GetKeyboardLayoutName(buffer{:array [0..KL_NAMELENGTH] of Char});
case ((StrToInt('$'+ Buffer)) and $03FF) of
LANG_ENGLISH: Caption := 'Eng';
LANG_RUSSIAN: Caption := 'Rus';
end;

Q-84: Как RichEdit сделать скролл на конец текста?

with RichEdit do begin
SelLength := 0;
SelStart := Length(Text);
Perform(EM_SCROLLCARET,0,0);
end;

Q-85: Как узнать состояние управляющих клавиш - Shift, Ctrl, Alt?

function IsKeyDown(vk: Word):Boolean;
begin
Result := GetKeyState(vk) and $8000 = $8000;
end;

vk для Ctrl, Shift, Alt соответственно равны: vk_control, vk_shift и vk_menu

Q-86: Как контрол может сам себя разрушить?

TMyWinControl = class(TWinControl)
private
procedure WMuser1(var msg: TMessage); message WM_USER+1;
...
public
procedure Release;
...
end;

procedure TMyWinControl.WMuser1;
begin
Free;
end;

procedure TMyWinControl.Release;
begin
PostMessage(Handle, WM_USER+1, 0, 0);
end;

Q-87: Как заставить MediaPlayer крутить один и тот же клип?

procedure TForm1.WMUser1(var msg:TMessage);// message WM_USER+1;
begin
with MediaPlayer1 do begin
Previous;
Notify := True;
Play;
end;
end;

procedure TForm1.MediaPlayer1Notify(Sender: TObject);
begin
if (Sender as TMediaPlayer).NotifyValue = nvSuccessful then
PostMessage(Handle, WM_USER+1, 0, 0);
end;

Q-88: Какой класс окна у консоли?

'tty' for 9x
'ConsoleWindowClass' for NT

Q-89: Как спрятать контрол, если известен его Handle?

ShowWindow(ButtonHandle, SW_HIDE); // SW_SHOW

Q-90: Как сделать окно без VCL?

program Project1;

{ Copyright (c) 1996 by Charlie Calvert

Standard Windows API application written in Object Pascal.
No VCL code included. This is all done on the Windows API
level.

Note that you need to include both Windows and Messages!}

uses
Windows, Messages;

const
AppName = 'Window1';

function WindowProc(Window: HWnd; AMessage, WParam,
LParam: Longint): Longint; stdcall;
begin
WindowProc := 0;

case AMessage of
wm_Destroy: begin
PostQuitMessage(0);
Exit;
end;
end;

WindowProc := DefWindowProc(Window, AMessage, WParam, LParam);
end;

{ Register the Window Class }
function WinRegister: Boolean;
var
WindowClass: TWndClass;
begin
WindowClass.Style := cs_hRedraw or cs_vRedraw;
WindowClass.lpfnWndProc := @WindowProc;
WindowClass.cbClsExtra := 0;
WindowClass.cbWndExtra := 0;
WindowClass.hInstance := HInstance;
WindowClass.hIcon := LoadIcon(0, idi_Application);
WindowClass.hCursor := LoadCursor(0, idc_Arrow);
WindowClass.hbrBackground := HBrush(Color_Window);
WindowClass.lpszMenuName := nil;
WindowClass.lpszClassName := AppName;

Result := RegisterClass(WindowClass) <> 0;
end;

{ Create the Window Class }
function WinCreate: HWnd;
var
hWindow: HWnd;
begin
hWindow := CreateWindow(AppName, 'Object Pascal Window',
ws_OverlappedWindow, cw_UseDefault, cw_UseDefault,
cw_UseDefault, cw_UseDefault, 0, 0, HInstance, nil);

if hWindow <> 0 then begin
ShowWindow(hWindow, CmdShow);
UpdateWindow(hWindow);
end;

Result := hWindow;
end;

var
AMessage: TMsg;
hWindow: HWnd;
begin
if not WinRegister then begin
MessageBox(0, 'Register failed', nil, mb_Ok);
Exit;
end;
hWindow := WinCreate;
if hWindow = 0 then begin
MessageBox(0, 'WinCreate failed', nil, mb_Ok);
Exit;
end;
while GetMessage(AMessage, 0, 0, 0) do begin
TranslateMessage(AMessage);
DispatchMessage(AMessage);
end;
Halt(AMessage.wParam);
end.

Q-91: Как записать массив в файл?

with TFileStream.Create('array.dat', fmCreate or fmOpenWrite) do begin
WriteBuffer(a, SizeOf(a));
Free;
end;

Q-92: О библиотеке RxLib

На сайте delphiplus.org в разделе Бесплатно|RXLibrary (http://delphiplus.spils.lv/RXLibrary.html) лежит RX Library 2.75 с help'ами и четырьмя неофициальными портами RX Library 2.75 под Delphi 6:

1. Версия 1.1 (1.18M) от Oxygen Software
2. Версия 1 (1.36M) от Dennis Ortiz
3. Патч на RxLib версия 1.5 (437K) от Polaris Software
4. Версия от Epsylon Technologies

Anatoly Podgoretsky wrote:
>
> Hi, Delphi Plus!
> You wrote to Anatoly Podgoretsky on Tue, 20 Nov 2001 16:00:55 +0000 (UTC):
>
> DP> 14.11.2001 в раздел "Бесплатно|Компоненты" выложен четвертый
> DP> неофициальный порт RX Library 2.75 под Delphi 6 (от Epsylon
> DP> Technologies).
>
> DP> http://www.delphiplus.org - ежедневные новости информационных
> DP> технологий http://www.faq.delphiplus.org - коллекция FAQ по Delphi
>
> Прекрасно, этим я больше доверяю, а как вообще насчет характеристики всех
> четырех портов, а то у людей глаза разбегаются :-)

Epsylon Technologies
-------------------
Здравствуйте!
Мы были вынуждены сделать свой вариант RxLib потому, что остальные нас немного не устраивали.
Сразу скажу, зачем нам вообще нужна библиотека RxLib - она используется в нашем продукте в качестве некоего примера всем известных компонентов. Поэтому к такой библиотеке с нашей стороны предъявлялось требование максимальной стандартности, если можно применить такой термин. Кроме того, наш продукт поддерживает несколько версий Delphi и C++Builder, поэтому от такой библиотеки требуется одновременная поддержка всех нужных нам версий компиляторов.

Естественно, мы рассматривали варианты использования уже готовой работы по адаптированию библиотеки под Delphi 6.0.
Однако:
- вариант от Polaris заточен для использования пакета Polaris Library.
Туда что-то добавлено, что-то починено, что-то переделано. Иначе
говоря, этот вариант не может быть стандартным;
- вариант от Oxygen является версией ТОЛЬКО под Delphi 6.0, содержит ряд
мелких неточностей при переводе design-time кода. Также там что-то
изменено по сравнению с 2.75. Кроме того, не переименован модуль
AppUtils.pas;
- вариант от Dennis Ortiz также является версией только под Delphi 6.0.
Ничего не могу сказать про нее - мы туда глубоко не заглядывали.

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

Наш вариант основан на общедоступном коде, и содержит модули из 2.75, включая update от 16.12.1999 и патч для C+Builder 5.0 от 30.05.2000. В эти модули добавлена возможность работы под Delphi 6.0, в том числе добавлен макрос RX_D6 и переименованы модули AppUtils и StrUtils. Все. Ничего больше. Никакая старая функциональность не удалена, никакие баги не чинились. Полдня работы.

--
Andrey Dementyev, Epsylon Technologies, http://www.epsylontech.com
Chief Software Architect

Информация от delphiplus
------------------------
1. C 19-ого декабря компания SGB Software совместно с Ником Ходж (Nick Hodges) из Borland support team займется дальнейшим развитием RxLib. Надеются выпустить 3-ю версию к середине марта 2002 года. Все желающие могут принять участие в этой работе, для этого достаточно написать на RxLIb@SGBSoftware.com.

2. На DelphiPlus выложен материал "A где сейчас RXLib?" - заметка написанная по материалам переписки в эхе fido7.ru.delphi.

Q-93: Как вывести ProgresBar на StatusBar?

--- Андрей Барташ

Gauge:=TGauge.Create(Form1);
Gauge.Parent:= StatusBar1;
Gauge.Top:=4;
Gauge.Left := 116;
Gauge.Height := 15;
Gauge.Width := 200;

Компонент TGauge находится на закладке Samples

Q-94: Как нажать клавиши в другом приложении?

"Нажимаем" клавиши в Блокноте (уже запущенном):

uses Sendkey; {описан ниже}

procedure TForm1.Button1Click(Sender: TObject);
var
h: HWND;
begin
h := FindWindow('Notepad', nil); // ищем окно Блокнота
SendMessage(h, WM_SYSCOMMAND, SC_HOTKEY, h); // активизируем его
PlayKeys(StrToKeys('abcdef')); // нажимаем клавиши
SendMessage(Handle, WM_SYSCOMMAND, SC_HOTKEY, Handle); // возвращаем фокус
end;

Коды vk_ клавиш можно найти в Win32 Programmer's Reference (win32.hlp): Virtual-Key Codes. {В дельфи не описаны коды клавиш ['A'..'Z'] и ['0'..'9'], их получают с помощью Ord, например, Ord('A'), Ord('9')}.

Символы из верхнего ряда клавиатуры посылаются с нажатым Shift. Заметим, что символы в локальной кодировке могут быть посланы после переключения кодировки в активном приложении, например, если перключатель (switch) Control-Shift, то это:

PlayKeys(Chr(vk_control)+#0+Chr(vk_shift)+#0); {downkey = #0};

--- unit Sndkey.pas ---

unit sndkey;

interface

uses
Windows,
Messages;

const
{VK constants missing from windows.pas}
VK_SEMICOLON = 186; {;}
VK_EQUAL = 187; {=}
VK_COMMA = 188; {,}
VK_MINUS = 189; {-}
VK_PERIOD = 190; {.}
VK_SLASH = 191; {/}
VK_BACKQUOTE = 192; {`}
VK_LEFTBRACKET = 219; {[}
VK_BACKSLASH = 220; {\}
VK_RIGHTBRACKET = 221; {]}
VK_QUOTE = 222; {'}

downkey = #0;
upkey = Chr(KEYEVENTF_KEYUP); {#2}

procedure PlayKeys(const keys: String);
function StrToKeys(const s: String): String;

{Alt-F4: PlayKeys(Chr(vk_menu)+#0+Chr(vk_f4)+#0+Chr(vk_f4)+#2+Chr(vk_menu)+#2)}
{"exit": PlayKeys(StrToKeys('exit'+chr(vk_return)));}
{"EXIT": PlayKeys(Chr(vk_shift)+downkey+StrToKeys('exit')+Chr(vk_shift)+upkey));}
{or short form: PlayKeys(Chr(vk_shift)+#0+StrToKeys('exit'));}

implementation

function StrToKeys; {keystroke for alone keys}
var
i: Longint;
c: Char;
begin
for i := 1 to Length(s) do
begin
c := s[i];
if c in ['a'..'z'] then {Upper}
c := Chr(Ord(c) and not $20);
Result := Result + c + downkey
+ c + upkey;
end;
end;

procedure PlayKeys;
const
ExtendedKeys : set of byte =
[ vk_up, vk_down,
vk_left, vk_right,
vk_home, vk_end,
vk_prior, vk_next,
vk_insert, vk_delete];
var
i, ips : Longint;
fb, sb: Byte;
keysdown: String;

procedure keybd (vk, kp : Byte);
begin
if vk in ExtendedKeys then
kp := kp + KEYEVENTF_EXTENDEDKEY;
keybd_event(vk, MapVirtualKey(vk, 0), kp, 0);
end;

begin
keysdown := '';
for i := 1 to Length(keys) div 2 do
begin
fb:= Ord(keys[2*i -1]);
sb:= Ord(keys[2*i]);
if sb = Ord(downkey) then
keysdown := keysdown + Chr(fb)
else
begin
ips := pos(Chr(fb), keysdown);
if ips > 0 then
Delete(keysdown, ips, 1)
else
Continue;
end;
keybd(fb, sb);
end;
{Autocomplete}
for i := 1 to Length(keysdown) do
keybd(Ord(keysdown[i]), Ord(upkey));
end;

end.
--- EOF unit Sndkey.pas ---

Leonid Troyanovsky

Q-95: Как узнать версию Windows?

type
TWinVersion = (wvUnknown,wv95,wv98,wvME,wvNT3,wvNT4,wvW2K,wvXP);

function DetectWinVersion : TWinVersion;
var
OSVersionInfo : TOSVersionInfo;
begin
Result := wvUnknown;
OSVersionInfo.dwOSVersionInfoSize := sizeof(TOSVersionInfo);
if GetVersionEx(OSVersionInfo) then begin
case OSVersionInfo.DwMajorVersion of
3: Result := wvNT3;
4: case OSVersionInfo.DwMinorVersion of
0: if OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT
then Result := wvNT4
else Result := wv95;
10: Result := wv98;
90: Result := wvME;
end;
5: case OSVersionInfo.DwMinorVersion of
0: Result := wvW2K;
1: Result := wvXP;
end;
end;
end;
end;

function DetectWinVersionStr : string;
const
VersStr : array[TWinVersion] of string = (
'Unknown',
'Windows 95',
'Windows 98',
'Windows ME',
'Windows NT 3',
'Windows NT 4',
'Windows 2000',
'Windows XP');
begin
Result := VersStr[DetectWinVersion];
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Ver := DetectWinVersion;
Label1.Caption := IntToStr(Ord(DetectWinVersion));
Label2.Caption := DetectWinVersionStr;
end;

Дополнительную информацию можно посмотреть в fido7.ru.delphi FAQ, тема Q79 - "Как узнать версию Windows?"

Анатолий Подгорецкий

Q-96: Как использовать в эхотаге API фyнкции

AA> как это ни странно, вызывать их. предварительно заюзав модуль windows.

Правильнее : вызвать, предварительно подключив модуль, в котором данная функция описана (это может быть windows, activex, shellapi и т.д.).
Найти модуль поможет клавиша F1 на имени функции.

Если функция не нашлась - то попробовать сделать поиск в папке с исходными текстами Дельфи.

Если функция не нашлась - есть шанс, что в этой версии Дельфи она не описана. В этом случае надо поискать "заголовочный файл" (API header file) в интернете. Огромная коллекция их находится на сайте www.delphi-jedi.org.

Если не помогло и это - придется взять описание функции из документации производителя данного API (обычно оно на С) и самому сделать ее обьявление, так же, как это сделано в windows.pas, только в своем юните.

Сергей Кабиков

Q-97: Автоматическое определения кодировки текста

AG> Существуют ли в сободном для изучения доступе алгоритмы автоматического
AG> определения кодировки текста?
О, еще сколько. Методом таблицы модельных распределений:

type
TCodePage = (cpWin1251, cp866, cpKOI8R);
PMap = ^TMap;
TMap = array [#$80..#$FF] of Char;

function GetMap(CP: TCodePage): PMap;
{ должна возвращать указатель на таблицу перекодировки из CP в Windows1251
(nil для CP = cpWin1251) }
begin
GetMap:=nil;
end;

function DetermineRussian(Buf: PChar; Count: Integer): TCodePage;
const
ModelBigrams: array [0..33, 0..33] of Byte = (
{АБВГДЕЖЗИЙКЛМHОПРСТУФХЦЧШЩЪЫЬЭЮЯ_Ё}
{А}(0,20,44,12,22,23,16,60,4,9,63,93,47,110,0,16,35,61,81,1,5,13,24,17,12,4,0,0,0,0,14,31,205,1),
{Б}(19,0,0,0,4,19,0,0,8,0,2,15,1,4,41,0,15,5,0,15,0,2,1,0,0,6,16,37,0,0,0,4,3,0),
{В}(97,0,1,0,2,57,0,5,40,0,4,25,2,23,78,2,8,28,4,12,0,1,0,0,8,1,0,40,1,0,0,5,106,3),
{Г}(13,0,0,0,9,5,0,0,15,0,1,17,1,2,96,0,24,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,8,0),
{Д}(63,0,9,1,2,71,1,0,35,0,3,16,2,22,50,2,19,9,2,25,0,2,1,0,1,0,1,9,4,0,1,5,17,4),
{Е}(4,14,15,34,56,22,13,14,2,34,39,77,73,150,6,9,101,64,81,1,0,15,5,12,10,6,0,0,0,0,3,4,235,1),
{Ж}(13,0,0,0,12,47,0,0,16,0,1,0,0,23,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,2,2),
{З}(76,2,11,3,11,4,1,0,7,0,2,4,11,24,17,0,6,1,0,8,0,0,0,0,0,0,0,16,6,0,1,4,17,0),
{И}(7,9,32,5,18,60,4,42,31,27,28,46,55,49,12,7,26,60,53,0,5,25,14,28,4,1,0,0,0,0,9,56,255,0),
{Й}(0,0,0,0,2,0,0,0,0,0,1,3,0,3,0,0,0,10,3,0,0,0,0,1,1,0,0,0,0,0,0,0,122,0),
{К}(92,0,3,0,0,7,2,1,39,0,0,27,0,14,110,0,18,5,35,18,0,0,11,0,0,0,0,0,0,0,0,0,5,5,0),
{Л}(85,1,0,2,1,70,6,0,85,0,5,3,0,9,67,1,0,9,0,15,0,0,0,2,0,0,0,9,66,0,15,43,57,4),
{М}(44,0,0,0,0,65,0,0,47,0,1,1,10,15,57,7,0,2,0,24,0,0,0,0,0,0,0,28,0,0,0,8,109,3),
{}(139,0,0,1,11,108,0,4,152,0,7,0,1,69,161,0,0,8,25,24,5,1,5,2,0,1,0,83,10,0,1,29,38,5),
{О}(0,72,139,76,74,32,32,19,12,52,21,93,68,72,7,34,93,102,98,1,2,6,6,19,15,2,0,0,0,1,4,9,252,2),
{П}(17,0,0,0,0,43,0,0,14,0,1,9,0,1,125,3,120,1,2,8,0,0,0,0,0,0,0,3,6,0,0,3,2,2),
{Р}(151,1,6,4,3,103,7,0,76,0,4,0,11,10,117,1,0,5,9,39,2,5,0,1,3,0,0,24,7,0,1,10,22,5),
{С}(24,1,21,0,3,39,0,0,33,0,56,41,11,15,58,30,5,30,183,16,0,4,1,4,1,0,0,8,25,0,1,50,41,2),
{Т}(83,0,43,0,3,87,0,0,71,0,9,3,2,26,180,0,55,33,1,23,1,0,1,4,0,0,0,20,78,0,0,5,82,4),
{У}(3,6,7,14,19,8,13,6,0,1,13,15,10,7,0,12,17,16,19,0,1,3,0,12,5,8,0,0,0,0,22,1,65,0),
{Ф}(4,0,0,0,0,4,0,0,11,0,0,1,0,0,9,0,3,0,0,4,1,0,0,0,0,0,0,0,0,0,0,0,2,0),
{Х}(9,0,2,0,0,2,0,0,5,0,0,1,0,5,26,0,4,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,76,0),
{Ц}(5,0,0,0,0,16,0,0,48,0,1,0,0,0,4,0,0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,3,0),
{Ч}(30,0,0,0,0,52,0,0,23,0,3,1,0,14,1,0,0,0,36,5,0,0,0,0,1,0,0,0,1,0,0,0,2,2),
{Ш}(13,0,0,0,0,28,0,0,17,0,4,4,0,4,3,0,0,0,1,3,0,0,0,0,0,0,0,0,3,0,0,0,1,1),
{Щ}(6,0,0,0,0,23,0,0,16,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1),
{Ъ}(0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0),
{Ы}(0,5,14,1,3,28,0,2,0,22,6,19,21,2,0,5,4,7,10,0,0,37,0,3,4,0,0,0,0,0,0,1,84,0),
{Ь}(0,1,0,0,0,9,0,10,1,0,13,0,2,26,0,0,0,10,3,0,0,0,1,0,6,0,0,0,0,0,6,4,117,0),
{Э}(0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,31,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0),
{Ю}(0,5,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,1,15,0,0,0,1,4,1,15,0,0,0,0,0,0,38,0),
{Я}(0,0,9,2,7,10,3,19,0,0,1,6,7,8,0,0,2,6,19,0,0,3,5,1,0,3,0,0,0,0,5,2,177,0),
{_}(42,80,193,43,109,41,18,53,159,0,144,27,83,176,187,229,70,231,99,47,15,13,6,58,7,0,0,0,0,38,0,22,0,2),
{Ё}(0,0,0,0,3,0,0,0,0,0,2,4,4,8,0,0,5,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0));
{ "рейтинг" буквы Ё условно принимается равным 1/20 от "рейтинга" буквы E,
если сочетание с участием Ё корректно, иначе - 0 }
type
TVariation = array [0..33, 0..33] of Integer;
var
I, J, iC, iPredC, Max: Integer;
C: Char;
CP: TCodePage;
D, MinD, Factor: Double;
AMap: PMap;
PV: ^TVariation;
Vars: array [TCodePage] of TVariation;
begin
DetermineRussian:=cpWin1251; { по yмолчанию }
{ вычисление распределений биграмм }
FillChar(Vars, SizeOf(Vars), 0);
for CP:=Low(Vars) to High(Vars) do begin
AMap:=GetMap(CP);
PV:=@Vars[CP];
iPredC:=32;
for I:=0 to Count - 1 do begin
C:=Buf[I];
iC:=32;
if C >= #128 then begin
if AMap <> nil then C:=AMap^[C];
if not (C in ['Ё', 'ё']) then begin
C:=Chr(Ord(C) and not 32); { 'a'..'я' -> 'А'..'Я' }
if C in ['А'..'Я'] then iC:=Ord(C) - Ord('А');
end
else
iC:=33;
end;
Inc(PV^[iPredC, iC]);
iPredC:=iC;
end;
end;
{ вычисление метрики и определение наиболее правдоподобной кодировки }
MinD:=0;
for CP:=Low(Vars) to High(Vars) do begin
PV:=@Vars[CP];
PV^[32, 32]:=0;
Max:=1;
for I:=0 to 33 do
for J:=0 to 33 do
if PV^[I, J] > Max then Max:=PV^[I, J];
Factor:=255 / Max; { ноpмализация }
D:=0;
for I:=0 to 33 do
for J:=0 to 33 do
D:=D + Abs(PV^[I, J] * Factor - ModelBigrams[I, J]);
if (MinD = 0) or (D < MinD) then begin
MinD:=D;
DetermineRussian:=CP;
end;
end;
end;

begin
{ тест: слово 'Пример' в разных кодировках (веpоятность ошибок на таких
коpотких текстах высока - в данном слyчае пpосто повезло!) }
writeln(DetermineRussian(#$CF#$F0#$E8#$EC#$E5#$F0, 6) = cpWin1251);
writeln(DetermineRussian(#$8F#$E0#$A8#$AC#$A5#$E0, 6) = cp866);
writeln(DetermineRussian(#$F0#$D2#$C9#$CD#$C5#$D2, 6) = cpKOI8R);
readln;
end.





--
Best regards,
Stas Malinovski. mailto:stasm@tsl.ru

Q-98: Как помигать лампочками на клавиатуре?

var
KeyState : TKeyboardState;
begin
GetKeyboardState(KeyState);
KeyState[VK_NUMLOCK] := KeyState[VK_NUMLOCK] xor 1;
SetKeyboardState(KeyState);
end;

Изменяет состояние индикаторов на обратное...
См. также VK_NUMLOCK, VK_CAPITAL

WinNT:
{
keybd_event( VK_SCROLL, 0x46, KEYEVENTF_EXTENDEDKEY | 0, 0 );
keybd_event( VK_SCROLL, 0x46, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}

Stas Malinovski. mailto:stasm@tsl.ru

Q-99: Как создать в runtime форму

with TxxForm.Create(Self) do Show;

with TxxForm.Create(Self) do
try
ShowModal;
finally
Free;
end;

Q-100: Как прочитать порт или записать в него.

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

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

В Win NT доступ к оборудованию со стороны пользовательской программы запрещен полностью. Для доступа на этих ОС требуется использовать kernel mode драйвера, тоже самое рекомендуется и для Win9x.
Вот несколько полезных ссылок:

TVicHW32 http://www.entechtaiwan.com/tools.htm
Tinyport (NT) http://www.winsite.com/info/pc/winnt/programr/tinypo21.zip.drag
DriverX http://www.tetradyne.com
giveio (NT)
http://www.wideman-one.com/gw/tech/Delphi/iopm/index.htm
Ports, by Harold Howe, http://www.bcbdev.com/components.htm

Код доступа к портам с помощью ассемблера.

procedure WritePortByte(Port:Word; Value:Byte);
asm
XCHG EDX,EAX
OUT DX,AL
end;

procedure WritePortWord(Port:Word; Value:Word);
asm
XCHG EDX,EAX
OUT DX,AX
end;

function ReadPortByte(Port:Word) : Byte;
asm
MOV EDX,EAX
IN AL,DX
end;

function ReadPortWord(Port:Word) : Word;
asm
MOV EDX,EAX
IN AX,DX
end;

Примечание:

Существуют устройства с подряд идущими (по адресам) _байтовыми_ портами, к которым нельзя обращаться со словными командами I/O. На сегодня они почти вымерли, но :

При выборе типа процедуры (BYTE или WORD) следует ориентироваться на спецификацию устройства ввода-вывода, к которому идет
обращение. Не следует обращаться к байтовому устройству с WORD-ориентированными процедурами - экономия времени мизерная, а побочные
эффекты могут быть катастрофическими."
Например, некоторые адаптеры сбрасывают биты ошибок после чтения статус-регистра. Другие отображают несколько внутренних регистров на один адрес I/O, и т.п.

На некоторых старых компьютерах Word процедуры могут не работать из за специфических особенностей интерфейса, правда такие компьютера практически уже не встречаются. Есть ISA Bus Specification, где эти вопросы четко формализованы. Выборка словного порта может быть разбита на два раза, даже если адрес четный, в зависимости от пожеланий устройства I/O.

Q-101: Как работать с битами?

Есть два способа.
Низкоуровневый подход обеспечивается логическими операциями :

var
I : integer;
N : integer; // Номер бита в диапазоне от 0..SizeOf(TYPE)*8 - 1

I := I or (1 shl N); // установка бита
I := I and not (1 shl N); // сброс бита
I := I xor (1 shl N); // инверсия бита
if (i and (1 shl N)) <> 0 then... // проверка установленного бита

Высокоуровневый подход опирается на представление числа в виде множества:

type
TIntegerSet = set of 0..SizeOf(Integer)*8 - 1;
var
I : Integer;
N : Integer;

Include(TIntegerSet(I), N); // установили N-ный бит в 1
Exclude(TIntegerSet(I), N); // сбросили N-ный бит в 0
if N in TIntegerSet(I) then... // проверили N-ный бит

I-102: Список рекомендуемой литературы

1. А. Архангельский, В. Ильин, М. Тагин
Русская справка (HELP) по Delphi 5 и Object Pascal (32 стр. с CD-ROM)
Бином, ISBN 5-7989-0168-8

2. А. Архангельский. Программирование в Delphi 5
Бином, ISBN 5-7989-0104-1

3. А. Архангельский. Программирование в Delphi 6
Бином, ISBN 5-7989-0227-7

4. П.Даpахвелидзе, Е.Маpков
Delphi 4 в подлиннике

5. П. Дарахвелидзе, Е. Марков, О. Котенок
Программирование в Delphi 5
BHV-СПб, ISBN 5-8206-0052-5

6) П.В. Шумаков, В.В. Фаронов "Delphi xx. Руководство разработчика баз данных."

7) М.Кэнту
Delphi 4 для пpофессионалов

8. Ч.Калвеpт
Delphi 4, Энциклопедия пользователя

9. Стив Тейксейра, Ксавье Пачеко
Delphi 5. Руководство разработчика. Том 1.
Основные методы и технологии программирования
Вильямс, ISBN 5-8459-0016-6
2000 Вильямс

10. Стив Тейксейра И Ксавье Пачеко
Delphi 5. Руководство разработчика. Том 2.
Разработка компонентов и работа с базами данных
2000 Вильямс

11. Конопка Рей
Создание оригинальных компонент в среде Delphi: Пер. с англ./Рей Конопка.
К.: НИПФ - "ДиаСофт Лтд.", 1996. - 512 с.
ISBN 5-7707-9551-4

12. Лишнер Рэй
Секреты Delphi 2: Пер. с англ./Рэй Лишнер. -
К.: НИПФ - "ДиаСофт Лтд.", 1996. - 800 с.
ISBN 966-7033-10-4

13. Том Сван "Секреты 32-разрядного программирования в Delphi"
Диалектика, Киев, 1997. 480 стр.,
ISBN 966-506-052-X (рус.)

14. Дэн Оузьер "Дельфи 2. Освой самостоятельно."
Восточная Книжная Компания,
1997. 624 стр. Binom.

15. Михаил Кpаснов. DirectX Гpафика в пpоектах Delphi
BHV
ISBN-5-94157-033-3

В списке отсутствует ряд хороших книг, по причине недостаточнысти данных, если у кого есть замечания, исправления или дополнения по данной статье, то просьба посылать их прямо на mailto: faq@nps.vnet.ee

Новые книги можно искать и заказывать через Интернет на сайте http://books.ru
Там же как правило есть аннотация.

Кроме указанных книг существует большое количество ресурсов в Интернете посвященных Дельфи - это статьи, электронные библиотеки и прочее. Один из ресурсов расположен на моем сайте - это несколько проектов электронных библиотека, в совокупности свыше 200 книг. Доступ ко всем проектам прямо с главной страницы http://www.podgoretsky.com, существует так же доступ и по FTP (3 анонимных сессии)

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

Q-103: Как удалить непустой каталог?

procedure TForm1.Button1Click(Sender: TObject);
var
lpFileOp: TSHFileOpStruct;
begin
FillChar(lpFileOp,SizeOf(lpFileOp),0);
lpFileOp.Wnd := Handle;
lpFileOp.wFunc := FO_DELETE;
lpFileOp.pFrom := PChar(Edit1.Text);
lpFileOp.fFlags := FOF_NOCONFIRMATION;
SHFileOperation(lpFileOp);
end;

Ivan Daniloff

Q-104: Как получить список файлов со всеми подкаталогами

procedure ScanDir(StartDir: string; Mask:string; List:TStrings);
var
SearchRec : TSearchRec;
begin
if Mask = '' then Mask := '*.*';
if StartDir[Length(StartDir)] <> '\' then StartDir := StartDir + '\';
if FindFirst(StartDir+Mask, faAnyFile, SearchRec) = 0 then
begin
repeat
Application.ProcessMessages;
if (SearchRec.Attr and faDirectory) <> faDirectory then
List.Add(StartDir + SearchRec.Name)
else if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
List.Add(StartDir + SearchRec.Name + '\');
ScanDir(StartDir + SearchRec.Name + '\',Mask,List);
end;
until FindNext(SearchRec) <> 0;
FindClose(SearchRec);
end;
end;

Пример вызова. параметры
1. имя папки
2. маска, по умолчанию *.*
3. хранилище для резульатат, любой наследник от TString, например TStringList

procedure TForm1.Button1Click(Sender: TObject);
begin
ListBox1.Items.Clear;
ScanDir('c:','',ListBox1.Items);
Label1.Caption := IntToStr(ListBox1.Items.Count);
end;

Анатолий Подгорецкий
anatoly@podgoretsky.com

I-105: Информация о программе

FAQ создан с помощью FAQ Maker ver. 1.1
от Анатолия Подгорецкого

Доступен на http:/www.podgoretsky.com или http://nps.vnet.ee

Альтернативный источник http://faq.delphiplus.org - более быстрый хостинг, FAQ центр, хранятся всевозможные FAQ, не только из иерархии FIDO7.RU.DELPHI.*