Why shouldn't you use a handle during component creation or streaming?

别等时光非礼了梦想. 提交于 2020-01-01 12:08:30

问题


I want to make a custom VCL control that wraps a SDL rendering surface via the SDL_CreateWindowFrom function. SDL_CreateWindowFrom takes an existing HWND handle and puts a high-performance rendering context (it has several backends available, including DirectX and OpenGL) onto it.

The helpfile says "Do not refer to the Handle property during component creation or streaming." But it doesn't say why. It says that the first time you try to access the Handle property, it'll call HandleNeeded to ensure that a valid handle exists.

So I have two questions. 1: What's the reason why you shouldn't reference the Handle property during component creation? 2. If the entire point of the control is to wrap a rendering surface that requires a HWND to be initialized, when is it safe to perform the initialization that (ideally) ought to be taking place during creation/streaming?


回答1:


At it's core, it's a performance thing. There are potentially other "bad" side-effects that can happen as well since during the streaming process. Things are in "mid-construction" and all that is normally expected to be there are probably not.

When you reference the "Handle" property, this will initiate the handle creation process. This is because reading Handle actually calls GetHandle. Do this too soon in the streaming process, and you may end up with, at best, slower streaming performance, at worse, a partially configured "handle."

If you need to refer to the Handle properly from within a property setter, you should check if the handle has been created by checking HandleAllocated, and only then do you reference it. If you needed to make some flag changes to the handle like calling SetWindowLong() or something, then you should "cache" that state in the component instance and then override CreateWnd and apply those settings at that point. Another option is to defer all handle access while streaming (if csLoading in ComponentState then) until the Loaded virtual method is called.

Finally, you need to be aware of cases where your handle may need to get recreated. This can happen if the surrounding form or the parent component's handle goes through a recreate process. Up until more recent releases of Windows, the only way to change some window flags was to destroy the handle and recreate with new flags in the CreateWindowEx() call. There are many components that still do this. You know if you're in a recreate situation by checking (csRecreating in ControlState).

So to directly answer your question, the best place is to override CreateWnd and do your work in there. CreateWnd will only be called when the handle gets created. A properly designed component should get only one call to CreateWnd right before it is going to be shown.




回答2:


To answer your second question: Assuming your control is a TCustomControl you should probably override CreateWindowHandle(). This has the benefit that all initialization is correctly repeated every time a new window handle is created for the control. This allows to change some window style flags that can not be set or reset without recreating the window. It does also allow to conserve resources by freeing the handle when it is not needed, and recreating it later.




回答3:


See also this question whats-the-difference-between-createwnd-and-createwindowhandle and even more the detailed answers on what to do and when...



来源:https://stackoverflow.com/questions/582721/why-shouldnt-you-use-a-handle-during-component-creation-or-streaming

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!