В чем разница между CreateWnd и CreateWindowHandle? - PullRequest
22 голосов
/ 24 февраля 2009

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

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

Ответы [ 4 ]

39 голосов
/ 25 февраля 2009

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

CreateParams ();

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

CreateWnd ();

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

CreateWindowHandle ();

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

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

4 голосов
/ 24 февраля 2009

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

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

2 голосов
/ 24 февраля 2009

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

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

0 голосов
/ 24 февраля 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...