I have a custom control which needs to get access to the height of the main form it is on. Since it is common for this control to be nested in a series of panels, I have written this code to try and get me to the main form:
TControl * control = this;
while( control->HasParent() )
{
control = control->ParentControl;
ShowMessage( control->Name );
}
Using the ShowMessage
statement to track my progress, as I step through the code I get all the way up to "BasePanel" which in this case is the last control up the ladder before the "MainForm." However, when the call to ShowMessage
happens for what should be the "MainForm" I get an access violation.
Is there some reason I am unable to access the main form of a control this way? Is there a better way to access a control's main form?
You are not checking if ParentControl
returns a NULL pointer before reading its Name
. When HasParent()
returns true, ParentControl
is NOT guaranteed to be valid. Case in point - TForm
is NOT a TControl
descendant in FireMonkey, so it cannot be returned by ParentControl
.
The purpose of HasParent()
is to report whether the component has a parent or not. TFmxObject
overrides HasParent()
to report whether the TFmxObject.Parent
property is NULL, and overrides GetParentComponent()
to return an appropriate TComponent
for that parent. TFmxObject.Parent
returns a TFmxObject
, as parent/child relationships do not have to be visual in FireMonkey like they do in VCL, so Parent
and GetParentComponent()
can actually return different objects at times.
You should be using GetParentComponent()
instead of ParentControl
, as the documentation says:
Call HasParent to determine whether a specific component has a parent.
Derived classes override this method to implement proper handling for parenting.
Use GetParentComponent to retrieve the component reference.
For example:
TComponent * comp = this;
while( comp->HasParent() )
{
comp = comp->GetParentComponent();
ShowMessage( comp->Name );
}
However, if your intent is to find the parent TForm
specifically, use your control's Root
property instead:
TCommonCustomForm *form = dynamic_cast<TCommonCustomForm*>(this->Root->GetObject());