Советы по Delphi

         

Ошибка диалога настройки принтера


Я разместил в своем приложении вызов диалога настройки принтера. Он вызывается из моего меню PrinterSetupDialog1.Execute ... пока вроде все нормально. Теперь вот что странно: мое приложение может вызвать его только один раз. При попытке вызвать его вторично ничего не происходит. Диалог не появляется.

Это "недавнообнаруженная" проблема. Для ее решения необходимо вызывать GetPrinter и SetPrinter перед каждым вызовом PrinterSetupDialog1.Execute:

    var Driver, Device, Port: array[0..79] of Char; Mode: THandle; begin ... GetPrinter(Driver, Device, Port, Mode); SetPrinter(Driver, Device, Port, 0); PrinterSetupDialog1.Execute; ... end;

Та же проблема возникает при использовании кнопки "Setup" из диалога печати.



-Steve Schafer [000719]



Ошибка фунциии GetTextLen компонента Memo


По всей видимости, функция GetTextLen в компоненте Memo работает не совсем правильно.

Загрузите в Memo1 большой текстовый файл.

    var {пример из файла помощи}
Buffer: PChar; Size: Byte; begin
Size := Memo1.GetTextLen; Inc(Size); GetMem(Buffer, Size); Memo1.GetTextBuf(Buffer, Size); ...   {не относящийся к делу код...} FreeMem(Buffer, Size); end;

Проблема: Memo1.GetTextLen возвращает размер выводимого, а не всего текста. [000350]



Ошибка фунциии Print.EndDoc


Да, EndDoc проверяет флаг FAborted, но вызывает EndPage, даже если FAborted равно True. EndDoc используется только тогда, когда печать завершена полностью и *успешно*.

Процедура Abort предполагает вызов Windows API AbortDoc(), но не делает этого и, следовательно, прерывание процесса печати не останавливает работу принтера. Поэтому, для обхода этой ошибки вам следует вызвать

    WinProcs.AbortDoc(Printer.Handle);

Я исправил модуль PRINTERS.PAS, после чего GPF пока не возникал...

    CheckPrinting(True); AbortDoc(Canvas.Handle); FAborted := True; WinProcs.EndDoc(DC);

- Garry Prefontaine [000409]



Ошибка Grid RangeSel+RowSel


Тема: Ошибка Grid RangeSel+RowSel
От: Bill Goelkel 71725,455
К: Все

Компонент: TStringGrid, TDrawGrid

Проблема: Если в свойстве Options goRangeSelect и goRowSelect имеют True, то не выбирается диапазон, состоящий из последовательных строк. Вместо этого выделяются множетсво разрозненных строк.

Решение: В исходных файлах VCL, строка 2,310 файла GRIDS.PAS:
procedure TCustomGrid.MoveAnchor, измените FAnchor.Y на FAnchor.X,
теперь это должно выглядеть так:

    if goRowSelect in Options then FAnchor.X := ColCount-1;

- Bill Goelkel [000781]



Ошибка конфигурации BDE


Я ищу противоположность SetRange, что-либо типа GetRange, но не нахожу этого ни в Delphi API, ни в BDE API.

В электронной справке обзор этой темы помещен в Filter Modes. Там вы можете узнать, что EditRangeStart и EditRangeEnd переводят таблицу в модальное состояние SetKey, где соответствующим критерием для включения/выключения фильтра служит отдельная запись, Метод ApplyRange возвращает в режим таблицы. Вот пример применения критерия фильтра (Filter criteria):

    Table1.EditRangeStart; { Устанавливаем начальный ключ } Label1.Caption := Table1.Fields[0].AsString; Table1.EditRangeEnd; { Устанавливаем конечный ключ } Label2.Caption := Table1.Fields[0].AsString;

[000704]



Ошибка маски редактирования на быстрых пентиумах


Данное поведение уже упоминалось ранее. Это, похоже, происходит только на быстрых машинах. Если у вас имеется исходный код RTL, вы можете сделать следующие изменения:

В MASK.PAS, замените

    for I := Low(NewKeyState) to High(NewKeyState) do NewKeyState[I] := 0;

На

    NewKeyState := KeyState;

- Steve Schafer [001003]



Ошибка метода ItemAtPos компонента ListBox


Оказывается, что метод ItemAtPos компонента ListBox - печальная жертва одной ошибки. Справочная система сообщает, что если вы вызываете ItemAtPos с параметром Existing, установленным в False и позиция курсора находится не над существующим элементом списка, функция возвращает позицию ПОСЛЕДНЕГО элемента списка.

ОШИБКА: TListBox.ItemAtPos(Point(X,Y), False) НЕ возвращает позицию последнего элемента списка когда курсор не над элементом. В этом случае функция возвращает позицию следующего, не существующего элемента списка. [000345]



