Introduction
Many Windows applications specify absolute position and absolute sizes when they lay out controls in the parent window. This strategy has some drawbacks: The created windows cannot be resized, changes are difficult and creation of good looking windows is time consuming.
Another way which is very common in cross platform frameworks (wxWidgets, QT, Java …) is to use layout algorithm. A layout algorithm determines the size and position of its controls based on its policy. Although every control can provide its preferences about its size, position and alignment, the layout algorithm can ignore these preferences if they are against its layout policy.
Using the Code
What is a Planner?
A planner implements a layout algorithm. Controls can be added to it with their preferences about their size, position and alignment with the Add
method while the SetControl
method sets their parent control. The Layout
method is used to lay out the controls.
class Planner {
public:
virtual void Layout() = 0;
virtual void SetControl(const Control& item) = 0;
virtual void AddControl(const Control& item,int factor,int style) = 0;
...
};
What is BoxPlanner?
A BoxPlanner
allows laying out controls in a row or in a column. A BoxPlanner
has a main direction: Horizontal (psHorizontal
-to lay out controls in a row) and Vertical ( psVertical
- to lay out controls in a column). The main direction can be given in the construction or by using SetDirection
method. The other direction will be the secondary direction.
When control is added to the planner
– it can specify its factor and style.
- The factor is a hint to the
planner
how to size the control in the main direction. If the factor is 0 – its desired size in the main direction will be used. Otherwise, its size in the main direction will be factor unit (factor unit - free space in the main direction divided by the sum of all controls factor).
- In the secondary direction, the control can specify that it wants all available space (
psGrowAll
) or wants use its desired size in the secondary direction and to be aligned to window -- psAlignLeft
,psAlignCenter
, psAlignRight
for horizontal direction or psAlignTop
, psAlignMiddle
, psAlignBottom
).
Demo for BoxPlanner?
In window creation, we create the controls and add them to BoxPlanner
instance:
LRESULT OnCreate ( LPCREATESTRUCT lpcs ) {
button1.Create(m_hWnd,CRect(0,0,100,50),_T("button 1"),WS_CHILD | WS_VISIBLE);
button2.Create(m_hWnd,CRect(0,0,100,40),_T("button 2"),WS_CHILD | WS_VISIBLE);
button3.Create(m_hWnd,CRect(0,0,100,40),_T("button 3"),WS_CHILD | WS_VISIBLE);
button4.Create(m_hWnd,CRect(0,0,100,40),_T("button 4"),WS_CHILD | WS_VISIBLE);
button5.Create(m_hWnd,CRect(0,0,100,50),_T("button 5"),WS_CHILD | WS_VISIBLE);
planner.AddControl(Control(button1.m_hWnd),2,Planner::psAlignLeft );
planner.AddControl(Control(button2.m_hWnd),2,Planner::psAlignRight );
planner.AddControl(Control(button3.m_hWnd),5,Planner::psGrowAll );
planner.AddControl(Spacer(10,10),2,Planner::psGrowAll );
planner.AddControl(Control(button4.m_hWnd),2,Planner::psGrowAll );
planner.AddControl(Spacer(10,10),0,Planner::psGrowAll );
planner.AddControl(Control(button5.m_hWnd),2,Planner::psGrowAll );
planner.SetControl(Control(m_hWnd));
SetMsgHandled(false);
return 0;
}
Now when on size event, we call the Layout
method:
void OnSize(UINT nType, CSize size) {
planner.Layout();
}
History
- 19th March, 2009: Initial post