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

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

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

FAQ для конференции fido.ru.delphi, основано на FAQ от Алексея Махоткина.
В основном сохраняется вся политика по ведению данного FAQ

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

Copyright (C) Alexey Mahotkin 1997-1999
Portion Copyright (C) Anatoly Podgoretsky, 2001

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

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

I-5: О поле Subject:

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

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

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

* обсуждение вопросов, относящихся к базам данных, для этого существует специализированная конференция RU.DELPHI.DB; вопросов относящихся к отчетам - RU.DELPHI.REPORTS; вопросов относящихся к Интернету - RU.DELPHI.INTERNETж относительно простых вопросов - RU.DELPHI.CHAINIK
Мотивация "мой аплинк/провайдер не получает эту эху/ньюсгруппу" в данном случае не принимается.

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

* обсуждение тем, не связанных с собственно Delphi: алгоритмы, общие вопросы программирования под Win32, общие организационные вопросы, связанные с разработкой программного обеспечения, etc. Для этого существуют специализированные эхоконференции.

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

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

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

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

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

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

Оригинальная версия от Махоткина на домашней странице автора http://alexm.here.ru.

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

I-8: Контрибуторы

Список людей, внесших свой вклад в создание этого FAQ., в алфавитно-случайном порядке:

Akzhan Abdulin (2:5040/55),
Alexey Tomin (alex(at)soniir.smr.ru),
Anthony Buntyakov (antosha(at)metcombank.ru),
Arthur Aseev (2:5030/465.2), Andrey Grigoriev (2:5061/24.20),
Alex Konshin (2:5030/217), Alexander Lokshin (2:5020/529),
Alexander Petrosyan (2:5020/468.8), Alex Petin (2:5000/97.8),
Alexey Solodovnikov (2:5030/257.15),
Andrey Ruckoy (2:5047/7),
Andrey Sarinkov (2:5040/33.121),
Alexey Sinutin (2:5022/12.16),
Andrew Verigo (2:452/23.32),
Alexey Yashin (2:5020/62.31),
Boris Loboda (2:461/256),
Boris Podchezertseff (2:5020/656.20),
Dmitry Kryloff (2:5054/9.20),
Dmitry Shikhman (2:468/13.32),
Edward Shigapov (2:5051/22.8),
Eugene Kopko (2:464/196),
Evgeny Levashoff (2:5022/31.7),
Eugene Mayevski (2:463/209),
Eugeny Sverchkov (2:5031/12.23),
Ilya Andreev (2:5030/55.28),
Ivan Gudym (2:4642/2213.9),
Igor Slusarev (2:5020/118.18),
Juris Bekins (2:5100/35),
Max Vystropov (2:5020/1412),
Oleg Belousov (oberon(at)nvart.ru),
Pavel Shklovsky (2:5011/18),
Roman Procopovich (2:5030/254.201),
Roman Rechmakov (2:5020/952.26),
Stanislav Babin (2:5030/356.7),
Serge Korolev (2:5020/104),
Sergey Mazunov (2:5083/30.20),
Sergey Maznichenko (2:5061/26.45),
Sergey Okhapkin (ex-2:5020/47),
Serg Vostrikov (2:5053/15.3),
Sergey Arkhipov (2:5054/88.10),
Sergey Belov (sbelov(at)aha.ru),
Victor Babkin (2:463/279.6),
Vlad Sharnin (vlad(at)nplks.rb.ru),
Victor Ishikeev (ivi(at)ufanet.ru),
Vladimir Vornichescu (2:469/101.24), vsbelashov(at)obs.omsk.ru.

Если вас незаслуженно обошли в этом списке, прошу извинить и уведомить об этом прискорбном факте.

Я также позволил себе не сопоставлять некоторые ответы с именами авторов этих ответов. Если вас не устраивает такая ситуация -- напишите об этом.

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

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

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

Список литературы на все интересующие темы, рекомендованный к прочтению, находится в неофициальном 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.
Большинство вопросов типа "А как сделать..." могут быть легко решены после
прочтения соответствующей главы в MSDN. Вы сэкономите массу своего и чужого времени.

Множество качественной информации, относящейся к программированию под Windows 95/NT, можно получить на http://www.sysinternals.com. Hа http://www.iarchitect.com находится большой ресурс, посвященный вопросам построения пользовательского интерфейса.

Если вам требуется работать с нестандартным железом, подумайте о написании драйвера. Это удобнее, проще и гибче. Соответствующая информация находится в DDK (Device Driver Development Kit). Самая известная фирма, занимающаяся поддержкой писателей драйверов -- Vireo. http://www.vireo.com. (Вроде бы проект также уже не доступен).
Отдельно стоит упомянуть, что если вы всего лишь желаете работать с последовательными портами, то вам следует приобрести библиотеку Async Professional фирмы Turbo Power.
Hа http://www.entechtaiwan.com/tools.htm лежат TVicHW32 и TVicPort. Hа http://www.bluewatersystems.com есть WinRT, а у все той же Vireo Software: Driver::Agent. Это все попытки избавить пользователя от написания драйверов.

Традиционно обитатели 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

Очень полезным ресурсом является Delphi Bug List, лежащий по адресу http://www.dataweb.net/~r.p.sterkenburg. Это список ошибок во всех известных версиях Delphi, адекватно обновляемый.

В FIDO вы можете подписаться на дружественные эхи, такие как:

RU.CBUILDER - Borland C++Builder;
SU.WINDOWS.PROG - общие вопросы программирования под MS Windows;
SU.WIN32.PROG - вопросы программирования для Win32 API;
SU.WIN95.PROG - вопросы программирования под MS Windows 95;
SU.DBMS - базы данных;
SU.DBMS.SQL - SQL-базы данных;
SU.DBMS.BORLAND - базы данных фирмы Borland;
SU.DBMS.INTERBASE - "родная" для Delphi база данных;
SU.SOFTW - общие вопросы разработки программ;
RU.ALGORITHMS - вещи, не зависящие от фамилии президента IBM и текущего номера сервиспака к NT;
SU.FLAME - обсуждение превосходства Borland Delphi над всеми прочими средствами разработки.