Ошибка объекта TListBox


Я получаю ошибку index out-of-range (индекс за пределами диапазона) при вызове DetailList.Items.Objects[X], когда X равен нулю, при дальнейшем тестировании ошибка Detail.Items[X] исчезает, даже когда X равен нулю. В чем дело?

Эта ошибка, похоже, происходит если я привожу -1 к типу TObject и размещаю ее в ListBox в массиве Items.Objects.

Это вызвано ошибкой в TListBoxStrings:

    function TListBoxStrings.GetObject(Index: Integer): TObject; begin Result := TObject(SendMessage(ListBox.Handle, LB_GETITEMDATA, Index, 0)); if Longint(Result) = LB_ERR then raise EStringListError.Create(LoadStr(SListIndexError)); end;

LB_ERR, вы наверное догадались, -1!

- Ralph Friedman [000997]



Ошибка переполнения диска


Попробуйте удалить из вашего проекта все, кроме dpr, pas и dfm-файлов, и перекомпилить его. Похоже, один из файлов вашего проекта был испорчен. У меня была аналогичная проблема, и я смог ее решить только таким способом. [001439]



Ошибка прокручивания TOutLine


Да, TOutline содержит ошибку реализации. По неизвестной причине, если у компонента есть горизонтальная полоса прокрутки, событие OnDrawItem не возникает. Установите только вертикальный скроллбар, или не устанавливайте их вовсе, это решит проблему. [000429]



Ошибка сохранения текста в Memo


При использовании примера текстового редактора (TextEditor), всякий раз, когда я использую функцию выравнивания (center, left или right) или Wordwrap, свойство Memo1.Modified сбрасывается в False!

Воспроизведение ошибки: Запустите пример текстового редактора Откройте любой текстовый файл, используя File|Open Создайте новый файл, используя File|New Напечатайте какой-либо текст Разместите окна рядом, используя Windows|Tile Модифицируйте открытый вами текстовый файл, включив в него несколько пробелов Возвратитесь к новому файлу и отцентрируйте текст Выйдите из программы, используя File|Exit Программа НЕ попросит сохранить ваш новый файл, поспольку флаг modified был сброшен в False! [000319]



Ошибка StringList.Find


TStringList.Find предполагает что список отсортирован, в противном случае метод Find терпит неудачу. Вероятно реальная ошибка (если она одна) в том, метод Find располагается в секции public. Для предотвращении такой путаницы его нужно было бы упрятать в секцию protected.

Вместо этого применяйте IndexOf, который использует метод Find только в том случае, если список отсортирован. [000450]



Ошибка TListBox MeasureItem


MeasureItem не работает, если элементы были добавлены через AddObject.

AddObject работает в два этапа. Сначала добавляется строка, затем указатель на объект. Проблема заключается в том, что добавление строки инициирует событие MeasureItem прежде, что происходит присвоение указателя на объект, поэтому в обработчик события MeasureItem вместо указателя попадает *мусор*. Не nil, не данные, а простой мусор.

Я обошел эту проблему, устанавливая глобальный флаг перед загрузкой элементов. MeasureItem проверяет этот флаг, и если он выставлен, указатель на объект игнорируется и возвращается произвольная высота. После этого я загружаю элементы, в цикле вычисляю высоту каждого, и для установления высоты использую сообщение lb_SetItemHeight. Все это я делаю перед тем как ListBox станет видимым. В конце я сбрасываю флаг, поскольку остальные вызовы MeasureItem обрабатываются правильно.

Конечно, это все криво, но другого решения я пока не знаю.

-Scott Samet [000720]



Ошибка TOutline ChangeLevelBy


...я, похоже, не могу получить для работы уровень ChangeLevelBy(-1), тем не менее, если вам необходимо переместить элемент на один уровень назад, то это можно сделать так:

    with Outline1[Outline1.SelectedItem] do
if
Level > 1 then moveto(Parent.Index,oaAdd);

[000682]



Ошибка в DriveComboBox


У меня была серия неудач, когда Delphi не смог загрузить некоторые формы и мой .EXE GPed. И всякий раз ошибка была связана с файлом LANGENG.DLL

Складывается впечатление, что виновником здесь является Drive combo box. У меня ошибка возникла только когда в диске D: (CD-ROM) была копия игры 7th guest. Этот CD имел нулевой объем и, естественно, не имел файлов в корневой директории.

Устанавливая свойство Uppercase в False, проект в этом случае вызывал ошибку в User.exe. [000424]



Ошибка в mmsystem.pas


"Объявление WaveInClose неверно."

Вы можете просто вновь объявить это сами:

    function WaveInClose(hWaveIn: THandle): Word; far; external 'MMSYSTEM'  index 505;

