В чем разница между CreateWnd и CreateWindowHandle?

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

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

Ответов (4)

Решение

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

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 ().

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

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

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

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

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

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

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