2009-02-24 2 views
21

Компоненты Delphi имеют CreateWnd и CreateWindowHandleDestroyWnd и DestroyWindowHandle). Они оба должны быть переопределены потомками, верно? И не предназначен для вызова, за исключением базовой реализации VCL?В чем разница между CreateWnd и CreateWindowHandle?

В чем разница между ними; когда должен быть отменен любой из них?

ответ

36

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

CreateParams();

В общем, большую часть времени вам действительно нужно переопределить CreateParams(). Если все, что вы хотите сделать, - это подкласс (помните стиль подкласса Windows?), См. Основную работу Petzold по программированию Windows), существующий класс управления и завершение его в элементе управления VCL, вы делаете это из CreateParams. Вы также можете контролировать, какие биты стиля установлены и другие различные параметры. Мы очень упростили процесс создания «подкласса». Просто вызовите CreateSubClass() из вашего метода CreateParams(). См. Основные элементы управления VCL для примера, такого как TCheckBox или TButton.

CreateWnd();

Вы бы переопределили это, если вам нужно немного поработать с дескриптором окна после его создания. Например, если у вас есть элемент управления, который является каким-то списком, деревом или иным образом требует конфигурации после создания, вы можете сделать это здесь. Вызовите унаследованный CreateWnd, и когда он вернется (вы знаете, что у вас есть действительный дескриптор, если вы вернетесь из CreateWnd, потому что он вызовет исключение, если что-то пойдет не так), просто примените свою дополнительную магию. Обычный сценарий - взять данные, которые кэшируются в списке экземпляров TStrings и фактически переместить его в базовый элемент управления окном. TListBox - классический пример этого.

CreateWindowHandle();

Я должен был обновить свою память на этом, но кажется, что это один, редко, если когда-либо, переопределяется. В немногих случаях внутри самого VCL кажется, что он используется для работы с определенными версиями Windows и локальными странностями с некоторыми элементами управления, такими как TEdit и TMemo. Другой более четкий случай - в самом TCustomForm. В этом случае он поддерживает новую модель интерфейса MDI (интерфейс mutli-document). В этом случае дети MDI не могут быть созданы с использованием обычного API CreateWindowEx(), вам нужно отправить сообщение в родительский фрейм MDI, чтобы фактически создать дескриптор. Поэтому единственной причиной этого метода является то, что фактический процесс создания дескриптора выполняется с помощью средств, совершенно иных, чем старый проверенный и созданный CreateWindowEx().

Я заметил, что ваш вопрос просто спрашивал о процессе создания, но есть соответствующие методы, которые в некоторых случаях переопределяются как для разрушения дескриптора, так и для «вуду», который иногда окружает релаксацию рук. Но это другие темы, которые следует рассматривать отдельно :-).

+0

Отличный ответ. Просто хотел добавить хороший веб-ресурс, чтобы завершить ответ, поскольку в исходном вопросе упоминается VCL: http://edn.embarcadero.com/article/20569 – Ampere

4

CreateWnd сначала вызывает CreateParams, а затем вызывает CreateWindowHandle, используя созданные Params. Как правило, вы переопределяете CreateWnd и CreateParams, а не CreateWindowHandle.

Надеюсь, это поможет!

0

Я уверен, что окончательный ответ может исходить только от людей, участвующих в создании VCL (Allen?), Но IMHO виртуальный метод с наименьшей ответственностью/который является самым низким в цепочке вызовов, должен быть переопределены. Вот почему я всегда переопределял CreateParams() и CreateWindowHandle(). Это похоже на хорошую подгонку, так как они оба вызываются CreateWnd(), и оба делают только одну специальную вещь.

В конце концов, это, вероятно, вопрос предпочтения.

2

Кто что делает:
CreateWnd является генеральным подрядчиком, который создает полностью сформированное окно для WinControl.
Прежде всего, он должен установить необходимые атрибуты для WindowClass, позвонив CreateParams и убедившись, что он правильно зарегистрирован.
Затем он получает фактически созданное окно, вызывая CreateWindowHandle, который возвращает полученную ручку из ОС.
После этого, у нас есть действительное окно, способного обрабатывать сообщения, и CreateWnd делает окончательный уход, регулируя различные визуальные аспекты, такие как размер, шрифт и т.д.

Там также позже сделанный шаг по CreateHandle, после завершения CreateWnd, чтобы помочь VCL в управлении своими окнами (идентификация, происхождение, ...).