-Steve Schafer [000790]



PASDBK16.DLL вызывает GPF


Кто-нибудь может мне сказать, почему я получаю эту ошибку, да еще с рекомендацией завершить работу Delphi? При попытке запустить мое приложение в среде ID, я получаю сообщение "PASDBK16.DLL caused a GPF at 0002:21e6 Shutdown of delphi is recommended" (PASDBK16.DLL вызвало GPF по адресу 0002:21e6. Рекомендуется завершить работу Delphi). Если я завершаю работу Delphi, снова его запускаю и пытаюсь после этого выполнить приложение, то получаю ошибку "Application is already running terminate before compiling" (Работа приложения уже прервана перед компиляцией).

У меня возникла сегодня такая же проблема, и мой коллега нашел ее решение. Если каталог разработки вы делаете каталогом общего доступа, то при наличии разных проектов может случиться так, что настройки компилятора одного из проектов будут использованы при сборке другого, использующего тот же путь. Проблема в модулях общего доступа, которые компилируются по разным путям. Решение заключается в определении выходного (output) каталога для вашего приложения и полной пересборки проекта (не забудьте при этом создать соответствующий каталог). После этого проблема должна исчезнуть.

- Sjef van der Velde [001103]



Printer.Abort не работает...


Это может помочь:

    procedure TForm1.Button1Click(Sender: TObject); begin Printer.BeginDoc; Printer.Canvas.TextOut(100,100, 'Программирование - это просто'); if CheckBox1.Checked then {Прерывание работы принтера.} begin Printer.Abort; WinProcs.AbortDoc(Printer.Canvas.Handle); Printer.EndDoc; {Наводим порядок.} exit; end; Printer.EndDoc; end;

- William E Murto [000727]



Проблема фильтров в компоненте SaveDialog


Для диалога SaveDialog1 я установил 3 фильтра. Она классно появляются при открытии выпадающего списка. Что мне необходимо сделать: мне нужно "прочесть" содержимое выбранного пользователем из списка фильтра для того, чтобы при последующем открытии SaveDialog1 данный элемент предлагался ему в первую очередь (свойство ItemIndex).

Это ошибка в исходном коде VCL, внутренней переменной FFilterIndex не присваивается значение, выбранное пользователем.

Если у вас имеется исходный код VCL, вы можете это исправить, скорректировав TOpenDialog.DoExecute в Dialogs.PAS. Просто добавьте следующее:

    function TOpenDialog.DoExecute(Func: Pointer): Bool; CommonDialogList.Remove(Self); if Result then begin ProcessMultipleSelection(lpstrFile); FFileName := FFiles.Strings[0]; FFilterIndex := nFilterIndex;                   {<=== вот что вам нужно добавить} if (Flags and OFN_EXTENSIONDIFFERENT) <> 0 then FOptions := FOptions + [ofExtensionDifferent]

Не (повторяю: не) изменяйте секцию interface кода VCL, если вы собираетесь продолжать пользоваться IDE.

- Owen Barder [000891]



Проблемы с диалогом печати (PrintDialog)


...в итоге я получил действительно большую проблему. У меня не получается вызывать диалоги PrintDialog и PrinterSetupDialog более одного раза. Метод вызова каждого диалога у меня привязан к определенному пункту меню и соответствующим кнопкам SpeedButton. После одного или двух нажатий оба диалога перестают работать, т.е. при их вызове ничего не происходит. Я проверял это на трех других компьютерах, работающих под операционной системой Windows for Workgroups.

Вот что нужно сделать:

В DIALOGS.PAS измените

    { 1530 }   hWndOwner := Application.Handle; { 1531 }   if TaskModalDialog(@PrintDlg, PrintDlgRec) then { 1532 }     SetPrinter(hDevMode, hDevNames) { 1533 }   else

на

    { 1530 }   hWndOwner := Application.Handle; { 1531 }   SetPrinter(hDevMode, hDevNames); { 1532 }   if not TaskModalDialog(@PrintDlg, PrintDlgRec) then

и

    { 1582 }   if Result then { 1583 }   begin { 1584 }     SetPrinter(hDevMode, hDevNames); { 1585 }     F := Flags;

на

    { 1582 }   SetPrinter(hDevMode, hDevNames); { 1583 }   if Result then { 1584 }   begin { 1585 }     F := Flags;

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

    procedure InitPrinter; var Device, Driver, Port: array[0..79] of Char; DevMode: THandle; begin GetPrinter(Device, Driver, Port, DevMode); SetPrinter(Device, Driver, Port, DevMode); end;

-Steve Schafer [000864]



Советы по Delphi


Какая может быть причина того,


