Часть 3
Имеются два новых оператора : as и is. as - оператор защищенного преобразования типов (typecasting). Вы можете использовать его, чтобы заставить компилятор преобразовать объект из одного типа в другой, но, если в во время выполнения эти типы окажутся несовместимыми, то вы получите ошибку. Hапример, если вы имеете класс TSport, с потомоками TBasketball и TFootball, вам может потребоваться переменная типа TSport; далее может так случиться, что в программе эта переменная будет фактически содержать экземпляр типа TFootball. Тогда вы можете обратиться к этой переменной
function PlayerGoodness(var MySport: TSport): Integer;
begin if (MySport is TBasketball) then Result := (MySport as TBasketball).ReboundShots else if (MySport is TFootball) then Result := (MySport as TFootball).TotalYardage; end; |
Основная
структура выглядит примерно так:
P := New(BigThing); try try Proc1(P); Proc2(P); except Handle(P); raise; end; finally Dispose(P); end; |
Создайте
метод для формы, перехватывающий исключения. Этот метод будет вызываться обработчиком
OnException объекта Application. В вашем методе проверьте, тот
ли это исключение, что вы ожидаете, например EDatabaseError. Почитайте
on-line help для события OnException. Там есть информация, как вызвать
собственный метод для события.
procedure TForm1.MyExcept(Sender: TObject; E: Exception);
begin if E is EDatabaseError then MessageDlg('Поймали exception', mtInformation, [mbOk], 0) { это не то, сделать raise } else raise E; end; procedure TForm1.FormCreate(Sender: TObject);
|
4. Delphi
используют строки в стиле Pascal или C?
И те и другие. Delphi имеет два различных набора функций манипулирования строками, один - для PChar; но в Delphi также есть функция MessageDlg, которая принимает строки типа Pascal.
Delphi
2.0 добавляет так называемые длинные строки (AnsiString), которыми
можно манипулировать как обычными строками в Pascal, но они имеют динамически
изменяющийся размер и могут быть размером до 4Гбайт. Можно выполнять преобразования
от PChar к AnsiString и наоборот. Старый строковый тип теперь
называется ShortString. По умолчанию кличевое слово string соответствует
типу AnsiString.
5. Есть ли в Delphi битовые множества?
В явном виде
битовых множеств в языке Object Pascal нет. Но вместо этого можно использовать
обычные множества, которые на самом деле и хранятся как битовые. Если множество
вам нужно для проверки, установлен ли какой то бит в слове (байте и т.д.)
можно попробовать такую конструкцию:
type PByteSet = ^TByteSet; TByteSet = set of Byte; var |
Я написал на C++ DLL, в которой у меня функция использует число типа float, передал из Delphi число типа Single и получил GPF 'Invalid Opcode'. Что неправильно?
Если
вы используете числа с плавающей точкой, лучше передавать их не по значению,
а по ссылке (указатель в C++). Вероятно DLL написана на MS Visual C++, так
как Microsoft и Borland используют разные соглашения о передаче параметров
при работе с сопроцессором. В случае Borland C++ и Delphi должны использовать
одинаковый способ передачи параметров и значений (через стек сопроцессора).
В любом случае вместо Single лучше использовать Double (double
или long float в C++), так как вообще говоря, реальный тип, который
соответствует типу Single точно не определен и может измениться в будущем.
7. Как заставить
приложение Delphi отвечать на сообщения Windows?
Используем сообщение WM_WININICHANGED в качестве примера. Объявление метода в TForm позволит вам обрабатывать сообщение WM_WININICHANGED:
procedure TForm1.WMWinIniChange(var Message: TMessage);
begin inherited; { ... ваша реакция на событие ... } end; |
Попробуйте
сделать это следующим образом:
type TForm1 = class(TForm) ... private procedure WMNCActivate(var Msg: TMessage); message WM_NCACTIVATE; end; procedure TForm1.WMNCActivate(var Msg: TMessage);
|
9. Как
перехватить сообщения Windows и обработать их перед тем, как выполнится строка
Application.Run?
Пример проекта
показывает, как получить сообщения Windows в данном случае. Это редкий случай,
в большинстве случаев переопределение процедуры Application.OnMessage
будет делать то же самое.
program Project1;
uses {$R *.RES} var function NewWndProc(hWndAppl: HWnd; Msg, wParam: Word;
lParam: Longint): Longint; export; begin |
10. Проблема с DragDrop
для внешних программ.
Я пишу небольшую программку - "мусорную корзину". В FormCreate вызывается DragAcceptFiles(HANDLE, True). Проблема в том, что когда размер окна восстанавливается и затем минимизируется Drag and Drop перестает работать. Я безуспешно пробовал помещать DragAcceptFiles в разные методы формы. Однако если сделать вызов DragAcceptFiles(Application.Handle, True) в MainForm.Create, то все работает. Как перехватить событие WM_DROPFILES ?
Это
можно сделать так:
type TMainForm = class(TForm) ... procedure FormCreate(Sender: TObject); private procedure DropFiles(var Msg : TWMDropFiles); message WM_DROPFILES; end; procedure TMainForm.DropFiles(var Msg : TWMDropFiles);
procedure TMainForm.FormCreate(Sender: TObject);
|
Следующий
код показывает как обрабатывать это событие. Обрабатываются имена всех "брошенных"
файлов. Для загрузки каждого файла вызывается CreateChild(FName). В
обработчике OnCreate данной формы вы должны вызвать DragAcceptFiles.
type TFrameForm = class(TForm) ... protected procedure WMDropFiles(var Msg: TMessage); message WM_DROPFILES; end; procedure TFrameForm.WMDropFiles(var Msg : TMessage);
|
Эквивалент в Delphi - Application.ProcessMessages.
Если вы выполняете
долгие вычисления, то вызов данного метода позволит в Win 16 выполняться параллельно
другим приложениям, а в Win 32 - корректно перерисовываться вашему приложению.
13. В каком порядке
происходят события при создании и показе окна?
При создании окна обработчики событий выполняются в следующем порядке:
Данная функция (UpCase) производит преобразование только латинских символов в верхний регистр. Для правильного преобразования необходимо использовать функции Windows API, поскольку именно Windows должна "знать" о кодировке национальных символов. Причем к конфигурации BDE кодровка Windows не имеет никакого отношения - имея английские Windows без русификатора и выставив в BDE кодировку Paradox ANSII Cyrillic нормальных русских букв получить не удастся.
А функции
для преобразования следующие - OemToAnsi, AnsiToOem, OemToAnsiBuf, AnsiToOemBuf
в Win16 (модуль WinProcs) и OemToChar, CharToOem, OemToCharBuf и CharToOemBuf
в Win32 (модуль Windows)..
15. Приложение,
написанное на Delphi, не запускается минимизированным.
Проверьте
глобальную переменную CmdShow для того чтобы определить, в каком состоянии
запускается приложение, и модифицируйте ее как вам необходимо:
begin if CmdShow = SW_SHOWMINNOACTIVE then WindowState := wsMinimized; end;
begin if CmdShow = SW_SHOWMINNOACTIVE then WindowState := wsMinimized else WindowState := wsMaximized; end; |
Секция interface - интерфейсная. Туда попадают объявления констант, типов (в т.ч. и объектов или классов) переменных, процедур и функций. Поэтому для этой части uses должен содержать ссылки на те модули, которые используются для объявлений в этой части.
Секция implementation - описание реализации интерфейсной части, здесь в uses должны быть упомянуты те модули, которыми вы пользуетесь для написания кода. Например, Вы хотите в модуле пользоваться функциями API Windows, для этого добавьте в объявлении implementation строку uses WinTypes, WinProcs; или uses Windows;. Таким образом, вы явно указываете что данными модулями будете пользоваться только в секции реализации.
Конечно,
можно упоминать модули только в части interface, но правильная расстановка
имен модулей в соответствующем uses гарантирует исключение циклических
ссылок, а также улучшает читаемость программы.
17. Как спрятать окна MDI Child?
Я пытаюсь это сделать, выставляя Form1.Visible := False, но это не помогает.
Windows
не позволяет прятать окна MDI Child.
18. Как убрать заголовок
у формы MDIChild?
Как убрать заголовок (Caption) из MDIChild?
Для
MDIChild установка свойства BorderStyle := bsNone не убирает
заголовок. Это можно сделать так:
procedure TMDIChildForm.CreateParams(var Params:
TCreateParams); begin inherited CreateParams(Params); Params.Style := Params.Style and (not WS_CAPTION); end; |
Мне нужно использовать clipboard для сохранения данных в собственном формате и я хочу для этого написать набор процедур ввода/вывода с использованием потоков (streams). Возможно ли создать объект TMemoryStream, эаполнить его и поместить в Clipboard?
Не только возможно, именно так поступают функции Clipboard.GetComponent и Clipboard.SetComponent. Сначала вы должны зарегистрировать свой собственный формат данных для Clipboard с помощью функции RegisterClipboardFormat:
Пример:
var hBuf: THandle; Bufptr: Pointer; MStream: TMemoryStream; begin MStream := TMemoryStream.Create; try { write your data to the stream } hBuf := GlobalAlloc(GMEM_MOVEABLE, MStream.Size); try BufPtr := GlobalLock(hBuf); try Move(MStream.Memory^, BufPtr^, MStream.Size); Clipboard.SetAsHandle(CF_MYFORMAT, hBuf); finally GlobalUnlock(hBuf); end; except GlobalFree(hBuf); raise; end; finally MStream.Free; end; end; |
Внимание: не уничтожайте буфер, созданный с GlobalAlloc. Поскольку вы поместили его в Clipboard, это уже дело clipboard'а его уничтожить. Опять же, получая буфер из Clipboard, не уничтожайте этот буфер - просто сделайте копию содержимого.
Для обратного
получения потока и данных, сделайте что-нибудь вроде этого:
var hBuf: THandle; BufPtr: Pointer; MStream: TMemoryStream; begin hBuf := Clipboard.GetAsHandle(CF_MYFORMAT); if hBuf <> 0 then begin BufPtr := GlobalLock(hBuf); if BufPtr <> nil then try MStream := TMemoryStream.Create; try MStream.WriteBuffer(BufPtr^, GlobalSize(hBuf)); MStream.Position := 0; { read your data from the stream } finally MStream.Free; end; finally GlobalUnlock(hBuf); end; end; end; |
В исходном тексте одного из компонентов третьих фирм я увидел строку:
В
соответствии с соглашением Windows код клавиши #0 означает отсутствие
реального нажатия. Управление в данную точку программы могло попасть, например
вследствие прямого вызова, а не нажатия клавиши или же нажатие уже было обработано
предком, вследствие чего код нажатой клавиши был сброшен в 0.
21. Аналог процедуры TP/BP Delay.
procedure TForm1.Delay(MSecs: Longint); var FirstTick: Longint; begin FirstTick := GetTickCount; repeat Application.ProcessMessages; until GetTickCount - FirstTick >= MSecs; end; |
В
Win32 API существуют также функции Sleep и SleepEx.
22. Каким
образом создать форму, которую можно таскать за поле?
Как сделать форму (окно), которое перетаскивается не за заголовок (Сaption), а за все поле ?
Нужно
обрабатывать сообщение WM_NCHITTEST:
type TForm1 = class(TForm) ... private procedure WMNCHitTest(var M: TWMNCHitTest); message WM_NCHITTEST; end; procedure TForm1.WMNCHitTest(var M: TWMNCHitTest);
|
Примечание:
окно можно сделать вообще без Сaption.
23. Как
программно спрятать или показать заголовок у формы?
Как программно спрятать или показать заголовок (Caption) у формы?
Вы
можете попробовать следующее:
procedure TForm1.HideTitlebar; var Save: Longint; begin if BorderStyle=bsNone then Exit; Save := GetWindowLong(Handle, GWL_STYLE); if (Save and WS_CAPTION) = WS_CAPTION then begin case BorderStyle of bsSingle, bsSizeable: SetWindowLong(Handle, GWL_STYLE, Save and (not WS_CAPTION) or WS_BORDER); bsDialog: SetWindowLong(Handle, GWL_STYLE, Save and (not WS_CAPTION) or DS_MODALFRAME or WS_DLGFRAME); end; Height := Height-GetSystemMetrics(SM_CYCAPTION); Refresh; end; end; procedure TForm1.ShowTitlebar; |
24. Как сделать приложение модальным?
Мне нужно сделать приложение модальным, для того чтобы обезопасить систему и в то же время позволить работать с программой.
Ok, пара предложений на эту тему:
Form1.SetFocus;
Application.OnDeactivate := FormDeactivate;
NullItem1.ShortCut := ShortCut(VK_Tab, [ssAlt]);
(NullItem1 нужно заменить на название созданного вами объекта - пункта меню)
Шаги 4-6
предотвращают переход на приложение по Alt-Tab.
25. Как изменить
шрифт у Application.Title (заголовка приложения)?
Никак. Это
ограничение Windows - вы не можете изменить шрифт ни у одного заголовка ни
у приложения, ни у окна. Для окна можно предложить следующее - создать свое
окно без заголовка (Caption) и рамки, которое будет само выводить нужную
надпись нужным шрифтом и одновременно будет способно изменять свои размеры.
26. Каким
образом (желательно не специфичным для Delphi) узнать, открыто меню или нет?
Вот так:
type TForm1 = class(TForm) MainMenu1: TMainMenu; Item01: TMenuItem; Item11: TMenuItem; Item21: TMenuItem; private { Private declarations } public procedure WMMenuSelect(var M: TWMMenuSelect); message WM_MENUSELECT; end; implementation {$R *.RES} procedure TForm1.WMMenuSelect(var M: TWMMenuSelect);
end. |
Следующий код показывает, как передать переменную в отчет.
В примере
строковой переменной отчета 'City' присваивается значение 'Bombey'.
Подразумевается, что есть готовый отчет с данной переменной. Поместите компонент
TReport на форму и установите требуемые свойства для вызова печати
отчета. Напишите обработчик OnClick для кнопки Button1 на форме
(кнопка - для простоты) :
procedure TForm1.Button1Click(Sender: TObject);
begin Report1.InitialValues.Clear; Report1.InitialValues.Add('@City=<Bombey>'); Report1.Run; end; |
Имя шрифта для отображения русских букв берется из файла PDOXWIN.INI секция [Properties] строка SystemFont. Если очень хочется, то можно исправить имя 'PDOXWIN.INI' на 'DBD.INI' в файле DBSRV.DLL (он лежит там же где и DBD.EXE) по смещению $E9D8 (не забудьте после 'DBD.INI' поставить шестнадцатеричный ноль), и в секции [Properties] файла DBD.INI добавить строку типа
Действительно,
если у Вас Pan Euro или русская версия Windows95, то DBD не будет показывать
шрифты Cyr в Preferences/General/Default system font.
Решить эту проблему можно двумя способами:
Для этого следует проверить существование определенных окон:
Delphi
1.0
function DelphiLoaded: Boolean;
function WindowExists(ClassName, WindowName: string):
Boolean; begin |
function DelphiLoaded: Boolean;
function WindowExists(ClassName, WindowName: string):
Boolean; begin |
function InIDE: Boolean; begin Result := Bool(PrefixSeg) and Bool(PWordArray(MemL[DSeg:36])^[8])); ;end |
На ранней стадии создания приложения решите для себя хотите ли вы позволить форме масштабироваться. Преимущество немасштабируемой формы в том, что ничего не меняется во время выполнения. В этом же заключается и недостаток (ваша форма может бать слишком маленькой или слишком большой в некоторых случаях).
Я создают toolbar, у меня есть иконки, но нет картинок в виде bitmap. Помогите!
Для преобразования файлов из одного формата в другой лучше всего иметь что-нибудь вроде HiJaak, который может преобразовывать форматы напрямую. Однако, будем считать, что у вас нет ничего, кроме Windows и Delphi. Следующая процедура может использоваться чтобы преобразовывать иконку в формат Windows Bitmap:
В
Delphi 1.0 есть специальный файл (X:\DELPHI\BIN\WORKOPT.DOS) который необходимо
поместить в каталог, где находится Workshop - в этом случае последний будет
"понимать" ресурсы, создаваемые Delphi 1.0 (например *.DCR).
8. Когда
используется свойство Glyph, как узнать, какой цвет прозрачный?
Delphi всегда
принимает, что цвет пикселя в левом нижнем углу картинки является фоновым
цветом и должен отображаться на экране как прозрачный. Это нигде не документировано,
но если у вас есть исходники VCL, вы можете посмотреть код в BUTTONS.PAS .
9. Как отобразить bitmap в
256 цветах?
Как подгрузить 256 цветный bitmap из ресурса и отобразить его в нормальной палитре?
Обычно это делается следующим образом. Код Вадима Пузанова (Красноярск).
procedure XLoadBitmap(Instance: THandle; BitmapName: PChar;
var HB: HBitmap; var HP: Palette); var DC: HDC; BI: PBitMapInfo; Pal: PLogPalette; I: Integer; ResIdHandle: THandle; ResDataHandle: THandle; Bitmap: HBitmap; C: HWnd; OldPalette, Palette: HPalette; begin procedure TForm1.FormCreate(Sender: TObject);
|
Hикакие. Все компилируется в .EXE файл. Конечно, если вы разработали другие файлы (HLP, данные и т.д. ), или если вы используете VBX/OCX файлы, тогда вы должны распространять и их заодно. Если вы используете файлы VBX, то в поставку нужно также включать BIVBX11.DLL.
Если приложение
использует функции BDE, вы также должны включать Borland DataBase Engine.
Конечно,
может: Нажмите кроме Shift еще и Alt и режьте на здоровье. Alt можно сразу
отпустить. Чтобы вернуться в старый режим, нужно выделить что-либо мышкой.
2. Редактирование файлов
SQL в Delphi IDE.
Если вы в Delphi 2.0 IDE редактируете файл с расширением SQL, то, хотя это нигде не документировано, происходит автоматический Syntax Highlighting. Наибольший недостаток - не отслеживается конец комментария '*/'.
В
Delphi 3.0 комментарии отрабатываются нормально.
3. Встроенный отладчик/дизассемблер.
Если вы создадите в ключе
Для Delphi 3.0 справедливо тоже самое ( ...\Delphi\3.0\Debugging, естественно), причем отладчик там по возможностям сравним с Turbo Debugger.
[Назад][Содержание][Вперед]