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

StackOverflow https://stackoverflow.com/questions/582721

Вопрос

Я хочу создать пользовательский элемент управления VCL, который оборачивает поверхность рендеринга SDL с помощью функции SDL_CreateWindowFrom.SDL_CreateWindowFrom берет существующий дескриптор HWND и помещает в него высокопроизводительный контекст рендеринга (в нем доступно несколько бэкэндов, включая DirectX и OpenGL).

В файле справки указано "Не ссылаться на свойство Handle во время создания компонента или потоковой передачи". Но не указано, почему.В нем говорится, что при первой попытке доступа к свойству Handle оно вызовет HandleNeeded, чтобы убедиться в существовании допустимого дескриптора.

Итак, у меня есть два вопроса.1:В чем причина, по которой вы не должны ссылаться на свойство Handle при создании компонента?2.Если весь смысл элемента управления заключается в том, чтобы обернуть поверхность рендеринга, для которой требуется инициализация HWND, когда безопасно выполнять инициализацию, которая (в идеале) должна выполняться во время создания / потоковой передачи?

Это было полезно?

Решение

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

Когда вы ссылаетесь на свойство "Handle", это инициирует процесс создания дескриптора.Это происходит потому, что дескриптор чтения на самом деле вызывает GetHandle .Сделайте это слишком рано в процессе потоковой передачи, и в лучшем случае вы можете столкнуться с более низкой производительностью потоковой передачи, в худшем - с частично настроенным "дескриптором".

Если вам нужно правильно ссылаться на дескриптор из средства установки свойств, вы должны проверить, был ли дескриптор создан, установив флажок HandleAllocated , и только после этого ссылаться на него.Если вам нужно внести некоторые изменения флага в дескриптор, например, вызвать SetWindowLong() или что-то в этом роде, то вам следует "кэшировать" это состояние в экземпляре компонента, а затем переопределить CreateWnd и применить эти настройки в этот момент.Другой вариант - отложить весь доступ к дескриптору во время потоковой передачи (если тогда csLoading в ComponentState) до тех пор, пока не будет вызван загруженный виртуальный метод.

Наконец, вы должны быть осведомлены о случаях, когда вашему дескриптору может потребоваться воссоздание.Это может произойти, если окружающая форма или дескриптор родительского компонента проходит через процесс воссоздания.Вплоть до более поздних выпусков Windows единственным способом изменить некоторые флаги окна было уничтожение дескриптора и воссоздание с новыми флагами в вызове CreateWindowEx().Есть много компонентов, которые все еще делают это.Вы узнаете, находитесь ли вы в ситуации воссоздания, проверив (csRecreating в ControlState).

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

Другие советы

Чтобы ответить на ваш второй вопрос:Предполагая, что ваш контроль - это TCustomControl ( Пользовательский контроль ) вероятно, вам следует переопределить CreateWindowHandle() Создать оконный дескриптор().Преимущество этого заключается в том, что вся инициализация корректно повторяется каждый раз, когда для элемента управления создается новый дескриптор окна.Это позволяет изменить некоторые флаги стиля окна, которые нельзя установить или сбросить без повторного создания окна.Это также позволяет экономить ресурсы, освобождая дескриптор, когда он не нужен, и создавая его заново позже.

Смотрите также этот вопрос в чем разница между createwnd и createwindowhandle и еще более подробные ответы о том, что делать и когда...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top