Какая может быть причина того, что программа, работающая в среде W31, не работает в W95 ?

Похоже на то, что данные, сохраненные в двоичном файле, читаются неправильно.

Имеется масса отличий в фундаментальных типах между Delphi 1.0 и Delphi 2.0, которые могут повлиять на двоичный файл. Вот некоторые из них: строки в Delphi 1.0 не эквивалентны строкам по умолчанию (длинным) в версии 2.0 "integer" 16-биный в Delphi 1.0 и 32-битный в 2.0 записи автоматически упаковываются в Delphi 1.0, но не в Delphi 2.0 - Rick Rogers [001111]


Что рекомендует Borland по поводу


Что рекомендует Borland по поводу организации дискового пространства Delphi версии 1.0 и 2.0 для использования обоими версиями без проблем одного и того же исходного кода?

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

Примерно такую же схему я использую и при работе с компонентами: модули регистрации я размещаю в различных модулях, например, XxxReg.pas для Delphi 1.0 и XxxReg32.pas для Delphi 2.0. Формат файлов ресурсов в WIN32 также другой, что приводит к необходимости иметь соответствующие XxxReg.dcr и XxxReg32.dcr, содержащие иконки для палитры компонентов. В качестве альтернативы вместо двух DCR-файлов возможно использование единственного файла Reg.pas и двух RES-файлов, и директивы {$R ...}, обернутой в директивы условной компиляции, управляющие выбором загрузки одного из файлов. (Смотрите ниже дополнение от Dan Miser).

При переключении с Delphi 2.0 на 1.0, вы должны или сделать "build all", или создать bat-файл для удаления всех DCU файлов.

Наконец, вы можете задавать различные выходные (output) каталоги для каждого проекта в Delphi 1 и 2. С помощью данного способа вы можете хранить все DCU и EXE файлы в отдельных каталогах. Для этой цели в каталоге приложения я использую два подкаталога с именами 16Bit и 32Bit.

- Mike Scott.

Дополнение от Dan Miser:

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

Образец списка файлов компонента:

XXXREG.R16 16-битный DCR файл
XXXREG.R32 32-битный DCR файл
XXXREG.PAS Модуль регистрации компонента

    unit XXXREG.PAS
interface
uses
Classes;
procedure Register;
implementation
{$IFDEF WIN32} {$R XXXREG.R32} {$ELSE} {$R XXXREG.R16} {$ENDIF}
procedure Register begin {Здесь расположен ваш код регистрации} end;
end.
[000923]


Module header is missing or


Когда я дважды щелкаю в Проводнике на файле, я получаю окно с ошибкой, гласящее: Error in module TestBu~1.dpr. Module header is missing or incorrect. (Ошибка в модуле TestBu~1.dpr. Заголовок модуля потерян или неверен.) В Delphi 2.0 информация, хранимая в регистрах, и необходимая для ассоциации и запуска проекта по его типу и имени файла, поддерживает в среде Win95 только 8 символов. Для исправления сложившийся ситуации, перейдите в меню Проводника и выберите пункт View|Options. Выберите закладку File Types и прокрутите список до появления регистрации расширений файлов Delphi. Выберите первый, щелкните на кнопке Edit, и дважды щелкните в списке на строке с командой Open. Заключите имя exe-файла в двойные кавычки и добавьте "%1", все это должно выглядеть примерно так: "D:\Borland\Delphi 2.0\Bin\Delphi32.EXE" "%1" Осуществите описанные выше действия для всех четырех зарегистрированных типов файлов Delphi.

- Mike Scott. [000921]


Ошибка чтения потока


Каждый раз при запуске Delphi 2.01 я получаю ошику "Stream Read Error" (ошибка чтения потока). Как мне отделаться от этого?

Удалите DSK- и DSM- файлы из вашего проектного каталога.

- Ralph Friedman [001093]



Всякий раз при возврате пустого


Всякий раз при возврате пустого результата в Delphi 2 при работе с Tquery я получаю ошибку INVALID FLOATING POINT OPERATION (неверная операция с плавающей точкой). Я что-то неправильно делаю, или это новая характеристика Delphi?

Я получал эту ошибку и уже давно ее исправил, (только не спрашивайте у меня почему) изменив синтаксис с 'WHERE a = "Hi"' на 'WHERE a IN ("Hi")'.

- Robert A. Dickinson [000917]


Ошибка в 32-битном StringGrid


Во время выполнения приложения заголовки колонок перемещаются, а сами колонки с данными нет. В 16-битной версии все работает превосходно.

- Bruce Bukovics [000989]



Ошибка в модуле Math


Функции MinValue и MaxValue в модуле Math возвращают значение, обратное ожидаемому (неверный код в math.pas).

- Christer Matson [000979]



