CreateWindowHandle/CreateWnd are VCL Wincontrol routines that can be overwritten to take action that needs to happen when the WindowHandle of a control gets (re)created. There are corresponding routines DestroyWindowHandle/DestroyWnd, but these routines are only called when the control is recreated and not when it is destroyed. It appears that this is known, see for example here and here.
I came across this issue because I wanted to do the following when a contol's handle was created:
RegisterDragDrop (Handle, DropTarget);
and this has to be matched by:
RevokeDragDrop(Handle);
at handle destruction. Initially I placed the first statement in an overwritten CreateWindowHandle and the second in DestroyWindowHandle. This resulted in memory leaks and I began to investigate. Here are the results of the investigation that I wanted to share with you in case you face the same issue.
1. DestroyWnd is only called when recreating the control (not at control destruction). It also calls DestroyWindowHandle. This is documented in the help file.
2, DestroyWindowHandle is called by DestroyWnd and separately by TWinControl.Destroy if WindowHandle <>0.
So it looks like my solution should work, however, when the control is a child of a TCustomForm and the form gets destroyed (almost always the case), TCustomForm.Destroy calls DestroyWindowHandle before destroying child objects and Windows, before destroying a control's handle, it first destroys the window handles of all child objects. So the DestroyWindowHandle of the child controls will not be called! WindowHandle = 0 inside TWinControl.Destroy. The choices you have for taking action before handle destruction are:
3. WM_DESTROY handler. It is called by windows before destroying the window handle of child controls.
4 WM_NCDESTROY handler. It is called by windows after destroying the window handle of child controls and before destroying the control's window handle.
I ended up putting RevokeDragDrop inside the WM_DESTROY handler, since this is called in all cases the window handle gets destroyed.
Although not a bug, this looks like bad VCL design to me and can be the source of many bugs.