Total Pageviews

Monday, May 10, 2010

Lesson 1 - Dynamically resizing controls in a CFormView

Dynamically resizing controls in a CFormView

If you've written an MFC application with the view based on the CFormView class and you have allowed uses to resize the application window to their taste, you may also wish to dynamically resize some of the controls that are part of the dialog template as the user resizes the window. This is how you do it:

Declare the following variables in the protected section of the header of your CFormView class:

long m_lWidth;
long m_lHeight;
CPoint topleft;

Now create a function called something like GetDimensions() and call it from the OnInitialUpdate()event in your CFormView.

void CMyClassView::OnInitialUpdate()
{

//...any other code that MFC App wizard or you have inserted...

GetDimensions();

}

The code for GetDimensions() should be something like this:

void CMyClassView::GetDimensions()
{

// this function gets the default dimensions of the
// form and an edit control on the form
// and calculates the ratios for resizing them.
// The calculation works like this:
// Get the differences between the widths and heights
// of form and edit box
// when the form is resized, calculate the new dimensions
// of the edit box by subtracting these differences from
// the NEW width and height of the FORM and apply these
// to the EDIT control

// get dimensions of form to CRect
CRect formRect;
CServStat2000View::GetWindowRect(&formRect);

// get a pointer to the edit control
CWnd* pEdit = GetDlgItem(IDC_EDIT2);

// get the dimensions of the edit control
CRect editRect; pEdit->GetWindowRect(&editRect);

// get CPoint co-ords for top left of edit box.
// these co-ords are used in MoveWindow to fix the
// anchor point of the top left of the edit box
topleft = editRect.TopLeft();

// convert the dimensions to values which
// match those returned for the form
ScreenToClient(&topleft);

// calculate difference between form width and edit box width
float fWidth = (float)formRect.Width()-(float)editRect.Width();

// calculate difference between form height and edit box height
float fHeight = (float)formRect.Height()-(float)editRect.Height();

// transfer values to long member variables
m_lWidth = (long) fWidth;
m_lHeight = (long) fHeight;

}

Now use the Class Wizard to insert an OnSize event handler into your CFormView. Adapt the following code inside the OnSize event handler.

// called when window is resized
void CMyClassView::OnSize(UINT nType, int cx, int cy)
{

// default action must be done first
CDaoRecordView::OnSize(nType, cx, cy);

// TODO: Add your message handler code here

// see GetDimensions() for explanation of
// how dims are calculated

// get new dimensions of form to CRect
CRect formRect; CMyClassView::GetWindowRect(&formRect);

// get pointer to the control to be resized
CWnd* pEdit = GetDlgItem(IDC_EDIT2);

// calculate new edit box width
float newWidth = (float)formRect.Width() - m_lWidth;

// calculate new edit box height
float newHeight = (float)formRect.Height() - m_lHeight;

// resize window
pEdit->MoveWindow(topleft.x, topleft.y, (long)newWidth, (long)newHeight, TRUE);

// repaint control
pEdit->RedrawWindow();

}

Now when you resize the application window, the edit control will be resized as well.

NOTE - the key feature is how you calculate the new size of the control. This code is for an edit control that sits at the bottom of the application window and fills it from left margin to right. When the application window is resized, the control's bottom and right hand edges "follow" the bottom and right hand edges of the window. If you have other controls on your form which are not resized or repositioned, a control that resizes itself may overlap them and spoil the look and functioning of the form. Try to plan the layout of your form and work out which controls you will be wanting to resize. Then position them in such a way that they don't interefere with one another nor with controls that are not resized dynamically.

No comments:

Post a Comment