Я только что установил Delphi


Я только что установил Delphi 2.0, все прошло успешно и без единой ошибки, в процессе инсталляции коментарии и замечания не возникали.

Далее в Delphi 2.0 я открываю руководство "Getting Started" (Подготовка). Согласно странице 42, "Adding a display grid" (добавление и отображение сетки данных), добавляю на форму DBGrid, устанавливаю DataSource в GDSDataModule.CustomerSource, но данные в DBGrid не отображаются, хотя на странице 42 написано "Immediately, the data is displayed in the DBGrid" (данные немедленно будут отображены в DBGrid).

При запуске приложения тоже самое, данные не отображаются.

При вызове из меню Delphi "Database Explorer" все таблицы и их данные видятся без проблем.

Таблицу необходимо открыть. Установите свойство Active компонента Тable в True. [000062]


Проблема Reset текстового файла


Имеется известная ошибка в Reset: если вы используете это в открытом текстовом файле, поля буфера файла _не_ сбрасываются в начало буфера. Вы можете обойти это, используя CloseFile, AssignFile и Reset вместо использования только Reset или "вручную" сбрасывая буфер:

    Reset( filevar ); with TTextRec(filevar) do SetTextBuf(filevar, BufPtr^, BufSize);

- Peter Below [000961]



Проблема с HeapAlloc


При попытке использования значений флагов, описанных в электронной справке, компилятор сообщает, что он не может их найти, т.е. они нигде не объявлены.

Похоже их объявления были удалены из WINDOWS.PAS:

    HEAP_NO_SERIALIZE        = 1 HEAP_GENERATE_EXCEPTIONS = 4 HEAP_ZERO_MEMORY         = 8

-Steve Schafer [000929]



в bsDialog, то невозможно использовать


В FORMS.PAS зловредная ошибка!!! Если Borderstyle установить в bsDialog, то невозможно использовать biHelp-BorderIcon. Почему? Ответ в процедуре CreateParams в строке:

    Icons := Icons * [biSystemMenu];
Данная строка фильтрует все, кроме biSystemMenu. Поэтому флаг biHelp и становится здесь недоступен! Правильная строка должна быть такой:

    Icons := Icons * [biSystemMenu, biHelp];
Я думаю что отчасти проблема заключается в несоответствии с Win95-MDI-Parent-Form (родительской MDI формы). Родительская форма клиента (Client Parentform) не в 3D (WS_EX_CLIENTEDGE). Любое другое Win95-MDI-приложение имеет 3D-эффект. Решение данной проблемы очень простое. ClientHandle в процедуре CreateWnd должен генерироваться с CreateWindowEx вместо CreateWindow, а ExtendedStyle WS_EX_CLIENTEDGE должен устанавливаться следующим образом:

    FClientHandle := Windows.CreateWindowEx(WS_EX_CLIENTEDGE,'MDICLIENT', nil, WS_CHILD or WS_VISIBLE or WS_GROUP or WS_TABSTOP or WS_CLIPCHILDREN or WS_HSCROLL or WS_VSCROLL or WS_CLIPSIBLINGS or MDIS_ALLCHILDSTYLES, 0, 0, ClientWidth, ClientHeight, Handle, 0, HInstance, @ClientCreateStruct);
Я надеюсь эта ошибка будет устранена уже в первой заплатке к Delphi2.0.

- Rolf Frei [000959]


Распределение памяти TstringList


Я создаю объект TStringList и добавляю 10,000 десятибайтовых строк по 1000 строк за раз, после чего, с помощью функции GetHeapStatus, получаю информацию о куче. Ниже представляю вам результаты: число TotalAddrSpace TotalAllocated 0 1,048,576 11,268 1,000 1,048,576 40,848 2,000 2,097,152 69,344 3,000 3,145,728 97,888 4,000 4,194,304 126,296 5,000 6,291,456 154,868 6,000 9,437,184 183,268 7,000 12,582,912 211,828 8,000 14,680,064 240,248 9,000 18,874,368 268,800 10,000 23,068,672 297,208 Я гляжу что Delphi 2.0 для моих данных размером 300Кб выделила памяти аж 23Мб! Ну и кому это понравится? У меня есть программа, заполняющая TStringGrid, и она работает вдвое медленне чем в версии Delphi 1.0! Похоже, что вся эта заторможенность вызвана чрезмерным распределением памяти.

- Mark Ford

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

-Steve Schafer [000916]



Связь TDBMemo и StringField


У меня имеется на одной из страниц TabNotebook поле DBMemo. Это поле связано с таблицей TTable (активной). Но я не могу редактировать, посылать или удалять значение этого поля. Почему? Поле в таблице текстовое, с 255 символами (A255)...