Q-10: Каким именно релизом 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-11: Как исправить проблемы с вызовом помощи при одновременно стоящих Delphi 1 и Delphi 2

(AP): Решаются так...

В regedit убейте из секции HKLM\SOFTWARE\Microsoft\Windows\Help все, что равно "...\help".

Изменив соответствующие пути, импортируйте в реестр следующий файлик:

REGEDIT4

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppPaths\delphi32.exe]
@="C:\\DELPHI2\\BIN\\delphi32.exe" "Path"="C:\\DELPHI2\\HELP"

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

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

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

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

Q-13: Как включить окошко CPU Window?

Вставьте в реестр строковый ключ

HKCU\Software\Borland\Delphi\2.0\Debugging\
EnableCPU=1

Соответственно, для Delphi 3 -- Delphi\3.0.

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

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

Q-15: При возникновении ошибки во время отладки программы машина перезагружается. Что делать?

Снести QEMM. Hачисто. Простое отключение его функций не помогает. Впрочем, это исправлено в QEMM 9.0.

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

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

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

[Display]
"BusThrottle"="On"

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

Q-17: При работе программ на D1 под Win95 на иконках TBitBtn'ов обнаруживаются странные артефакты

При работе программ на Delphi 1 под Windows 95 в hicolor-режимах на иконках TBitBtn'ов обнаруживаются странные коричневые артефакты. Как от них избавиться?

(AB): Залить фон битмапа синим цветом.

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

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

Q-19: Куда из Delphi 3 делся модуль для работы с ReportSmith? А мои любимые модули работы с OLE

Они лежат в X:\DELPHI3\LIB\DELPHI2.

Q-20: Hе работает передача данных по OLE в русский Excel.

(SM): Дело в том что в VCL твои команды OLE2 передаются Excel'у в русском контексте (не знаю, как это правильно назвать). Для исправления необходимо найти в файле OLEAUTO.pas в функции GetIDsOfNames строчку

if Dispatch.GetIDsOfNames(GUID_NULL, @NameRefs, NameCount, LOCALE_SYSTEM_DEFAULT, DispIDs) <> 0 then

и заменить ее на

if Dispatch.GetIDsOfNames(GUID_NULL, @NameRefs, NameCount, ((LANG_ENGLISH+SUBLANG_DEFAULT*1024)+SORT_DEFAULT* 65536 ), DispIDs) <> 0 then

После этого у меня Excel стал понимать нормальные английские команды :)). Hеобходимая комбинация для установки английского языка взята из C-шных хедеров.

Q-21: Как русифицировать сообщения программы?

Ответ зависит от версии Delphi.

Ежели кому интересно то на http://members.xoom.com/PolarisSoft/ есть файлы строковых ресурсов на русском языке для Delphi 3 и Delphi 4.

Q-22: Как во время компиляции модуля определить, под какой версией Delphi она происходит?

Используйте

{$IFDEF VERXXX}
. . .
{$ELSE}
. . .
{$ENDIF}

Пользуйтесь вот такой таблицей:

* VER80 -- Delphi 1
* VER90 -- Delphi 2
* VER93 -- C++Builder 1
* VER100 -- Delphi 3
* VER110 -- C++Builder 3
* VER120 -- Delphi 4
* VER130 -- Delphi 5
* VER140 -- Delphi 6


(Sergey Anvarov, 2:5012/27.204)

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

Воспользуйтесь функцией ActivatePrevInstance из библиотеки rxLib. Для завершения второго экземпляра используйте Application.Terminate.

(AS): Другой вариант: X:\DELPHI2\DEMOS\IPCDEMOS\ipcthrd.pas, функция IsMonitorRunning().

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

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

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

Q-25: А как поместить свою иконку на taskbar, там где часы и переключатель клавиатуры?

(Этот вопрос получил первый приз).

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

Q-26: Как сделать плавно изменяющийся цвет заголовка окна, как в MSOffice'95?

В rxLib есть TGradientCaption.

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

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

1. if S <> '' CharToOem(PChar(S),PChar(S));
2. CharToOem(Pointer(S),Pointer(S));

см. также Q-74

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

В rxLib есть TrxFolderMonitor.

(Win16) FileCDR, но она плохо документирована.

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

(DS): SelectDirectory, rxLib: TDirectoryEdit.

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

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

Application.ProcessMessages.

(AA): Если вы хотите отдавать timeslices в нитях, пользуйтесь Sleep(0); это отдаст остаток слайса системе.

(Win16) Если вы хотите разрешить отработку сообщений другим программам, но не вашей, то лучше пользоваться Yield().

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

Как мне запустить какую-нибудь программу? А как подождать, пока эта программа не отработает? Как выяснить, работает ли программа или уже завершилась? Как принудительно закрыть выполняющуюся программу?

WinExec() или ShellExecute. У второй больше возможностей.

(SO): CreateProcess() в параметре process info возвращает handle запущенного процесса. Вот и делаешь WaitForSingleObject(pi.hProcess, INFINITE);

(AA): (Win16) Delay можно взять из rxLib.

handle := WinExec(...);
if handle >= 32 then
while GetModuleUsage(handle) > 0 do
Delay( nn );
else
raise ....

(AM): Чтобы выяснить, работает ли программа, используйте GetProcessTimes(), параметр lpExitTime.

(Win32) Для принудительного завершения процесса -- TerminateProcess.

(Win16) (RR): Hадо послать программе сообщение WM_QUIT:

Handle := Winexec(App, 0);
PostMessage(Handle, WM_QUIT, 0, 0);

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

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

uses ShellApi;

{ ... }

ShellExecute("http://www.company.com", ... );
ShellExecute("mailto:author@somewhere.net", ...);

Q-33: Как правильно закрыть и удалить форму?

Как правильно закрыть и удалить форму? Почему моя MDI Child форма при закрывании просто минимизируется?

Обрабатывайте событие OnClose для формы и выставляйте в нем параметр Action в caFree. Дело в том, что его значение по умолчанию для MDI Child форм caMinimize. Кстати, если сделать Action := caNone, то форму нельзя будет закрыть.

