Symbian
Symbian OS Library

FAQ-0884 What is the correct way to create controls?

[Index][spacer] [Previous] [Next]



 

Classification: C++ Category: UIKON
Created: 06/23/2003 Modified: 07/14/2003
Number: FAQ-0884
Platform: Symbian OS v6.0, Symbian OS v6.1, Symbian OS v7.0, Symbian OS v7.0s

Question:
What pattern should I follow to ensure the correct creation of my UI controls?

Answer:
For each UI control:

1) Create the control object (e.g. iMyControl = new (ELeave) CMyNiftyControl;)
2) Set the control's container window (e.g. iMyControl->SetContainerWindowL(*this);)
3) Call second phase control construction (e.g. iMyControl->ConstructL();)

Each control should then in its second phase construction method (ConstructL() or ConstructFromResourceL()) repeat the steps above (if necessary) for any child controls.

4) Once the entire view is constructed, you should set the size of it. Never set the size of the child control(s) in the second phase construction method! When the control's size changes, a call is made to the control's SizeChanged() method. That's the method you should override for all controls that you create and do the layout of all that control's child controls. By setting the size of all child controls in the SizeChanged() method, layout changes will trickle down the entire control tree whenever a control higher up in the hierarchy has its size changed. Call the MinimumSize() method on the child(ren) to find the size they prefer.

5) Once the entire view has been constructed, and the size has been set, activate it for drawing by calling ActivateL() on it. Never call ActivateL() one control at a time, but call it on the top control when it's fully constructed. Child controls will then automatically be activated recursively.

When you code your own UI controls, try always to follow the pattern above. Avoid breaking the pattern by, for example, adding NewL() methods to your controls. It is recommended that you use NewL() and NewLC() methods for other classes, but avoid using them for CCoeControl derived ones. Strictly, the reason for this is that a CCoeControl that a has a NewL() method instead of a public constructor can't be added to a dialog, because the dialog framework relies on the control having a public constructor and a ConstructFromResourceL() method. You might argue it's still better to have a private c'tor and a NewL() method for controls that you know will never be added to a dialog, but we still strongly recommend that you ALWAYS use the pattern described above anyway!

Notes
a) Window-owning controls (i.e. CCoeControl classes that call CreateWindowL() in their ConstructL() method) do not require you to set their container window, but for consistency it is recommended that you always do that anyway. Previously (UIQ v2.0 and before), you had to know if the control you were about to create was window-owning or not, because calling SetContainerWindowL() on a window-owning control would cause a panic. But this is not the case from UIQ v2.1. The problem is that there is really no way to know (other than maybe finding the answer in the documentation or just trying to make the SetContainerWindowL() call to see if it panicked or not). Hence, the panic was removed; so for consistency, always follow the pattern above.

b) Make sure you never activate a control before it has been given it's size. A window owning control that is given its size AFTER it has been activated will cause the entire screen to blank and be redrawn.