Mark Edington (Delphi R&D) признал наличие проблемы со связью элемента управления TDBMemo с TStringField в Delphi 2 и пообещал ее устранить в ближайшее время.

- Mike Orriss [000986]



Куда из Delphi 3 делся модуль


Nomadic отвечает:

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



Получение констант с определением ошибки функцией LoadStr


Возбуждение исключения и передача строковой константы ошибки из CONSTS.PAS (как это делалось в Delphi 1 и Delphi 2) в Delphi3 невозможна. Например:

    raise SomeException.Create(LoadStr(SInsertLineError));

в Delphi3 теперь не работает. Я предлагаю использовать выражение

    raise SomeException.Create( {$IFNDEF VER100}LoadStr{$ENDIF} (SInsertLineError));

для вызова функции LoadStr "по нужде", устаревшей почему-то для этих целей в Delphi 3.

При попытке вызвать данную функцию в Delphi 3 (для получения типа ошибки, декларированной в модуле CONSTS(.PAS/.DCU)), мы получаем следующую ошибку компилятора: "Incompatible types: 'Integer' and 'String'"

Никакой информации по этому поводу я не нашел ни в фирменной документации, ни на Borland-сервере. [000061]



Некорректность реализации свойства BorderWidth



При использовании в компонентах свойства BorderWidth будте внимательны. В большинстве компонентов (ControlBar, ProgressBar, StatusBar, ToolBar, TrackBar и т.д.), это свойство реализовано некорректно. Можно получить забавные результаты или большие неприятности.

На рисунке показаны возможные варианты при использовании различных значений BorderWidth в компоненте ProgressBar. Высота компонента ProgressBar.Height = 16.

В последних двух вариантах вместо индикатора – изображение под активным окном. Не надейтесь, что компонент стал "прозрачным". Это "моментальный снимок" при создании окна.

Если есть желание, то некорректность можно исправить в ComCtrls.pas, переопределив BorderWidth.

   
TProgressBar = class(TWinControl) private … FBorderWidth: TBorderWidth; … procedure SetBorderWidth(Value: TBorderWidth); … published … property BorderWidth: TBorderWidth read FBorderWidth write SetBorderWidth;

constructor TProgressBar.Create(AOwner: TComponent); begin … FBorderWidth := inherited BorderWidth; … end;
procedure TProgressBar.SetBorderWidth(Value: TBorderWidth); begin if Value > (Height div 2)-3 then Exit if Value <> inherited BorderWidth then begin inherited BorderWidth := Value; FBorderWidth := inherited BorderWidth; end; end;

Аналогичный подход можно использовать в других компонентах. В процедуре SetBorderWidth вместо Exit можно создать исключение, но это уже на любителя. C уважением, VS. [001297]



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


Nomadic советует:

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



в Delphi 1, каждая форма,


Под win95 в EXE-файле, скомпилированном в Delphi 1, каждая форма, имеющая диалоговый стиль, имеет на Панели Задач свою кнопку. Например в ситуации, когда имеется главная форма и форма с фокусом, пользователь может нажать кнопку главной формы и не увидеть форму, активную в данный момент, вследствие чего он может подумать о том, что приложение "зависло". Такое же поведение наблюдается если активна форма, не имеющая диалогового стиля, а пользователь нажимает на Панели Задач кнопку главной формы.

Скрытому окну Delphi-приложения необходим стиль WS_CAPTION, поэтому вам необходимо его задать только в модуле Forms или в обработчике события формы OnCreate:

    SetWindowLong(Application.Handle,GWL_STYLE, WS_CAPTION or      GetWindowLong(Application.Handle,GWL_STYLE))
Это также причина того, почему это работает в Delphi 2 (здесь стиль устанавливается в Forms)!

- Nils Seidel [000988]


Иногда, мое приложение, работающее


Олег Кулабухов приводит следующий код:

Во время обработки сообщений PopUp меню, вы должны назначить активное окно, а потом после всплывания меню послать сообщение WM_NULL.

    procedure TForm1.WndProc(var Msg : TMessage);
var
p : TPoint;
begin
case
Msg.Msg of
WM_USER + 1:
case Msg.lParam of
WM_RBUTTONDOWN: begin
SetForegroundWindow(Handle);
GetCursorPos(p);
PopupMenu1.Popup(p.x, p.y);
PostMessage(Handle, WM_NULL, 0, 0);
end;
end;
end;
inherited;
end;

[001837]



Как добавить документы в папку `Старт`->`Документы`?


Олег Кулабухов приводит следующий код:

    uses ShlOBJ;

procedure TForm1.Button1Click(Sender: TObject);
var
s : string;
begin
s := 'C:\DownLoad\ntkfaq.html';
SHAddToRecentDocs(SHARD_PATH, pChar(s));
end;

