Click here to Skip to main content
15,885,032 members
Articles / Desktop Programming / MFC

CResizableFormView

Rate me:
Please Sign up or sign in to vote.
3.50/5 (27 votes)
6 Jun 2001 188.1K   2.5K   45  
Extension of Paolo Messina's CResizableDialog concept
<h2>Introduction</h2>

<p>The inspiration for this coding project was the result of a) Paolo 
Messina's article on his CResizableDialog code, and b) me mentioning 
I had adapted a CFormView to use a CResizablePage in an embedded 
property sheet.

<p>The CResizablePage in a formview was a minor exercise compared to 
this.  What I've come up with is a CResizableFormView.  This code 
is based entirely on Paolo's CResizableDialog code.

<p>If you're not interested in how I did it, Skip to the bottom of 
this article to see how to implement it yourself.


<br>
<br>
<h2>The Concept</h2>

It seemed to me that if a dialog box could benefit from this 
technique, then so could a formview, because after all, a formview 
is nothing more than a view that acts like a dialog box.  It even 
uses a resource template like a dialog box.

<br>
<br>
<h2>Initially</h2>

The initial coding was fairly straightforward. I created a 
CFormView-derived class called CResizableFormView.  Next, I copied 
all of the utility functions (functions not contributed by 
ClassWizard).  Then, I evaluated the need/availablity of some of 
the windows messages Paolo's code was using. I ended up only 
needing to handle the WM_SIZE command.

Lastly, I decided that the min/max window size code was not applicable 
to a formview, so I deleted the code involving that particular aspect 
of CResizableDialog.

<br>
<br>
<h2>Implementation</h2>

After getting the code to compile, I tried deriving a new class 
based on my new CResizableFormView.  After some experimentation, I 
discovered that I could not use the AddAnchor function until AFTER 
the InitialUpdate had completed.  If I didn't follow this rule, 
the controls would not resize correctly.

<p>
<pre>
void CFormview2View::OnInitialUpdate()
{
	CResizableFormView::OnInitialUpdate();
	GetParentFrame()->RecalcLayout();
	ResizeParentToFit();

	// put our code AFTER the stuff ClassWizard gave us.
	AddAnchor(IDC_LIST1, TOP_LEFT, BOTTOM_RIGHT);
	AddAnchor(IDC_GROUP1, TOP_LEFT, BOTTOM_LEFT);
}
</pre>


<br>
<br>
<h2>Minor Issues</h2>

After playing around with re sizing for a while, I discovered that 
if I made the view window smaller than the original dialog 
template, a couple of bad things happened involving the controls 
that were "anchored".

<ul><li>
The listbox disappeared altogether and would only partially appear 
as I made the view horizontally larger.
</li></ul>

<ul><li>
The groupbox around the radio controls would just keep re sizing 
until nothing was left (of the groupbox).
</li></ul>

<p>It was obvious at that point that I had to include some code to 
restrict the controls from re sizing once they reached (or were 
smaller than) their original size.  I also assumed that I had to 
be mindful of getting the correct original size, meaning I had to 
determine each control's size before the window was allowed to be 
resized the first time. Assuming that the programmer could decide 
to do something other than use a call to MFC's ResizeParentToFit(), 
I had to make sure to get the control's info immediately after the 
view was created, but before it was resized.  I wanted to impact 
as little of Paolo's original code as I could manage, so the fix 
was a while coming.

<p>To remedy the situation, I created a CTypedPtrArray that held a 
new structure.  This structure contains the original size and 
location of each "anchored" control, as well as its HWND and 
control ID.  To support the structure, I had to also write a 
couple of new functions.  Here are the details:

<p>
<pre>
void CResizableFormView::AddResizedControls()
</pre>

<p>This function is responsible for determining the HWND and window 
size / location of the specified control, as well as storing its 
anchor positions.  The parameter list is identical to the original 
AddAnchor function.  Once all of this information was gathered, 
the control was added to the new CTypedPtrArray for safe-keeping.

<p>
<pre>
void CResizableFormView::AnchorControls()
</pre>

<p>This function actually calls AddAnchor() for all of the controls 
the programmer specified when he/she called the 
AddResizedControls() function.  The significance of this will be 
evident later.

<br>
<br>
<h2>Results</h2>

In order to implement the sizing/positioning fix, A new order of 
execution was required in the CResizableFormView-derived class. The 
OnInitialUpdate() function now looks like this:

<p>
<pre>
void CFormview2View::OnInitialUpdate()
{
	// jms - 11/28/00 - new code starts
	// We do this here because we need to get the *original* size of the 
	// controls *before* the dialog is sized the first time.  I don't know 
	// what will happen if we do it after, but I didn't want to find out.
	//
	// Since we do this here, I decided to pass the parameters needed by 
	// the AddAnchor() function to eliminate the need to call AddAnchor 
	// from this function (after the view had been resized).
	AddResizedControl(IDC_LIST1, TOP_LEFT, BOTTOM_RIGHT);
	AddResizedControl(IDC_GROUP1, TOP_LEFT, BOTTOM_LEFT);
	// jms - 11/28/00 - new code stops

	CResizableFormView::OnInitialUpdate();
	GetParentFrame()->RecalcLayout();
	ResizeParentToFit();

	// Normally, we would put the calls to AddAnchor AFTER we call 
	// ResizeParentToFit().
	//AddAnchor(IDC_LIST1, TOP_LEFT, BOTTOM_RIGHT);
	//AddAnchor(IDC_GROUP1, TOP_LEFT, BOTTOM_LEFT);

	// jms - 11/28/00 - new code starts
	// Now anchor the controls we specified earlier in this function. We call 
	// this function because it cycles thru the list of controls that are to 
	// be resized. This prevents us from having to call AddAnchor (lots of 
	// redundant typing at this point).
	AnchorControls();

}
</pre>


<br>
<br>
<a name="FinalWord">
<h2>The Final Word</h2>

<p>To implement the CResizableFormView preform the following steps:

<p>0) Create a CFormView class and its dialog template if necessary.

<p>1) Change the base class to CResizableFormView

<p>2) #include "ResizableFormView.h" in your derived formview's header file.

<p>3) If the function isn't already there, use ClassWizard to override the 
OnInitialUpdate() function.

<p>4) Call AddResizedControls() for each control that will be resized/repositione. 
Do this <b>BEFORE</b> the call to the base class' OnInitialUpdate().

<p>5) Call AnchorControls().  Do this <b>AFTER</b> the call to ResizeParentToFit();


<br>
<br>
<h2>About The Author</h2>

<p>John Simmons has been a programmer since 1982 and has experience in Pascal, and 
C++ (both self-taught). He's been writing DOS programs since 1984, and Windows 
programs since 1991 almost exclusively with Visual C++ and MFC.  He's written well 
over 2 million lines of code since 1989.



By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior) Paddedwall Software
United States United States
I've been paid as a programmer since 1982 with experience in Pascal, and C++ (both self-taught), and began writing Windows programs in 1991 using Visual C++ and MFC. In the 2nd half of 2007, I started writing C# Windows Forms and ASP.Net applications, and have since done WPF, Silverlight, WCF, web services, and Windows services.

My weakest point is that my moments of clarity are too brief to hold a meaningful conversation that requires more than 30 seconds to complete. Thankfully, grunts of agreement are all that is required to conduct most discussions without committing to any particular belief system.

Comments and Discussions