А. Григорьев - О чём не пишут в книгах по Delphi

Тут можно читать онлайн А. Григорьев - О чём не пишут в книгах по Delphi - бесплатно ознакомительный отрывок. Жанр: comp-programming, издательство БХВ-Петербург, год 2008. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    О чём не пишут в книгах по Delphi
  • Автор:
  • Жанр:
  • Издательство:
    БХВ-Петербург
  • Год:
    2008
  • Город:
    СПб
  • ISBN:
    978-5-9775-019003
  • Рейтинг:
    4.25/5. Голосов: 81
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

А. Григорьев - О чём не пишут в книгах по Delphi краткое содержание

О чём не пишут в книгах по Delphi - описание и краткое содержание, автор А. Григорьев, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Рассмотрены малоосвещённые вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные механизмы их работы, особенности для протоколов TCP и UDP и др. Большое внимание уделено разбору ситуаций возникновения ошибок и получения неверных результатов в "простом и правильном" коде. Отдельно рассмотрены особенности работы с целыми, вещественными и строковыми типами данных, а также приведены примеры неверных результатов, связанных с ошибками компилятора, VCL и др. Для каждой из таких ситуаций предложены методы решения проблемы. Подробно рассмотрен синтаксический анализ в Delphi на примере арифметических выражений. Многочисленные примеры составлены с учётом различных версий: от Delphi 3 до Delphi 2007. Прилагаемый компакт-диск содержит примеры из книги.

Для программистов

О чём не пишут в книгах по Delphi - читать онлайн бесплатно ознакомительный отрывок

О чём не пишут в книгах по Delphi - читать книгу онлайн бесплатно (ознакомительный отрывок), автор А. Григорьев
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

WndParent TWinControl(Owner).Handle

else

raise EInvalidOperation.CreateFmt(SParentRequired, [Name]);

FDefWndProc := WindowClass.lpfnWndProc;

ClassRegistered := GetClassInfo(WindowClass.hInstance, WinClassName, TempClass);

if not ClassRegistered or (TempClass.lpfnWndProc <> @InitWndProc) then

begin