[001786]



Как изменить изображение кнопки `Пуск`


The_Sprite советует:

Пример из серии "Что можно сделать с рабочим столом". В общем, это обычный трюк с кнопкой "Пуск" (Start).

Совместимость: все версии Delphi

    { объявляем глобальные переменные }
var
Form1: TForm1; StartButton: hWnd; OldBitmap: THandle; NewImage: TPicture; { добавляем следующий код в событие формы OnCreate }
procedure TForm1.FormCreate(Sender: TObject);
begin
NewImage := TPicture.create; NewImage.LoadFromFile('C:\Windows\Circles.BMP'); StartButton := FindWindowEx
(FindWindow( 'Shell_TrayWnd', nil),
0,'Button', nil); OldBitmap := SendMessage(StartButton,
BM_SetImage, 0,
NewImage.Bitmap.Handle); end;
{ Событие OnDestroy }
procedure TForm1.FormDestroy(Sender: TObject);
begin
SendMessage(StartButton,BM_SetImage,0,OldBitmap); NewImage.Free; end;

[001375]



Как я могу использовать анимированный курсор?


Из советов Nomadic'a:

Сперва Вы должны взять хэндл курсора Windows и присвоить его одному из элементов массива Cursors обьекта Screen.

Предопределенные курсоры имеют отрицательный индекс, а определенные пользователем (Вами) курсоры получают положительные индексы.

Ниже пример формы, использующей анимированный курсор:

    procedure TForm1.Button1Click(Sender: TObject);
var
h: THandle; begin
h := LoadImage(0, 'C:\TheWall\Magic.ani', IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE or LR_LOADFROMFILE ); if h = 0 then ShowMessage('Cursor not loaded') else begin Screen.Cursors[1] := h; Form1.Cursor := 1; end; end;

[001127]



Как очистить папку 'Документы' меню 'Старт'?


Олег Кулабухов приводит следующий код:

Просто используйте SHAddToRecentDocs() с параметром имени файла nil.

    uses
ShlOBJ;

procedure TForm1.Button1Click(Sender: TObject);
begin
SHAddToRecentDocs(SHARD_PATH, nil);
end;

[001841]



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


Nomadic отвечает:

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



Как определить появление каких-либо изменений на дисплее?


Олег Кулабухов приводит следующий код:

    type
TForm1 = class(TForm)
Button1: TButton;
private
{ Private declarations }
procedure WMDisplayChange(var Message: TMessage);
message WM_DISPLAYCHANGE;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.WMDisplayChange(var Message: TMessage);
begin
{Do Something here}
inherited;
end;

[001906]



Как определить размер Desktop-TaskBar?


Олег Кулабухов приводит следующий код:

    procedure TForm1.Button1Click(Sender: TObject);
var
r : TRect;
begin
SystemParametersInfo(SPI_GETWORKAREA,
0,
@r,
0);
Memo1.Lines.Add(IntToStr(r.Top));
Memo1.Lines.Add(IntToStr(r.Left));
Memo1.Lines.Add(IntToStr(r.Bottom));
Memo1.Lines.Add(IntToStr(r.Right));
end;

[001883]



Как отключить хранитель экрана?


Олег Кулабухов приводит следующий код:

    procedure TForm1.Button1Click(Sender: TObject);
begin
{Turn it off}
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,
0,
nil,
0);
{Turn it on}
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,
1,
nil,
0);
end;

[001829]



Как открыть 'Панель управления' и ее компоненты?


Олег Кулабухов приводит следующий код:

Начнем.

Запуск самой контрольной панели:

    WinExec('rundll32 shell32.dll,Control_RunDLL',SW_SHOW);

Свойства дисплея - Фон:

    WinExec('rundll32 shell32.dll,Control_RunDLL desk.cpl,,0',SW_SHOW);

Свойства дисплея - Хранитель экрана:

    WinExec('rundll32 shell32.dll,Control_RunDLL desk.cpl,,1',SW_SHOW);

Свойства экрана - Оформление:

    WinExec('rundll32 shell32.dll,Control_RunDLL desk.cpl,,2',SW_SHOW);

Свойства экрана - Настройки:

    WinExec('rundll32 shell32.dll,Control_RunDLL desk.cpl,,3',SW_SHOW);

Установка времени:

    WinExec('C:\WINDOWS\CONTROL.EXE TIMEDATE.CPL', sw_ShowNormal);

Свойства мыши:

    WinExec('C:\WINDOWS\CONTROL.EXE MOUSE',sw_ShowNormal);

Принтеры:

    WinExec('C:\WINDOWS\CONTROL.EXE PRINTERS', sw_ShowNormal);

[001863]