Q-34: Мне надо добавить много строк в TListbox или в TCombobox или в TMemo

Мне надо добавить много строк в TListbox или в TCombobox или в TMemo или в TRichEdit, при этом сам объект постоянно мигает, перерисовываясь. Как избавиться от этого?

BeginUpdate/EndUpdate.

Q-35: Как мне запрограммировать непрямоугольную форму, например, как у Norton CrashGuard, в форме щита?

SetWindowRgn() (Win32).

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

{$R CURSORS.RES}

const
crZoomIn = 1;
crZoomOut = 2;

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

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

Q-37: Как ограничить перемещение курсора мыши какой-либо областью экрана?

ClipCursor(). Учтите, что использование этой функции -- плохой тон.

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

ActivateKeyboardLayout(). Учтите, что использование этой функции -- плохой тон.

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

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

Q-40: Как получить короткий путь файла если имеется длинный?

GetShortPathName()

Q-41: Как написать сервис для Windows NT?

В поставке Delphi 4 есть пример. http://www.sawatzki.de.

Q-42: Как работать с реестром?

uses TRegistry

Begin
with TRegistry.Create;
try
OpenKey('\Sotware\FirmName\ProgName\Version',True);
WriteInteger('Count',Count);
finally
Free
end;
end;

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

procedure EjectCDROM(aLetter : char);
const
AliasName = 'MyCoolCdrom';
var s : string;
begin
s := 'open ' + aLetter + ': type cdaudio alias ' + AliasName + aLetter + ' shareable wait';
if mciSendString(PChar(s), nil, 0, 0) <> 0 then exit; // fails to open
try
s := 'set ' + AliasName + aLetter + ' door open wait';
mciSendString(PChar(s), nil, 0, 0);
finally
s := 'close ' + AliasName + aLetter + ' wait';
mciSendString(PChar(s), nil, 0, 0);
end;
end;

Q-44: Как перехватывать клавиши, нажатые в окне другой программы? И вообще, любые события

SetWindowsHookEx().

Q-45: Как вызывать из 32-битной программы 16-битные DLL?

Hадо применять так называемые "thunks". Смотри статью на http://www.itecuk.com/delmag/thunk95.htm.

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

RTFM packed, $A.

Q-47: Где взять подробную документацию по работе с RTF, TRichEdit?

В MSDN.

В rxLib 2.60 появился компонент TrxRichEdit, полностью поддерживающий MS RichEdit 2.0 и его DB-aware версия. Рекомендуется.

Q-48: Как можно перетаскивать форму не только за заголовок?

WM_NCHITTEST.

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

Обрабатывать CM_MOUSEENTER/CM_MOUSELEAVE.

Q-50: Как добавить пункты в системное меню окна?

Получить хэндл системного меню окна можно с помощью функции GetSystemMenu().

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

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

В файл MyWave.rc пишешь:

MyWave RCDATA LOADONCALL MyWave.wav

brcc32.exe MyWave.rc, получаешь MyWave.res.

В своей программе пишешь:

{$R MyWave.res}

Все!

Предупреждая следующий твой вопрос "а как прочитать wave-файл из исполняемого файла?"

procedure RetrieveMyWave;
var
hResource: THandle;
pData: Pointer;
begin
hResource:=LoadResource( hInstance, FindResource(hInstance, 'MyWave', RT_RCDA
TA));
try
pData := LockResource(hResource);
if pData = nil then
raise Exception.Create('Cannot read MyWave');
// Здесь pData указывает на MyWave
// Теперь можно, например, проиграть его (Win32):
PlaySound(pData, 0, SND_MEMORY);
finally
FreeResource(hResource);
end;
end;

+++++++++++++++++++++++++++++++++

PlaySound('RESNAME', 0, SND_MEMORY or SND_RESOURCE);

Anatoly Podgoretsky


Q-52: Как узнать и поменять разрешение экрана?

Поменять:

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_PELSWIDTH or DM_PELSHEIGHT;
ChangeDisplaySettings(dm, 0);
end;

Узнать можно также с помощью объекта Screen

Screen.Width
Screen.Height

Q-53: Как во время выполнения программы создать так называемый "array of const"

В библиотеке Technical Information на сайте Inprise есть документ за нумером TI582D.txt, посвященный этой проблеме. Вкратце, в качестве array of const можно использовать массив типа TVarRec.

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

Как обратиться к определенному адресу физической памяти? А как прочитать значение из порта? Где мой любимый массив Port[]?

Прочитайте какую-нибудь книжку про программирование под Win32. Вкратце -- забудьте про все эти глупости.

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

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

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

У этой процедуры должен быть еще один дополнительный параметр.
В метод класса кpоме паpаметpов, обьявленных в заголовке, пеpедаётся ещё паpаметp Self

procedure MyRegularProc(ASelf, Sender: TObject);
begin
ShowMessage(ASelf.ClassName + ' ' + Sender.ClassName);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
amethod: TMethod;
begin
amethod.Code := @MyRegularProc;
amethod.Data := Self;
Button1.OnClick := TNotifyEvent(amethod);
end;

Leonid Troyanovsky

Q-57: Библиотеки, инструменты и т. п.

Отдельный F.A.Q. по библиотекам и инструментам третьих фирм ведется Михаилом Чернышевым и регулярно публикуется им в RU.DELPHI, а также находится на http://delphi.da.ru.

Q-58: Как работать с графическими форматами, хотя бы самыми известными?

Hа [32]http://www.imagelib.com лежит библиотека ImageLib.

Hа компакте с Delphi 3 в каталоге EXTRAS есть библиотека JPEG. Если сказать в модуле uses jpeg; то можно работать с .jpg как с TPicture.

Еще есть freeware-библиотека Nishita ViewLib. JPG, JFIF, GIF, BMP, DIB, RLE, TGA, PCX. http://einstein.ae.eng.ua.edu/nishita/index.htm.

Q-59: Как работать с файлами архивов, хотя бы самыми распространенными?

