Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The control 'xxx' has no parent window

Tags:

dll

delphi

tframe

I'm was trying to write a dll library in Delphi wih a function that creates an instance of a TFrame descendant and returns it. But when I imported this function in an application, every time I called it I would get an exception like "the 'xxx' control has no parent window". I'm not 100% sure, but the exception appeared in the constructor of that class when any of GUI controls was accessed.

Could you please tell me what the reason of that behaviour is? Should I just use TForm descendants instead or is there a better solution?

Thank you!

like image 387
Mariusz Schimke Avatar asked Sep 23 '10 06:09

Mariusz Schimke


2 Answers

About the error

That error message is raised from the Controls.pas unit, from the TWinControl.CreateWnd method. Essentially that code is used to create the Window handle for your TWinControl descendant (TFrame, TButton, TEdit... if it can have keyboard focus it's an TWinControl descendant), and it's actually an very sensible error message: You can't have a Window without an WindowParent, and since we're talking about the VCL here, it makes a lot of sense to try and get the parent window handle from TWinControl.Parent; And that's not assigned.

That's not WHY the error message is popping up. You get to see that error message because some of the code you're using to set up the frame requires an Window handle for some operation. It could be anything, like setting the Caption of some component (that internally requires an window handle do to some calculation). I personally really hate it when that happens. When I create GUI's from code I try to delay the assignment of Parent as much as possible, in an attempt to delay the creation of the window, so I got bitten by this many times.

Specific to your DLL usage, possible fix

I'm going to put my psycho mind reader hat on. Since you need to return a FRAME from your DLL, and you can't return the actual Frame because that's an Delphi-specific object and you're not allowed to return Delphi-specific objects over DLL boundaries, my guess is you're returning an Window Handle, as all the nice API's do, using a function definition like this:

function GiveMeTheNiceFrame:HWND;

The trouble is, that routine requires the creation of the actual Window Handle, by a call to TWinControl.CreateWnd, and in turn that call requires an parent window handle to set up the call to Windows.CreateWindowEx, and the routine can't get an parent window handle, so it errors out.

Try replacing your function with something allong the lines of:

function GiveMeTheNiceFrame(OwnerWindow:HWND):HWND;
begin
  Result := TMyNiceFrame.CreateParanted(OwnerWindow).Handle;
end;

... ie: use the CreateParented(AParentWindow:HWND) constructor, not the usual Create(AOwner:TComponent) and pass an owner HWND to your DLL.

like image 126
Cosmin Prund Avatar answered Nov 02 '22 09:11

Cosmin Prund


There are a few important things to remember:

  1. When using DLLs, both your DLL and your EXE each have an Application instance that are struggling for control. The Controls in your DLL will see the Application instance that belongs to the DLL; the Controls in your EXE will see the Application instance that belongs to the EXE. That struggle is not there when using packages, as then there will only be one Application instance.
  2. Frames are Controls, but they are not Forms.
  3. When using Controls in an application, they cannot visually exist without a parent Control (usually a Form or a container that has a parent hierarchy towards a Form).
  4. Some Controls cannot expose their full functionality unless they exist visually and have a valid parent.

Try to reproduce your problem inside the EXE; if you cannot reproduce, it is probably the first thing in the above list.

--jeroen

like image 36
Jeroen Wiert Pluimers Avatar answered Nov 02 '22 09:11

Jeroen Wiert Pluimers