if (ClassRegistered then

Windows.UnregisterClass(WinClassName, WindowClass.hInstance);

WindowClass.lpfnWndProc := InitWndProc;

WindowClass.lpszClassName := WinClassName;

if Windows.RegisterClass(WindowClass) = 0 then RaiseLastOSError;

end;

CreationControl := Self;

CreateWindowHandle(Params);

if FHandle = 0 then RaiseLastOSError;

if (GetWindowLong(FHandle, GWL_STYLE) and WS_CHILD <> 0) and (GetWindowLong(FHandle, GWL_ID) = 0) then

SetWindowLong(FHandle, GWL_ID, FHandle);

end;

StrDispose(FText);

FText := nil;

UpdateBounds;

Perform(WM_SETFONT, FFont.Handle, 1);

if AutoSize then AdjustSize;

end;

Собственно создание окна опять происходит не здесь, а в методе CreateWindowHandle, который очень прост: он состоит из одного только вызова API-функции CreateWindowExс параметрами, значения которых берутся из полей записи Paramsтипа TCreateParams(листинг 1.10)

Листинг 1.10. Запись TCreateParams

TCreateParams = record

Caption: PChar;

Style: WORD;

ExStyle: DWORD;

X, Y: Integer;

Width, Height: Integer;

WndParent: HWnd;

Param: Pointer;

WindowClass: TWndClass;

WinClassName: array[0..63] of Char;

end;

В записи Paramsхранятся параметры как окна, передаваемые в функцию WindowCreateEx, так и оконного класса (поля WindowClassи WndClassName). Все поля инициализируются методом CreateParamsна основе значений свойств оконного компонента. Данный метод виртуальный и может быть перекрыт в наследниках, что бывает полезно, когда необходимо изменить стиль создаваемого окна. Например, добавив расширенный стиль WS_EX_CLIENTEDGE(или, как вариант, WS_EX_STATICEDGE), можно получить окно с необычной рамкой (листинг 1.11).

Листинг 1.11. Перекрытие метода CreateParams

procedure TForm1.CreateParams(var Params: TCreateParams);

begin

// Вызов унаследованного метода заполнения всех полей

// записи Params

inherited CreateParams(Params);

// Добавляем флаг WS_EX_CLIENTEEDGE к расширенному стилю окна

Params.ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE;

end;

Примечание

В разд. 1.1.4 мы говорили, что имя оконного класса, который VCL создает для оконного компонента, совпадает с именем класса этого компонента. Здесь мы видим, что на самом деле имя оконного класса можно сделать и другим, для этого достаточно изменить значение поля Params.WinClassName.

Обратите внимание, что всем без исключения классам метод CreateWndназначает одну и ту же оконную процедуру — InitWndProc. Это является основой в обработке сообщений с помощью VCL, именно поэтому оконная процедура назначается не в методе CreateParams, а в методе CreateWnd, чтобы в наследниках нельзя было изменить это поведение (метод CreateWndтоже виртуальный, но при его переопределении имеет смысл только добавлять какие-то действия, а не изменять поведение унаследованного метода).

Чтобы понять, как работает процедура InitWndProc, обратите внимание на еще одну особенность метода CreateWnd: перед вызовом CreateWindowHandle (т.е. непосредственно перед созданием окна) он записывает ссылку на текущий объект в глобальную переменную СreationСontrol. Эта переменная затем используется процедурой InitWndProc(листинг 1.12).

Листинг 1.12. Оконная процедура InitWndProc

function InitWndProc(HWindow: HWnd; Message, WParam, LParam: LongInt): LongInt;

begin

CreationControl.FHandle := HWindow;

SetWindowLong (HWindow, GWL_WNDPROC, LongInt(CreationControl.FObjectInstance));

if (GetWindowLong(HWindow, GWL_STYLE) and WS_CHILD <> 0) and (GetWindowLong(HWindow, GWL_ID) = 0) then

SetWindowLong(HWindow, GWL_ID, HWindow);

SetProp(HWindow, MakeIntAtom(ControlAtom), THandle(CreationControl));

SetProp(HWindow, MakeIntAtom(WindowAtom), THandle(CreationControl));

asm

PUSH LParam

PUSH WParam

PUSH Message

PUSH HWindow

MOV EAX, CreationControl

MOV CreationControl, 0

CALL [EAX].TWinControl.FObjectInstance

MOV Result, EAX

end;

end;

Примечание

Код функции InitWndProcв листинге 1.12 взят из Delphi 7. В более поздних версиях код включает в себя поддержку окон, работающих с кодировкой Unicode, поэтому там предусмотрен выбор между ANSI- и Unicode-вариантами функций API (подробнее об ANSI- и Unicode-вариантах см разд. 1.1.12 ). Такой код сложнее понять из-за этих дополнений. Кроме того, из листинга 1.12 убрано все, что относится к компиляции под LINUX, чтобы не засорять листинг.

Из листинга 1.12 видно, что оконная процедура InitWndProcне обрабатывает сама никаких сообщений, а просто переназначает оконную процедуру у окна. Таким образом, InitWndProcдля каждого окна вызывается только один раз, чтобы переназначить оконную процедуру. Обработка того сообщения, которое привело к вызову InitWndProc, тоже передается в эту новую процедуру (ассемблерная вставка в конце InitWndProcделает именно это). При просмотре этого кода возникают два вопроса. Первый — зачем писать такую оконную процедуру, почему бы не назначить нужную процедуру обычным образом? Здесь все дело в том. что стандартными средствами оконная процедура назначается одна на весь оконный класс, в то время как по внутренней логике VCL каждый экземпляр компонента должен иметь свою собственную оконную процедуру. Добиться этого можно только порождением подкласса уже после создания окна. Указатель на свою уникальную оконную процедуру (откуда эта процедура берется и почему она должна быть уникальной, мы поговорим в следующем разделе) каждый экземпляр хранит в поле FObjectInstance. Значение глобальной переменной CreationControlприсваивается, как мы помним, непосредственно перед созданием окна, а первое свое сообщение окно получает буквально в момент создания. Так как VCL — принципиально однонитевая библиотека, ситуация, когда другой код вклинивается между присваиванием значения переменной CreationControlи вызовом InitWndProc, невозможна, так что в InitWndProcпопадает правильная ссылка на создаваемый объект.

Второй вопрос — зачем так сложно? Почему в методе CreateWndсразу после создания окна нельзя было вызвать SetWindowLongи установить нужную оконную процедуру там, вместо того чтобы поручать это процедуре InitWndProc? Здесь ответ такой: это сделано потому, что свои первые несколько сообщений (например, сообщения WM_CREATEи WM_NCCREATE) окно получает до того, как функция CreateWindowExзавершит свою работу. Чтобы завершить создание окна, CreateWindowExотправляет несколько сообщений окну, и только после того как окно обработает их должным образом, процесс создания окна считается завершенным. Так что назначать уникальную оконную процедуру после завершения CreateWindowEx— это слишком поздно. Именно поэтому уникальная оконная процедура назначается таким неочевидным и несколько неуклюжим способом.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


А. Григорьев читать все книги автора по порядку

А. Григорьев - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




О чём не пишут в книгах по Delphi отзывы


Отзывы читателей о книге О чём не пишут в книгах по Delphi, автор: А. Григорьев. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x