Воспользуйтесь библиотекой ExceedZip 3.0 (http://www.exceedsoft.com).

Q-60: Как использовать DirectX в своей программе?

Модули для работы с DirectX находятся на Delphi Super Page, в пакете DelphiX. Также на http://www.geocities.com/SiliconValley/1142/ лежит модули для работы с DirectSound. Информацию по программированию DirectX можно взять на MSDN и в книге Чарльза Калверта "Delphi 2: Энциклопедия пользователя".

-------------------------------------------------------
PA> Самая прелесть, и забыта:
PA> http://www.yks.ne.jp/~hori/index-e.html - DelphiX by Hiroyuki Hori
PA> - лучший набор инструментов для работы с DirectX

Учтите существование эхи RU.DIRECTX.

Pavel Anufrikov
------------------------------------------------------

AP: Обидно за Хироюки, вроде как первый был.

Q-61: Как использовать OpenGL в своей программе?

Модули для работы с OpenGL можно взять на
http://www.signsoft.com/opengl. Информацию -- на http://www.opengl.org.
Также есть книга Ю. Тихомирова "OpenGL: программирование трехмерной графики".
Еще загляните на http://reality.sgi.com/mjk за примерами и http://www.scitechsoft.com за библиотекой MesaGL.

Учтите существование эхи RU.OPENGL.

Q-62: Как встроить просмотр HTML в свою программу?

В Delphi 4+ имеется пример Web-браузера на Delphi.

MS Internet Explorer умеет быть элементом управления ActiveX, что позволяет поместить его на форму.

Netscape Navigator умеет делать то же самое, подробности на http://www.chami.com/tips/delphi/103096D.html

Еще на http://www.pbear.com лежат THTMLViewer и TFrameViewer.

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

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

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

CVS. http://www.cyclic.com. С его помощью разрабатывается весьма львиная доля программного обеспечения в Internet. Интеграция с Delphi -- нулевая ;) Крайне рекомендуется. Я лично пользуюсь ею ощутимое время и не представляю себе более разработки без этого средства. "Введение в CVS" можно прочитать на http://alexm.here.ru.

Microsoft Visual Source Safe. Проигрывает в функциональности, может выигрывать в "привычности".

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

MSDebug Макса Русова. Hаходится на http://www.dic.ru/users/rusov/. Поддерживает Delphi 3 и выше, ловит только утечки памяти, но делает это хорошо.

Hа http://www.numega.com можно купить BoundsChecker for Delphi. Он проверяет также и утечки ресурсов.

Рекламировался также "MemProof", информацию о котором можно получить на http://www.listsoft.ru/programs/pr1520.htm.

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

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

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

Q-67: Как уменьшить размер исполняемого файла программы?

Писать на WinAPI без использования VCL. Это пригодно для и без того крохотных программ.
Существуют freeware библиотеки, упрощающие программирование без VCL, например:

KOL http://xcl.cjb.net
ACL http://a-press.parad.ru/pc/bokovikov/delphi

Воспользоваться пакетами (packages) из Delphi 3. Эффект появится, когда исполняемых файлов больше одного.

Воспользоваться компрессорами исполняемых файлов, например:
Shrinker http://www.blinkinc.com,
WWPack32 http://kolos.uni.lodz.pl/warezak,
NeoLite ftp://ftp.zdnet.com/pub/private/sWlIB/utilities/other_utilities/neolitee.zip,
Petite, http://www.icl.ndirect.co.uk/petite/.

Компрессировать или нет исполняемые файлы, должен решить каждый, так как возможны и негативные моменты от использования сжатия. Дискуссия по этому поводу никогда не прекращается.

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

http://www.iconbazaar.com

Q-69: Как сделать ping из своей программы?

И вообще, посоветуйте какую-нибудь альтернативу стандартным дельфовым Internet-компонентам.

Зайди на [53]http://www.rtfm.be/fpiette. Там кyча компонентов для инета с исходниками. Там и ping есть.

Q-70: Как правильно создавать компоненты в 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-71: Как мне работать с файлами MS Word или таблицами MS Excel?

Воспользоваться функцией CreateOLEObject и работать с VBA (Visual Basic for Applications) или WordBasic.

NB: Обратите внимание на то, как устанавливаются именованные параметры у процедур WordBasic'а, например, FileOpen(Name := 'myname.doc');

Пример проверен только на русском Word 7.0! Может, поможет...

unit InWord;
interface
uses
... ComCtrls; // Delphi3
... OLEAuto; // Delphi2
[skip]
procedure TPrintForm.MPrintClick(Sender: TObject);
var W: Variant;
S: String;
begin
S:=VarToStr(Table1['Num']); //В D3 без промежуточной записи
// в var у меня не пошло :(
try // А вдруг где ошибка :)
W:=CreateOleObject('Word.Basic');
// Создаем документ по шаблону MyWordDot
// с указанием пути если он не в папке шаблонов Word
W.FileNew(Template:='C:\MyPath\DB\MyWordDot',NewTemplate:=0);
// Отключение фоновой печати (на LJ5L без этого был пустой лист)
W.ToolsOptionsPrint(Background:=0);

// Переходим к закладке Word'a 'Num'
W.EditGoto('Num'); W.Insert(S);
//Сохранение
W.FileSaveAs('C:\MayPath\Reports\MyReport')
W.FilePrint(NumCopies:='2'); // Печать 2-х копий
finally
W.ToolsOptionsPrint(Background:=1);
W:=UnAssigned;
end;
end;
{.....}

Sergey Arkhipov 2:5054/88.10

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

Второй путь, более правильный.

Нужно импортировать TLB библиотеку соответствующего COM-сервера (MS Word, MS Excel, AutoCAD, и т.п.) или воспользоваться готовыми компонентами из палитры Servers поставляемыми с Delphi 5 и

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

Пример использования TLB.

program wordemo;

{$APPTYPE CONSOLE}

uses
SysUtils, ActiveX, Word2000, OleCtrls, Variants;
var
W:TWordApplication;
D:_Document;
P:Paragraph;
FileName:OleVariant;
begin
CoInitialize(NIL);
try
// создадим экземпляр объекта-обертки вокруг Word 2000
W:=TWordApplication.Create(NIL);
try
// создадим новый документ на основе шаблона Normal

D:=W.Application.Documents.Add(EmptyParam,EmptyParam,EmptyParam,EmptyParam);
// добавим новый параграф
P:=D.Paragraphs.Add(EmptyParam);
// Запишем туда какой-нибудь текст
P.Range.InsertAfter('Hello Word :-)');
// сохраним документ
FileName:='wordemo.doc';

D.SaveAs(FileName,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,
EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam);
finally
// завершим работу Word
W.Free;
end;
finally
CoUnInitialize;
end;
end.

Andrew V. Fionik

Замечание от Denver The Marion
Нашёл такую интересную закономерность директива W.Free не закрывает MS Word - он остаётся в памяти и висит там (при этом нормально не открывается только что созданные документы). Если изменить строку на W.Quit - всё работает нормально. Рабиралось всё это дело на Delphi 5 и MS Word 2000.

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

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

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

(EM, DS):

type
TForm1 = class(TForm)
Label1: TLabel;
RxTrayIcon1: TRxTrayIcon;
procedure FormCreate(Sender : TObject);
procedure RxTrayIcon1DblClick(Sender: TObject);
private
{ Private declarations }
procedure ApplicationMinimize(Sender : TObject);
procedure ApplicationRestore(Sender : TObject);
public
{ Public declarations }
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_HIDE);
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-73: Delphi 5.0 and Win2K

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

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

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

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

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

