Por que você não deve usar um identificador durante a criação ou streaming de componente?

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

Pergunta

Eu quero fazer um controle VCL personalizado que envolve uma superfície de renderização SDL através da função SDL_CreateWindowFrom. SDL_CreateWindowFrom leva uma alça HWND existente e coloca um contexto processamento de alto desempenho (tem várias infra-estruturas disponíveis, incluindo DirectX e OpenGL) para ele.

O helpfile diz "não se referem à propriedade Handle durante a criação ou streaming de componente." Mas ele não diz porquê. Ele diz que a primeira vez que você tentar acessar a propriedade Handle, ele vai chamar HandleNeeded para garantir que existe um identificador válido.

Então, eu tenho duas perguntas. 1: O que é a razão pela qual você não deve fazer referência a propriedade Handle durante a criação do componente? 2. Se o ponto inteiro do controle é para embrulhar uma superfície de renderização que requer um HWND de ser inicializado, quando é seguro para realizar a inicialização que (idealmente) deve estar ocorrendo durante a criação / reprodução?

Foi útil?

Solução

No seu núcleo, que é uma coisa desempenho. Há potencialmente outros "maus" efeitos colaterais que podem acontecer também desde que durante o processo de streaming. As coisas estão em "meados de construção" e tudo o que é normalmente esperado para estar lá provavelmente não são.

Quando você faz referência a propriedade "Handle", este irá iniciar o processo de criação de alça. Isso ocorre porque Handle leitura realmente chama GetHandle. Faça isso muito cedo no processo de streaming, e você pode acabar com, no máximo, mais lento streaming de desempenho, na pior das hipóteses, um parcialmente configurado "pega".

Se você precisa para se referir ao tratar adequadamente a partir de um setter propriedade, você deve verificar se o identificador foi criado, verificando HandleAllocated, e só então você referenciá-lo. Se você precisava de fazer algumas mudanças bandeira para a alça como chamar SetWindowLong () ou algo assim, então você deve "cache" que estado na instância de componente e, em seguida, substituir CreateWnd e aplicar essas configurações nesse ponto. Outra opção é adiar todo o acesso punho durante a transmissão (se csLoading em ComponentState então) até que o método virtual Loaded é chamado.

Finalmente, você precisa estar ciente de casos em que o seu punho pode precisar de obter recriado. Isso pode acontecer se o formulário circundante ou o puxador do componente pai passa por um processo de recriar. Até mais recentes versões do Windows, a única maneira de mudar algumas bandeiras janela era destruir a alça e recriar com novas bandeiras na chamada CreateWindowEx (). Há muitos componentes que ainda fazem isso. Você sabe se você estiver em uma situação recriar verificando (csRecreating em ControlState).

Então, para responder diretamente a sua pergunta, o melhor lugar é substituir CreateWnd e fazer o seu trabalho lá. CreateWnd só será chamado quando a alça é criado. Um componente projetado corretamente deve receber apenas uma chamada para CreateWnd direita antes que vai ser mostrado.

Outras dicas

Para responder à sua segunda pergunta: Assumindo que o seu controle é uma TCustomControl você provavelmente deve substituir CreateWindowHandle () . Isto tem a vantagem de que toda a inicialização se repete corretamente cada vez que uma nova janela identificador é criado para o controle. Isto permite alterar alguns sinalizadores de estilo janela que não pode ser definido ou redefinido sem recriar a janela. Ele também permitem recursos de conserva, libertando a alça quando não é necessário, e recriá-lo mais tarde.

Veja também esta pergunta o que está-the-diferença, entre-createwnd-e -createwindowhandle e ainda mais as respostas detalhadas sobre o que fazer e quando ...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top