Как получить снимок экрана (типа screen-capture программ)?


Решение 1

Используйте стандартный Windows API:

используйте hWnd := GetDesktopWindow для получения дескриптора 'рабочего стола';
используйте hDC := GetDC (hWnd) для получения HDC (дескриптора контекста экрана) ;
и не забывайте освобождать (уничтожать дескриптор) hDC после выполнения задачи.

Используя TCanvas.Handle в качестве HDC, можно при помощи WinAPI реализовать функции рисования, или, если это возможно, можно присвоить HDC свойству Handle непосредственно при создании TCanvas.

Решение 2

В D1 (по идее должно работать и в D2) попробуйте это:

Разместите на форме TPaintBox и TButton.

    procedure TForm1.Button1Click(Sender: TObject);

var
DeskTop : TCanvas ;
begin
DeskTop := TCanvas.Create ; try with DeskTop do Handle := GetWindowDC (GetDesktopWindow) ;
with PaintBox1.Canvas do CopyRect (Rect (0, 0, 200, 200), DeskTop, Rect (0, 0, 200, 200))
finally DeskTop.Free
end end;

Это скопирует верхнюю левую область рабочего стола в верхнюю левую область вашего TPaintBox. [000121]



Как поменять обои в Windows 98/Windows 2000, когда включен Active Desktop?


Олег Кулабухов приводит следующий код:

Да, в данном случае стандартное изменение через SystemParametersInfo не пройдет. Придется использовать IActiveDesktop. Но учтите, что для его применения библиотека Shell32.dll должна иметь версию старше 4.71. В этом FAQ есть пример того, как узнавать версию файла, можете им воспользоваться.

    uses
ComObj, // For CreateComObject and Initialization/Finalization of COM
ShlObj; // For IActiveDesktop

{ The CLASS ID for ActiveDesktop is not defined in
ShlObj, while the IID is so we define it here. }
const
CLSID_ActiveDesktop: TGUID = '{75048700-EF1F-11D0-9888-006097DEACF9}';

{ Demonstrate getting the Wallpaper }
procedure TForm1.Button1Click(Sender: TObject);
var
ActiveDesktop: IActiveDesktop;
CurrentWallpaper: string;
CurrentPattern: string;
WallpaperOptions: TWallpaperOpt;
tmpBuffer: PWideChar;
begin
// Create the ActiveDesktop COM Object
ActiveDesktop := CreateComObject(CLSID_ActiveDesktop) as IActiveDesktop;

// We now need to allocate some memory to get the current Wallpaper.
// However, tmpBuffer is a PWideChar which means 2 bytes make>
// up one Char. In order to compenstate for the WideChar, we
// allocate enough memory for MAX_PATH*2
tmpBuffer := AllocMem(MAX_PATH*2);
try
ActiveDesktop.GetWallpaper(tmpBuffer, MAX_PATH*2, 0);
CurrentWallpaper := tmpBuffer;
finally
FreeMem(tmpBuffer);
end;
if CurrentWallpaper <> '' then
Label1.Caption := 'Current Wallpaper: ' + CurrentWallpaper
else
Label1.Caption := 'No Wallpaper set';

// Now get the current Wallpaper options.
// The second parameter is reserved and must be 0.
WallpaperOptions.dwSize := SizeOf(WallpaperOptions);
ActiveDesktop.GetWallpaperOptions(WallpaperOptions, 0);
case WallpaperOptions.dwStyle of
WPSTYLE_CENTER: Label2.Caption := 'Centered';
WPSTYLE_TILE: Label2.Caption := 'Tiled';
WPSTYLE_STRETCH: Label2.Caption := 'Stretched';
WPSTYLE_MAX: Label2.Caption := 'Maxed';
end;

// Now get the desktop pattern.
// The pattern is a string of decimals whose bit pattern
// represents a picture. Each decimal represents the on/off state
// of the 8 pixels in that row.
tmpBuffer := AllocMem(256);
try
ActiveDesktop.GetPattern(tmpBuffer, 256, 0);
CurrentPattern := tmpBuffer;
finally
FreeMem(tmpBuffer);
end;
if CurrentPattern <> '' then
Label3.Caption := CurrentPattern
else
Label3.Caption := 'No Pattern set';
end;

{ Demonstrate setting the wallpaper }

procedure TForm1.Button2Click(Sender: TObject);
var
ActiveDesktop: IActiveDesktop;
begin
ActiveDesktop := CreateComObject(CLSID_ActiveDesktop)
as IActiveDesktop;
ActiveDesktop.SetWallpaper('c:\downloads\images\test.bmp', 0);
ActiveDesktop.ApplyChanges(AD_APPLY_ALL or AD_APPLY_FORCE);
end;

[001923]