Vladimir Kladov
-----------------------------------

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

Ruslan Fedoseev

Q-74: Почему в консольных приложениях неправильно отображаются русские буквы?

Потому что кодировка шрифтов, используемых в редакторе Delphi - 1251 (ANSI), а в консольных приложениях - 866 (OEM). Чтобы добиться правильного отображения нужно использовать функцию CharToOEM (но при этом возрастёт размер кода), либо сразу писать проект в каком-либо консольном текстовом редакторе (Dos Navigator, Far)

CharToOem('Привет',TmpStr);
Writeln(TmpStr);

Denis Filonov

Q-75: В чем pазличия ShellExecute и CreateProcess?

ShellExecute может запустить приложение, ассоциированное с расширением файла, например:

ShellExecute(Handle, 'open', 'mydoc.doc', nil, nil, SW_SHOW);

запустит Word (или другое приложение, зарегистрованное для *.doc) и откроет файл mydoc.

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

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

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

procedure QryName(threadID: DWord; Caller: HWND); external 'lib0.dll';

procedure TForm1.WMCopydata(var msg: TMessage); // message WM_COPYDATA;
begin
Caption := PChar(PCopyDataStruct(Pointer(msg.LParam)).lpData);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
ahwnd: THandle;
begin
{Ищем по заголовку}
ahwnd := FindWindow(nil, PChar(Edit1.Text));
if ahwnd <> 0 then
QryName(GetWindowThreadProcessID(ahwnd, nil), Handle);
end;

--- lib0.dpr ---

library lib0;

uses
Messages,
Windows;

function Answer( nCode: Integer; wprm: WParam; lprm: LParam): LResult; stdcall;
type
PMsg = ^TMsg;
var
buffer : array [0..MAX_PATH] of Char;
cd : TCopyDataStruct;
msg : PMsg;
Caller : HWND;
AHook: HHook;
begin
Result := 0;
msg := PMsg(lprm);
if (msg.Message = 0) and (msg.LParam <> 0) then
begin
AHook := msg.lParam;
Caller := msg.wParam;
cd.cbData := GetModuleFileName(0, buffer, SizeOf(buffer))+1;
cd.lpData := @buffer;
cd.dwData := GetCurrentThreadID;
SendMessage(Caller, WM_COPYDATA, 0, LParam(@cd));
UnHookWindowsHookEx(AHook);
PostThreadMessage(GetCurrentThreadID, 0, 0, 0);
end;
end;

procedure QryName(tid: DWord; Caller: HWND);
var
AHook : Hhook;
begin
AHook := SetWindowsHookEx(WH_GETMESSAGE, Answer, Hinstance, tid);
if AHook <> 0 then
PostThreadMessage(tid, 0, Caller, AHook);
end;

exports
QryName;

begin
end.

Q-77: Как центрировать по форме модальный диалог?

procedure CenterDialogPos(DlgHandle, WindowHandle: HWND);
var
DlgRect : TRect;
WndRect : TRect;
x, y, w, h : integer;
begin
if (DlgHandle <> 0) then begin
GetWindowRect(DlgHandle, DlgRect);
GetWindowRect(WindowHandle, WndRect);
w := DlgRect.Right - DlgRect.Left;
h := DlgRect.Bottom - DlgRect.Top;
//center horz
x := WndRect.Left + ((WndRect.Right - WndRect.Left - w) div 2);
//keep on screen
if x < 0 then x := 0
else if x + w > Screen.Width then x := Screen.Width - w;
//center vert
y := WndRect.Top + ((WndRect.Bottom - WndRect.Top - h) div 2);
//keep on screen
if y < 0 then y := 0
else if y + h > Screen.Height then y := Screen.Height - h;
SetWindowPos(DlgHandle, 0, x, y, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
end;
end;

procedure TForm1.WMUser1(var msg: TMessage); // message WM_USER+1;
begin
CenterDialogPos(GetActiveWindow, Handle);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
PostMessage(Handle, WM_USER+1, 0, 0);
ShowMessage('Test');
end;

Q-78: Как издать звук через PC Speaker?

Procedure Sound(Duration: Integer; Freq: Word);
var
Ver: TOsVersionInfo;
begin
Ver.dwOSVersionInfoSize := SizeOf(Ver);
GetVersionEx(Ver);
if ver.dwPlatformId = VER_PLATFORM_WIN32_NT then
Windows.Beep(Duration, Freq)
else begin
asm
mov al,0b6H
out 43H,al
mov ax,Freq
out 42h,al
ror ax,8
out 42h,al
in al,61H
or al,03H
out 61H,al
end;
sleep(Duration);
asm
in al,61H
and al,0fcH
out 61H,al
end;
end;
end;

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

Использовать функцию API GetVersionEx

function GetVersionEx(var lpVersionInformation: TOSVersionInfo): BOOL; stdcall;

Аргумент функции – структура TOSVersionInfo, содержит
DwVersionInfoSize:DWORD – заполняется как sizeof TOSVersionInfo) перед вызовом функции

