Too Frequently Asked Questions of RU.DELPHI hierarchy.
Слишком часто задаваемые вопросы эх иерархии RU.DELPHI
Copyright (c) Alexey Mahotkin 1997-1998
Редакция 0.12 от 01 Mar 1998
Общие вопросы программирования на Borland Delphi.
Compiler/maintainer: Alexey Mahotkin, 2:5020/433, alexm(at)hsys.msk.ru
Благодарности: активным писателям эх иерархии RU.DELPHI и контрибуторам
этого F.A.Q., without whom nihil.
С целью предотвращения спама произведено небольшое искажение e-mail адресов.
AA: Akzhan Abdulin, 2:5040/55
AB: Anthony Buntyakov, antosha(at)metcombank.ru
ArAs: Arthur Aseev, 2:5030/465.2
AG: Andrey Grigoriev, 2:5061/24.20
AK: Alex Konshin, 2:5030/217
AL: Alexander Lokshin, 2:5020/529
AP: Alexander Petrosyan, 2:5020/468.8
AlPe: Alex Petin, 2:5000/97.8
AR: Andrey Ruckoy, 2:5047/7
AnSa: Andrey Sarinkov, 2:5040/33.121
AS: Alexey Sinutin, 2:5022/12.16
AV: Andrew Verigo, 2:452/23.32
AY: Alexey Yashin, 2:5020/62.31
BL: Boris Loboda, 2:461/256
BP: Boris Podchezertseff, 2:5020/656.20
DK: Dmitry Kryloff, 2:5054/9.20
DS: Dmitry Shikhman, 2:468/13.32
EK: Eugene Kopko, 2:464/196
EL: Evgeny Levashoff, 2:5022/31.7
EM: Eugene Mayevski, 2:463/209
ES: Eugeny Sverchkov, 2:5031/12.23
IA: Ilya Andreev, 2:5030/55.28
IG: Ivan Gudym, 2:4642/2213.9
IS: Igor Slusarev, 2:5020/118.18
JB: Juris Bekins, 2:5100/35
MV: Max Vystropov, 2:5020/1412
PS: Pavel Shklovsky, 2:5011/18
RP: Roman Procopovich, 2:5030/254.201
RR: Roman Rechmakov, 2:5020/952.26
SB: Stanislav Babin, 2:5030/356.7
SK: Serge Korolev, 2:5020/104
SM: Sergey Mazunov, 2:5083/30.20
SO: Sergey Okhapkin, 2:5020/47
SV: Serg Vostrikov, 2:5053/15.3
SA: Sergey Arkhipov, 2:5054/88.10
SB: Sergey Belov, sbelov(at)aha.ru
VB: Victor Babkin, 2:463/279.6
VS: Vlad Sharnin, vlad(at)nplks.rb.ru
Q: 1. Как сделать так, чтобы программу можно было запустить только
в одном экземпляре?
A: Воспользуйтесь функцией ActivatePrevInstance из библиотеки rxLib. Для
завершения второго экземпляра, попытавшегося запуститься, используйте
Application.Terminate;
(AS): Другой вариант: X:\DELPHI2\DEMOS\IPCDEMOS\ipcthrd.pas, функция
IsMonitorRunning().
(EK): CreateSemaphore(nil,0,1,'MySemaphoreName');
if GetLastError = ERROR_ALREADY_EXISTS then
Halt(1);
..........
Application.Run;
Q: 2. Как работать с разными графическими форматами, кроме BMP, хотя бы
самыми распространенными: GIF, JPG, TIFF?
A: Воспользуйтесь библиотекой ImageLib. Лежит на www.imagelib.com.
Hа компакте с Delphi 3 в каталоге EXTRAS есть библиотека JPEG. Если сказать
в модуле uses jpeg; то можно работать с .jpg как с TPicture.
(AA): Опять-таки, есть LightLib Images (url не помню, но по altavista
находится с полпинка, поставляется с книжкой Чарлза Калверта).
Еще есть Nishita ViewLib, freeware. JPG/JIF/GIF/BMP/DIB/RLE/TGA/PCX.
http://einstein.ae.eng.ua.edu/nishita/index.htm
Q: 3. Куда из Delphi 3 делся модуль для работы с ReportSmith? А мои любимые
модули работы с OLE: ole2, oleauto и olectl?
A: Они лежат в X:\DELPHI3\LIB\DELPHI2\.
Q: 4. Моя программа довольно долго делает какую-то полезную работу, типа
чтения дерева каталогов или обильных вычислений, и в этот момент почти не
работают остальные программы. Как разрешить им это делать?
A: Application.ProcessMessages.
(AA): Win32: Если вы хотите отдавать timeslices в нитях, пользуйтесь Sleep(0);
это отдаст остаток слайса системе. Win16: Если вы хотите разрешить отработку
сообщений другим программам, но не вашей, то лучше пользоваться Yield().
Q: 5. Как мне вывести какое-нибудь окошко с картинкой, пока программа
грузится?
A: Смотрите пример в X:\DELPHI\DEMOS\DB\MASTAPP\mastapp.dpr.
Удобно использовать функцию ShowSplashWindow из rxLib.
Q: 6. Как мне запустить какую-нибудь программу? А как подождать, пока
эта программа не отработает? Как выяснить, работает ли программа или уже
завершилась? Как принудительно закрыть выполняющуюся программу?
A: WinExec() или ShellExecute. У второй больше возможностей.
(AY, VB): CreateProcess().
(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): Handle:=Winexec(App, 0); PostMessage(Handle, WM_QUIT, 0, 0);
Q: 7. Как мне работать с файлами MS Word или таблицами Excel?
A: Воспользоватьс функцией CreateOLEObject и работать с VBA или 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;
.....
Q: 8. Как сделать так, чтобы запущенна программа не была видна на
панели задач?
NB: Предположим, вы пользуетесь компонентой TrxTrayIcon из rxLib, иначе
непонятно, как вы будете возвращать ее из минимизированного состояния.
A: (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едупpеждаю пpо гpабли, на котоpые я наступал:
Будь готов к тому, что если пpи попытке закpытия пpиложения в OnCloseQuery
или OnClose выводится вопpос о подтвеpждении, то могут быть пpоблемы с
автоматическим завеpшением пpогpаммы пpи shutdown - под Win95 пpосто
зависает, под WinNT не завеpшается. Очевидно, что сообщение выводится, но
его не видно (пpичем SW_RESTORE не сpабатывает). Решение - ловить
WM_QueryEndSession и после всяких завеpшающих действий и вызова
CallTerminateProcs выдавать Halt.
Q: 9. А как поместить свою иконку на taskbar, там где часы и переключатель
клавиатуры?
A: В библиотеке rxLib есть компонент TrxTrayIcon.
Q: 10. Как сделать так, чтобы в моей форме курсор перемещалс по полям
ввода по Enter, как по Tab?
A: (SV):
Если вы хотите обрабатывать событие на уровне формы (а не в каждом отдельном
компоненте), уберите обработчики события у всех компонент и создайте
FormKeyPress -- обработчик OnKeyPress для формы:
procedure Form1.OnKeyPress(Sender : TObject; var Key : char);
begin
if Key = #13 then begin
SelectNext(Sender as TWinControl, true, true);
Key := #0;
end;
end;
(AnSa): Давно хотелось высказаться по поводy этого способа. Во-пеpвых, нyжно
выставлять y фоpмы KeyPreview = True. Во-втоpых, если на фоpмy поместить
default-кнопкy, то никакого пеpемещения фокyса не бyдет.
Q: 11. А где взять нормальный хелп дл Delphi 3? И для вторых, собственно,
тоже -- часть ссылок ведет в никуда, часть ведет не туда, некоторые компоненты
без хелпа...
A: Hадо поставить нормальные Delphi 3, а не Confidentional/Field beta.
Для Delphi 2 -- или найдите где-нибудь обновленные файлы .HLP, например, на
www.borland.com или на Delphi Super Page, или на каком-нибудь компакте, или
поставьте себе версию 2.01. Моя имеет истинную версию (Help|About...,
наберите Alt-VERSION) 2.0.76.0. Узнать ее можно также по странице Internet в
панели компонентов.
Q: 12. Посоветуйте что-нибудь для работы с модемом и/или COM-портом из Delphi.
A: AsyncPro. Он покроет 95% ваших нужд.
Для маньяков, желающих пользоваться Win32 -- открывайте "COMx" как файл и
пишите/читайте. Еще хорошо почитать Help на тему вещей, начинающихся на
"comm".
Q: 13. А как включить окошко CPU Window?
A: (AP): Вставьте в registry строковый ключ
HKCU\Software\Borland\Delphi\2.0\Debugging\EnableCPU=1
соответственно для Delphi 3 -- Delphi\3.0.
Q: 14. А как печатать на матричном принтере в текстовом режиме для
скорости?
A: (AR):
var
f : textfile;
begin
AssignFile ( f, 'prn' );
Rewrite ( f );
WriteLn ( f, 'some data' );
CloseFile ( f );
end.
NB: Hе забудьте, что слать данные надо в 866 кодовой странице. См. ниже.
Q: 15. Посоветуйте хорошую книгу по Delphi.
A: a) Кен Хендриксон "Руководство разработчика баз данных"
b) Рэй Конопка "Hаписание оригинальных компонент в среде Delphi"
c) Рэй Лишнер "Секреты Delphi 2"
d) Том Сван "Програмирование в Delphi для Windows95"
e) Tом Сван "Секреты 32 разрядного программирования в Delphi"
f) Джеффри Рихтер "Windows для профессионалов" (highly recommended!)
g) Т. Миллер, "Использование Delphi 3"
Q: 16. Как сделать плавно изменющийся цвет заголовка окна, как в
MSOffice'95?
A: Hадо ловить сообщение WM_NCPAINT. Существует также компонент CustomNC by
Alex Prilipko 2:5045/29, которые позволяет самому рисовать всю неклиентскую
часть окна.
(AP): Тот компонент - плохой. Совсем. Правильный компонент, by Акжан Абдулин
и еще кто-то был в фэхе(не WDEVDELPHI). Ищите cap*.zip.
NB: cap030.zip и cap031p.zip были в файлэхе FED32SRC.
Q: 17. Как мне перекодировать строки из Win-кодировки в Dos-кодировку и
наоборот?
A: CharToOEM/OEMToChar, CharToOEMBuff/OEMToCharBuff.
Q: 18. Как работать с архивными файлами, хотя бы с самыми
распространенными, типа .ZIP?
A: (AS): Воспользуйтесь библиотекой ExceedZip 3.0 (www.exceedsoft.com)
(VS): Hа CDROM с Delphi3 есть каталог INFO\EXTRAS\ZLIB. Подробности на
http://quest.jpl.nasa.gov/zlib/
Q: 19. Как правильно закрыть и удалить форму? Почему моя MDI Child форма
при закрывании просто минимизируется?
A: Обрабатывайте событие OnClose дл формы и выставлйте в нем параметр
Action в caFree. Дело в том, что его значение по умолчанию для MDI Child
форм =caMinimize. Кстати, если сделать Action := caNone, то форму нельзя
будет закрыть.
Q: 20. Мне надо добавить много строк в TListbox или в TCombobox или в TMemo
или в TRichEdit, при этом сам объект постоянно мигает, перерисовываясь. Как
избавиться от этого?
A: BeginUpdate/EndUpdate.
Q: 21. Как исправить проблемы с вызовом помощи при одновременно стоящих
Delphi 1 и Delphi2?
A: (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"
...и скажите "START HelpPath.REG":
Q: 22. Что такое rxLib?
A: Одна из самых, если не сама лучшая библиотека общего назначения для
Delphi. Огромное количество компонентов и полезных функций. Полные исходные
тексты. Совместима со всеми Delphi (1, 2 и 3), а также с C++-Builder.
Великолепные примеры использования. Исчерпывающие файлы помощи на русском
языке. Текущая версия -- 2.40.
IMHO -- a must have для любого дельфиста. Прежде чем огорчаться отсутствием
чего-либо или пытаться написать свое -- посмотрите, нет ли этого в rxLib.
Скажем так -- без rxLib мое программирование на Delphi будет гораздо более
утомительным.
Авторы:
Fedor Koshevnikov (kosh(at)masterbank.msk.ru)
Igor Pavluk (pavluk(at)masterbank.msk.ru)
Serge Korolev (korolev(at)masterbank.msk.ru)
Q: 23. Как мне запрограммировать непрямоугольную форму, например, как у
Norton CrashGuard, в форме щита?
A: (ArAs): SetWindowRgn(); (только Win32).
(AV): Есть компонент TFormShaper, free for noncommercial use:
http://www.wirtschaft.tu-ilmenau.de/~aeg/
(AM:) (Win32) Пример кода, создающий эллиптическую форму, которую к тому же
можно двигать за любую точку, что демонстрирует обработку сообщения
WM_NCHITTEST:
unit main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
rgn : HRGN;
procedure WMNCHitTest(var Message : TWMNCHitTest); message WM_NCHITTEST;
protected
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
rgn := CreateEllipticRgn(0, 0, Width, Height);
SetWindowRgn(Handle, rgn, True);
end;
procedure TForm1.WMNCHitTest(var Message : TWMNCHitTest);
begin
if PtInRegion(rgn, Message.XPos, Message.YPos) then
Message.Result := HTCAPTION
else
Message.Result := HTNOWHERE;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
DeleteObject(rgn);
end;
end.
(DK:) Hадо задать форме стиль окна WS_EX_TRANSPARENT. Тогда будут рисоваться
только лежащие на ней контролы.
Вот пример кода:
type
TForm1 = class(TForm)
{ ... }
protected
procedure CreateParams(var Params : TCreateParams); override;
end;
procedure TForm1.CreateParams(var Params : TCreateParams);
begin
inherited CreateParams(Params);
{ форма становится прозрачной }
Params.ExStyle := Params.ExStyle or WS_EX_TRANSPARENT;
end;
end;
Q: 24. Delphi 2 & 3 не отображают русские TTF под Windows NT WorkStation
+ ServicePack#3.
A: (AlPe): Попробуй сделать
[HKLM\Software\Microsoft\Windows NT\CurrentVersion\FontMapper]
DEFAULT=0xcc (204) вместо 0x00 (Именно DEFAULT, а не (Default):-) получше
маленько будет...
Q: 25. Как установить компонент от Delphi 2 под Delphi 3? Delphi требуют
.PAS-файл.
A: Hикак. Ищите исходник или .DCU, скомпилированный дл Delphi 3.
Q: 26. Как получить от программы сообщения на русском языке?
A: (EL): 1) В X:\Delphi\Sources\vcl - отредактировать все файлы текстовых
ресурсов Delphi (или наиболее часто возникающие Exception'ы и надписи
на кнопках).
2) В Delphi\bin есть компилятор текстовых ресурсов (brcc32.exe - точно не
помню).Откомпилировать все изменненные *.rc.
3) Получившиеся res-файлы кинуть в Delphi\Lib
(SB): Для Delphi 3:
1) Delphi3\Doc\Consts.int переименовать в Delphi3\Doc\Consts.pas;
2) внутри Consts.pas в конце дописать: "end.";
3) внутри Consts.pas исправить все "Yes", "No", "Cancel" и т. д. на русский
вариант;
4) откомпилировать consts.pas с помощью dcc32, получится Consts.dcu.
5) Consts.dcu скопировать в Delphi 3\Lib вместо имеющегося там.
NB: Русские ресурсы для D1 и D2 проходили в свое время по WDEVDELPHI в файле .
Q: 27. При возникновении ошибки во врем отладки программы машина
перезагружается. Что делать?
A: Снести QEMM. Hачисто. Простое отключение его функций не помогает.
Q: 28. Как использовать свои курсоры в программе?
A:
{$R CURSORS.RES}
const
crZoomIn = 1;
crZoomOut = 2;
Screen.Cursors[crZoomIn] := LoadCursor(hInstance, 'CURSOR_ZOOMIN');
Screen.Cursors[crZoomOut] := LoadCursor(hInstance, 'CURSOR_ZOOMOUT');
Q: 29. Как правильно создавать компоненты в run-time? Что задавать в
качестве параметра Owner при создании компоненты? Как обрабатывать события
от созданных компонент, типа нажатий на кнопки?
A: 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: 30. Как ограничить перемещение курсора мыши какой-либо областью
экрана?
A: ClipCursor()
Q: 31. Как отловить события создания или удаления файлов другими
программами?
A: (Win32:) FindFirstChangeNotification/FindNextChangeNotification/
FindCloseChangeNotification
(Win16:) FileCDR, но она плохо документирована.
Q: 32. Как сделать так, чтобы по Alt-F4 форма не закрывалась,
а выдавала запрос на сохранение?
A: Обрабатывать OnCloseQuery.
Q: 33. При работе программ на D1 под Win95 в hicolor-режимах иконки на
TBitBtn'ах обнаруживаются странные коричневые артефакты. Как от них избавиться?
A: (AB): Залить фон битмапа синим цветом.
Q: 34. Как работать с registry?
A: TRegistry.
Q: 35. Как получить короткий путь файла если имеется длинный?
("c:\Program Files" ==> "c:\progra~1").
A: GetShortPath()
Q: 36. Как напрмую работать с портами/памтью из-под Win95/NT?
A: (VS): а http://www.strongsoftware.net/tvicport/ лежат TVicHW32 и TVicPort.
Под Win95 можно обращаться к портам из ассемблерных вставок. Под NT этот номер
не пройдет -- скорее всего, придется писать драйвер устройства. RTFM WindowsNT
Device Driver Kit.
Q: 37. Как переключать раскладку клавиатуры из своей программы?
A: ActivateKeyboardLayout.
Q: 38. Как просматривать HTML в программе?
A: Можно воспользоватьс Netscape Navigator или Internet Explorer -- они
умеют быть OLE-серверами.
(AL): Еще на www.pbear.com лежат THTMLViewer и TFrameViewer.
Q: 39. Как перехватывать клавиши, нажатые в окне другой программы?
И вообще, любые события, поступающие другим программам?
A: (AP): SetWindowsHookEx(). Пример использования лежит на
www.i-connect.ru/~paf/links31.zip
Q: 40. Как вывести диалог выбора _директории_?
A: (DS): SelectDirectory, rxLib: TDirectoryEdit.
Q: 41. Не работает передача данных по OLE в русский Excel.
A: (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: 42. Можно ли скомпилировать на Delphi 2/3 программу, работающую
под Windows 3.1?
A: (NP): Нет, но на компактах с Delphi 2/3 поставлется Delphi 1 специально
для этой цели.
Q: 43. Как вызывать из 32-битной программы 16-битные DLL?
A: (EM): Надо применть так называемые Thunks. Смотри статью на
http://www.itecuk.com/delmag/thunk95.htm
Q: 44. Почему у меня record a : word; b : longint end; имеет размер
восемь байт вместо шести?
A: RTFM packed, $A.
Q: 45. Где взть подробную документацию по работе с RTF, TRichEdit?
A: (MC): www.microsoft.com/msdn, зарегистрироваться и искать.
Q: 46. Как можно перетаскивать форму не только за заголовок?
A: WM_NCHITTEST.