DwMajorVersion:DWORD – старшая цифра версии Windows
Windows 95 - 4
Windows 98 - 4
Windows Me - 4
Windows NT 3.51 - 3
Windows NT 4.0 - 4
Windows 2000 - 5
Windows XP - 5

DwMinorVersion: DWORD – младшая цифра версии
Windows 95 - 0
Windows 98 - 10
Windows Me - 90
Windows NT 3.51 - 51
Windows NT 4.0 - 0
Windows 2000 - 0
Windows XP - 1

DwBuildNumber: DWORD
Win NT 4 – номер билда
Win 9x – старший байт – старшая и младшая цифры версии / младший – номер билда

dwPlatformId: DWORD
VER_PLATFORM_WIN32s Win32s on Windows 3.1.
VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 9x
VER_PLATFORM_WIN32_NT Win32 on Windows NT, 2000

SzCSDVersion:DWORD
NT – содержит PСhar с инфо о установленном ServicePack
9x – доп. инфо, может и не быть

Alexander Kramarenko

Q-80: Как из dll узнать узнать полный путь к этой dll.

function GetModuleFileNameStr(Instance: THandle): String;
var
buffer : array [0..MAX_PATH] of Char;
begin
GetModuleFileName( Instance, buffer, MAX_PATH);
Result := buffer;
end;

GetModuleFileNameStr(Hinstance); // dll name
GetModuleFileNameStr(0); // exe name

Leonid Troyanovsky

Q-81: Как узнать кол-во цветов цветовой палитры?

function GetColorsCount : DWord;
var
DC : HDC;
begin
DC := GetDC( 0 );
Win32Check(DC <> 0);
Result :=1 shl (GetDeviceCaps(DC, PLANES) *
GetDeviceCaps(DC, BITSPIXEL));
ReleaseDC( 0, DC );
end;

Leonid Troyanovsky

Q-82: Как заставить мигать кнопку приложения на AppBar?

procedure TForm1.Timer1Timer(Sender: TObject);
begin
FlashWindow(Application.Handle, True);
end;

Leonid Troyanovsky

Q-83: Как убрать VerticalScrollBar из TListBox навсегда?

procedure TListBoxForEver.CreateParams (var Params:
TCreateParams); //override
begin
inherited CreateParams(Params);
Params.Style := Params.Style and not WS_VSCROLL;
end;

Leonid Troyanovsky

Q-84: Как убрать из ListView горизонтальный скролбар навсегда?

type
TNoHScrollListview = Class( TListview )
private
Procedure WMNCCalcSize( Var msg: TMessage ); message WM_NCCALCSIZE;
end;

procedure TNoHScrollListview.WMNCCalcSize(var msg: TMessage);
var
style: Integer;
begin
style := getWindowLong( handle, GWL_STYLE );
If (style and WS_HSCROLL) <> 0 Then
SetWindowLong( handle, GWL_STYLE, style and not WS_HSCROLL );
inherited;
end;

by Peter Below

Q-85: Как обнаружить активность юзера?

Application.OnMessage := DoMessageEvent;

procedure TForm1.DoMessageEvent ( var Msg: TMsg;
var Handled: Boolean);
begin
case Msg.message of
WM_KEYFIRST..WM_KEYLAST,
WM_MOUSEFIRST..WM_MOUSELAST:
{Произошли события клавиатуры и мыши};
..
end;
end;

Leonid Troyanovsky

Q-86: Как передать строку другому приложению?

получатель:

procedure ReceiveMessage (var Msg: TMessage); message WM_COPYDATA;
..
procedure TFormReceive.ReceiveMessage;
var
pcd : PCopyDataStruct;
begin
pcd := PCopyDataStruct(Msg.LParam);
Caption := PChar(pcd.lpData);
end;

отправитель:

procedure TFormXXX.Button1Click(Sender: TObject);
var
cd : TCopyDataStruct;
begin
cd.cbData := Length(Edit1.Text)+1;
cd.lpData := PChar(Edit1.Text);
SendMessage ( FindWindow('TFormReceive', nil),
WM_COPYDATA,
0,
LParam(@cd));
end;

Leonid Troyanovsky

Q-87: Удаление файлов из временного каталога, безопасно ли?

При получении имени папки предназначенной для хранения временных файлов могут возникнуть ytrjnhst проблемы.

>> Прекрасно это выглядит, когда в качестве каталога временных файлов назначен например C:\Windows

>:-) Я и говорю что небезопасно.

Особенно пикантно это выглядит, в свете того, что

Remarks
Windows 95/98/Me: The GetTempPath function gets the temporary file
path as follows:

The path specified by the TMP environment variable. The path specified by the TEMP environment variable, if TMP is not defined or if TMP specifies a directory that does not exist. The current directory, if both TMP and TEMP are not defined or specify nonexistent directories.

Этак переименовываешь C:\TEMP - и программа чистит текущий каталог :-)

Windows NT/2000 or later: The GetTempPath function does not verify that the directory specified by the TMP or TEMP environment variables exists. The function gets the temporary file path as follows:

The path specified by the TMP environment variable. The path specified by the TEMP environment variable, if TMP is not defined. The Windows directory, if both TMP and TEMP are not defined.

Этак удаляешь переменные окружения - и программа "деинсталлирует" Windows

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

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

Тенцер А.Л.
Andrew V. Fionik
Anatoly Podgoretsky

Q-88: Как сохранить всю форму в файл (как Delphi в *.dfm)?

constructor TForm1.Create(AOwner: TComponent); // override;
var
fname: String;
begin
{ Для динамически создаваемых контролов, может требоваться
RegisterClasses(..); }
fname := FormFilename;
if FileExists( fname ) then
begin
CreateNew(AOwner);
ReadComponentResFile(fname, Self);
end
else
inherited Create( AOwner );
end;

procedure TForm1.FormCloseQuery( Sender: TObject;
var CanClose: Boolean);
begin
WriteComponentResFile(FormFileName, Self);
end;

{Peter Below, Vladimir Titov}

Q-89: Как отследить переход фокуса в приложении?

procedure TForm1.AppControlChange(Sender: TObject);
begin
if Sender is TScreen then
Caption := TScreen(Sender).ActiveForm.ActiveControl.Name;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Screen.OnActiveControlChange := AppControlChange;
end;

Leonid Troyanovsky

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

const
cm_mycommand = $00A0;

procedure TForm1.FormCreate(Sender: TObject);
var HSysMenu: HMENU;
begin
HSysMenu:=GetSystemMenu(Handle,FALSE);
InsertMenu( HSysMenu, 0, MF_BYPOSITION or MF_STRING,
cm_mycommand, 'MyString');
end;

procedure TForm1.WMSysCommand (var Message:
TWMSysCommand); // message WM_SYSCOMMAND;
begin
case Message.CmdType of
cm_mycommand: ShowMessage('My Command');
else
inherited;
end;
end;

Leonid Troyanovsky

Q-91: Какое сообщение надо отлавливать в Application.OnMessage для отслеживания клавиши Alt (vk_menu)

WM_SYSKEYDOWN/WM_SYSKEYUP

Q-92: Как поменять иконку и стpокy в заголовке консольного окна?

procedure TForm1.Button1Click(Sender: TObject);
var
h : HWND;
AIcon : TIcon;
begin
AllocConsole;
SetConsoleTitle(PChar('Console Title'));
Sleep(0);
h := FindWindow(nil, PChar('Console Title'));
AIcon := TIcon.Create;
ImageList1.GetIcon(0, AIcon);
SendMessage(h, WM_SETICON, 1, AIcon.Handle);
AIcon.Free;
end;

Leonid Troyanovsky

Q-93: Как избежать повторного запуска моего приложения?

=== Вариант с поиск по классу окна ===
constructor TYourMainForm.Create(AOwner: TComponent); // override;
var
wndclass : String;
PrevInstance : HWnd;
begin
wndclass := ClassName;
PrevInstance := FindWindow(PChar(wndclass), nil);
if PrevInstance <> 0 then
begin
ShowMessage(Format('Main form %s is already exist', [wndclass]));
Application.Terminate;
end
else
inherited Create(AOwner);
end;

Такое окно существует и в IDE (запускать придется из Explorer).

Leonid Troyanovsky

=== Вариант с Мьютексом ===
В файле проекта (.dpr) прямо можешь написать нечто вроде:
uses windows,...
var
H: THandle;
begin
H := CreateMutex(nil, True, 'уникальное_имя_для_твоей_проги');
if GetLastError = ERROR_ALREADY_EXISTS then
begin
H := FindWindow(nil, 'название заголовка окна программы');
SetForegroundWindow(H);
Exit;
end;
Application.Initialize;
Application.Title := 'название заголовка окна программы';
Application.CreateForm(TAppData, AppData);
Application.CreateForm(TMain, Main);
Application.Run;
CloseHandle(H);
end;

Прочко Денис Владимирович.
sysadmin@)farmeko.khv.ru

Q-94: Delphi 6 требует Proxies.pas?

{$ifdef D_6_UP} // Это моя константа
DesignIntf, DesignEditors, DesignWindows, DsnConst,
{$else}
DsgnIntf,
{$endif}

Eugene Mayevski
------------------------------------

Вопрос: Файл designeditors.pas использует 'proxies' в uses.
Исходный текст (proxies.pas) или откомпилированный модуль (proxies.dcu) нигде не находится ни на моем жеском диске ни на D6 Pro CD..

Просто реорганизуйте ваш проект на использование runtime пакетов и добавьте "DesignIDE" к вашемк списку runtime пакетов. Proxies находится здесь, и вам не нужен исходный текст вообще.

Почему это сделано? Просто доя уверенности, что вы не сможете распространять design time части (property editors, component editors), это запрещено по личензии. DesignIDE.bpl не является свободно распространяемым, вы имеете право использовать его только на машине на которой установлена Delphi, подобно Component libraries.

forums.borland.com

Q-95: Как хранить настройки программ.

Нижеприведенный текст являет собой вольное изложение отдельных статей февральского выпуска Microsoft Platform SDK. Год 2001 от рождества Христова. При проектировании способов хранения настроек своей программы следует задаться тремя вопросами:

Что хранить.
Где хранить.
Как хранить.

Что хранить

Поскольку первая часть вопроса нам известна по определению, т.е. хранить мы будем настройки программы, то перейдем ко второй части вопроса. Ваша программа устанавливается на КОМПЬЮТЕР а пользуются ей ПОЛЬЗОВАТЕЛИ. Соответственно все настройки разделяются на две части а то и на все три - настройки которые относятся к компьютеру в целом, настройки которые относятся ко всем локальным пользователям, настройки которые относятся к конкретному пользовател. В зависимости от специфики программы первая и вторая часть могут быть совмещены или разделены.
Поэтому важно сделать логическое разделение - какие настройки вашей программы действительно специфичны для самого ПК, какие настройки должны прилагаться ко всем пользователям, какие должны прилагаться к конкретному пользователю. Кроме того Мокрософт рекомендует чтобы настройки учитывали возможную мобильность пользователя, т.е. для пользователя находящегося в разных местах, возможно потребуется иметь разные наборы настроек.

Где хранить

Вообще в голову приходят три вещи.
Хранить настройки в системном реестре.
Хранить настройки в каталоге куда установлена программа.
Хранить настройки в системном каталоге Windows.
Хранить настройка в домашнем каталоге пользователя.

В Windows имеется три места предназначенных для хранения настроек которыми и следует пользоваться.

Системный реестр
Домашний каталог пользователя (точнее один из его подкаталогов)
Общий каталог для пользователей

Прочие мысли о местах хранения настроек должны быть выброшены из голов как вредные и противоестественные, Microsoft уже за вас все придумала и нефиг извращаться. Для тех кто не понимает почему, объясняю. На нормальной ОС (W'NT, W'2K) программа обычно запускается от имени и с правами конкретного пользователя. Обычно, если этот пользователь не является администратором, он имеет право изменять содержимое следующих ресурсов:

часть реестра HKEY_CURRENT_USER\*
содержимое своего домашнего каталога
содержимое временного каталога (который как правило находится внутри домашнего)
содержимое некого каталога или каталогов специально выделенного для этого администратором

При нормальном (читайте параноидальном) администрировании системы прочие места либо доступны только в режиме чтения, либо вообще недоступны. В том числе и папки \Program Files и Windows. Посему любая попытка программы изменять любые файловые ресурсы окромя вышеуказанных черевата тем что ее (программу) и его (пользователя) пошлют подальше. Причем далеко не в самой вежливой форме.

Пример
Adobe Photoshop и его разработчики наивно полагают что им должны быть выданы эксклюзивные права мусорить своими scratch-файлами в корневых каталогах дисков, кроме того они полагают что им должна быть выдана в пользование в режиме полный доступ часть системного реестра.. Временных каталогов, специально выделенных для подобоного рода занятий, их не устраивает. Как результат - Photoshop имеет серьезные проблемы с работой под Windows NT/2000.

Системный реестр

С точки зрения хранения настроек программы системный реестр разделен на две части. Это ветви HKEY_CURRENT_USER для хранения настроек специфичных для пользователя, и HKEY_LOCAL_MACHINE для хранения настроек специфичных для всего ПК и соответственно всех пользователей, работающих с этим ПК. Рекомендуемая структура ветвей для хранения настроек программы - HKEY_CURRENT_USER\Software\Company Name\Application Name\Version и соответственно HKEY_LOCAL_MACHINE\Software\Company Name\Application Name\Version. Параметры Company Name, Application Name, Version желательно не хранить в виде hard-coded строк в коде программы а устанавливать в опциях проекта (Project\Options\Version Info) и доставать впоследствии из ресурса с помощью той же библиотеки RxLib. Альтернативный путь выбирать данные о версии программы из ресурсов - использование Windows API (GetFileVersionInfo, GetFileVersionInfoSize, VerQueryValue).
Программе следует расчитывать на то что доступ к подключам HKEY_LOCAL_MACHINE разрешен в режиме только для чтения, а доступ к подключам HKEY_CURRENT_USER допускает чтение, изменение и создание новых подключей и значений.
Программе следует расчитывать на то что нужных ей ключей может не оказаться в реестре или значения лежащие в реестре имеют неверный формат или недопустимые значения. В таком случае, вместо несуществующих или неверных значений настройки, программа должна использовать значения по умолчанию которые разработчик может "железно забить в код" или получить с помощью различных системных функций.
Не следует использовать системный реестр для хранения больших кусков данных. Вместо этого лучше хранить объемные данные в отдельном файле, а в реестре запомнить имя этого файла.

Домашний каталог пользователя

Для хранения настроек слишком больших для того чтобы их размещать в реестре существуют специально выделенные каталоги внутри домашнего каталога пользователя. Эти каталоги обычно называются "специальными каталогами" и имеют имена Application Data и Local Settings. Полный путь к ним можно получить с помошью функций SHGetSpecialFolderPath или SHGetFolderPath.

Общий каталог пользователей

Обычно это каталог "Documents and Settings\All users". Внутри него имеются такие-же подкаталоги для хранения настроек и данных программ но относящихся ко всем пользователям. Полный путь к ним можно также получить с помошью функций SHGetSpecialFolderPath или SHGetFolderPath.

Как хранить

Системный реестр
Для работы с системным реестром можно использовать функции Registry API общим числом около 40 штук, а можно использовать классы из Registry.pas - TRegistry, TRegistryIniFile, TRegIniFile. Особенно следует обратить внимание на TRegistryIniFile который предоставляет упрощенную модель доступа к системному реестру очень схожую с моделью работы с INI-файлами.

INI-файлы
Это старый метод хранения настроек программ, но все еще применяющийся программистами. Настройки хранятся в текстовом файле в виде:

[Section1]
Field1=Value1
Field2=Value2
...
FieldN=ValueN

[Section2]
Field1=Value1
Field2=Value2
...
FieldN=ValueN
...

[SectionN]
Field1=Value1
Field2=Value2
...
FieldN=ValueN

Для доступа к данным содержащимся в INI-файлах существуют классы из модуля IniFiles - TIniFile, TMemIniFile.
Преимущество использования INI-файлов состоит в том что их можно легко подредактировать с помощью текстового редактора. Они обычно легче воспринимаются для прочтения нежели дерево ключей системного реестра.

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

Экономится место
Настройку можно спрятать от пользователя (сделать нечитабельной)

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

Заключение

Почти вся эта информация была вычерпана из кладезя мудрости под названием Platform SDK (Software Development Kit), поставляемого в составе сборника документации MSDN (Microsoft Software Developer Network). Разработчикам настоятельно рекомендуется приобрести Platform SDK, это снимает огромную массу вопросов связанную с программированием под Windows.

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

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 (рус.)

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

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

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

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

Q-97: Как перетащить файлы из проводника в иою программу

TMainForm = class(TForm)
...
private
procedure WMDROPFILES(var Message: TWMDROPFILES); message
WM_DROPFILES;
procedure ProcessFile(Filename: string);
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
DragAcceptFiles(MainForm.Handle, TRUE); // enable drag&drop
end;

procedure TMainForm.ProcessFile(Filename: string);
begin
// any actions
end;

procedure TMainForm.WMDROPFILES(var Message: TWMDROPFILES);
var
Files : Longint;
I : Longint;
Buffer : array[0..MAX_PATH] of Char;
begin
Files := DragQueryFile(Message.Drop,$FFFFFFFF,nil,0); // Get count of
files
for I := 0 to Files - 1 do begin
DragQueryFile(Message.Drop,I,@Buffer,SizeOf(Buffer)); // Get N file
ProcessFile(Buffer); // do something with the file
end;
DragFinish(Message.Drop); // end drag loop
end;

"Anatoly Podgoretsky"

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

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

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

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