Question

Automatic resizing controls in a MFC CFormView

Asked by: sternocera

I'm following a tutorial for MFC/C++ that regards automatic resizing of elements in a formview. Essentially, I want to have a CFormView dialog with elements that occupy the entire screen, no matter what the desktop resolution is, and elements that move around as the window is resized. I've found a tutorial that covers this:

http://www.codeproject.com/docking/AutoResizingControls.asp

Everything is working, except when I resize the window. That is to say that no matter what my desktop resolution is, my form fully fills it. However, when I resize the window, the elements don't move around to accommodate the new size of the window. I suspect this is due to this (from the tutorial):

"The BPControlAnchorMap-mechanism was originally designed for dialogs where the dialog or parent-window and its controls, both have constant dimensions. A problem arises when you use the mechanism with CFormView. A CFormView resizes itself to fit into the area of the parent-window in which it is contained. Since this process happens before you can call InitAnchors(), the control-map will be empty and the controls will not be resized correctly.

A workaround for this is to use the flag ANIF_CALCSIZE when calling the InitAnchors-function. If you call InitAnchors(ANIF_CALCSIZE), then the InitAnchors-function will try to find the original size of the parent-window (your CFormView) by taking the bottom-right-most coordinate of all controls which are in the control-map."

I've used this ANIF_CALCSIZE argument, and everything works as described.

Here is my OnSize overloading function:

void CLustreView::OnSize(UINT nType, int cx, int cy)
{
      CFormView::OnSize(nType, cx, cy);
      CRect rcWnd;
      GetWindowRect(&rcWnd);
      HandleAnchors(NULL);
      Invalidate(false);
}

I haven't forgotten to #include <atltypes.h>, the code compiles, but the elements still won't accommodate the size of the window.

Please advise.

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2007-07-24 at 03:05:05ID22716514
Topics

C++ Programming Language

,

Windows Programming

,

Windows MFC Programming

Participating Experts
3
Points
0
Comments
21

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. CFormView parented by a CTabCtrl
    I am attempting to create a CTabCtrl and associate a CFormView with each tab to display various statistics. So far it all works fine, I can launch the app, which creates a CView view, the CView view then creates a CTabctrl control and the control creates each of the associat...
  2. The difference between MFC and OpenGL x , y coordinates
    This is Makoto from HK. I face a problem that the original point (0,0) in openGL is at the left bottom corner. But the original point in MFC is at the left top corner. Now I would like to use MFC function to get the mouse position for dragging objects drawn in OpenGL. How can...
  3. CFormView
    Please help How can I destroy the CFormView. Since I'm using this function but isn't working Void CSpSheet::OnFileClose() { CFormView::Destroywindow() }

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: itsmeandnobodyelsePosted on 2007-07-24 at 04:37:55ID: 19555062

I made a sample formview with some controls and resized it. The positions and shape of the controls actually do not change when resizing. It's only scrollbars that appear when making it smaller than the size defined in the resources.

I think the behavior is ok. You can't shrink controls properly as the font and image may not be shrinked with the same scale but in steps only. Hence text is either too small or would be cut or couldn't be read.

Does your view has a different behavior?

Regards, Alex

 

by: sternoceraPosted on 2007-07-24 at 04:45:46ID: 19555098

Alex,

Yes, my view behaves differently. I don't want the actually size of the elements to change - I want their positions to change. This would mean that the screen would be a lot more crowded on a lower resolution display, and more sparse on a higher resolution display. The position of the elements scales, not the elements themselves.

Anyone who's ever coded HTML will know what I mean by this.

Thanks,
Sternocera

 

by: itsmeandnobodyelsePosted on 2007-07-24 at 04:50:14ID: 19555124

>>>> If you call InitAnchors(ANIF_CALCSIZE), then the
>>>> InitAnchors-function will try to find the original size
>>>> of the parent-window (your CFormView)
If I interpret that text correctly the new calculation is not based on the new size but on the size defined in the dialog resource. If I am right  the ANIF_CALCSIZE is more suitable to get called in the OnInitialUpdate and wouldn't change anything if called in OnSize.

Regards, Alex

 

by: itsmeandnobodyelsePosted on 2007-07-24 at 05:06:40ID: 19555249

>>>> Anyone who's ever coded HTML will know what I mean by this.
Yes, that was my bad ;-)

>>>> Yes, my view behaves differently.
Hmmm, sizing on different resolutions is ok. I've done that recently. We kept the relative positions same and resized controls and images as well. For the latter we needed classified possible resolutions and loaded images per class. That was cause automatically resized pictures were rather bad especially if they have text inside. Another problem was fonts. We classified font sizes as well and changed to a true type font (to get more variance). Each possible resolution got appropriate fonts associated so that the texts were not clipped but have maximum size within their box.

Resizing a form window dynamically by the user is a completely different thing especially if you don't resize the controls. Then, your form must be dynamically scaled what really gives poor results for any text outside of controls (or in static controls), for images and for lines of boxes and frames.

Regards, Alex

 

by: sternoceraPosted on 2007-07-24 at 06:06:10ID: 19555674

I don't want to resize images or fonts. I'm happy to have fonts & images consistently the same size, I'd just like them to keep their *relative* position.

Pretty standard stuff.

Any idea why my overloaded OnSize function doesn't work?

 

by: sternoceraPosted on 2007-07-24 at 08:00:50ID: 19556742

Here is the OnSize function:

void CLustreView::OnSize(UINT nType, int cx, int cy)
{
      CFormView::OnSize(nType, cx, cy);
      CRect rcWnd;
      GetWindowRect(&rcWnd);
      HandleAnchors(NULL);
      Invalidate(false);
}

I should mention that I call the base class's OnSize function, and since my baseclass is a CFormView that is what's called.

This differs from the tutorial, where as in the tutorial CDialog's base class is called.

 

by: sternoceraPosted on 2007-07-24 at 08:02:36ID: 19556760

*I should have said that the CDialog base class is called. Whoops.

 

by: AndyAinscowPosted on 2007-07-24 at 08:28:10ID: 19557044

From help file about OnSize

nType
Specifies the type of resizing requested. This parameter can be one of the following values:

SIZE_MAXIMIZED   Window has been maximized.

SIZE_MINIMIZED   Window has been minimized.

SIZE_RESTORED   Window has been resized, but neither SIZE_MINIMIZED nor SIZE_MAXIMIZED applies.

SIZE_MAXHIDE   Message is sent to all pop-up windows when some other window is maximized.

SIZE_MAXSHOW   Message is sent to all pop-up windows when some other window has been restored to its former size.

cx
Specifies the new width of the client area.

cy
Specifies the new height of the client area.


so you are already given the actual size of the client area that you want to fill.


ps.  GetWindowRect gets the *window* rectangle - not necessarily the size of the client area.
pps. You don't even do anything with the window rect after you get it !

 

by: sternoceraPosted on 2007-07-24 at 08:30:42ID: 19557076

Sorry. I tried setting HandAnchors to NULL before, but changed it back. Now, the function is like this:

void CLustreView::OnSize(UINT nType, int cx, int cy)
{
      CFormView::OnSize(nType, cx, cy);
      CRect rcWnd;
      GetWindowRect(&rcWnd);
      HandleAnchors(&rcWnd);
      Invalidate(false);
}

 

by: AndyAinscowPosted on 2007-07-24 at 08:33:46ID: 19557107

repeat:  ps.  GetWindowRect gets the *window* rectangle - not necessarily the size of the client area.

Showing what is in HandleAnchors might be useful.

 

by: AndyAinscowPosted on 2007-07-24 at 08:37:41ID: 19557149

consider this.
Client rectangle - 0,0,300,300
Window rectangle - 500,500,820,820

How will you code behave?

 

by: sternoceraPosted on 2007-07-24 at 08:44:38ID: 19557215

This is HandleAnchors:
                             
 void HandleAnchors(RECT *pRect);
                             
#define BEGIN_ANCHOR_MAP(theclass) void theclass::HandleAnchors(RECT *pRect) { \
                                m_bpfxAnchorMap.HandleAnchors(pRect); \
                                }; \

Here is the non-class member HandleAnchors that is called in turn (it's a bit of a monolithic function):
  void HandleAnchors(RECT *pRectParent) {
 
    int             iCtrl = 0;
    TCtrlEntry      *pCtrl = NULL;
    FSIZE           szCtrl;
    BOOL            bChanged = FALSE;
    RECT            rcParent;
    HDWP            hDeferPos = NULL;
    WINDOWPLACEMENT wpl;
   
    if (pRectParent==NULL) {
   
      ::GetWindowRect(m_hWndParent, &rcParent);
      PreProcess(&rcParent);
   
    } else PreProcess(pRectParent);
   
    // handle the visibility of the sizing-grip if we have one
    if (m_hWndSizeGrip!=NULL) {
   
      wpl.length = sizeof(wpl);
      ::GetWindowPlacement(m_hWndParent, &wpl);
      if ((wpl.showCmd==SW_MAXIMIZE) && (::IsWindowVisible(m_hWndSizeGrip))) {
        ::ShowWindow(m_hWndSizeGrip, SW_HIDE);
      } else if (!::IsWindowVisible(m_hWndSizeGrip)) {
        ::ShowWindow(m_hWndSizeGrip, SW_SHOW);
      };
   
    };
   
    // handle child-controls
    hDeferPos = BeginDeferWindowPos(m_nCtrlCount);
 
    for (iCtrl=0; iCtrl < m_nCtrlCount; iCtrl++) {
   
      pCtrl = &m_Ctrl[iCtrl];
      if (pCtrl->hWnd==NULL) continue;
     
      // get the size of the control
      szCtrl.cx = pCtrl->rect.right-pCtrl->rect.left;
      szCtrl.cy = pCtrl->rect.bottom-pCtrl->rect.top;
     
      // we´ve nothing changed until now
      bChanged = FALSE;
     
      // handle docking
      if ((pCtrl->nFlags & ANF_DOCK_ALL)==ANF_DOCK_ALL) {
     
        SetFRect(&pCtrl->rect, 0, 0, m_rcClient.right, m_rcClient.bottom);
        bChanged = TRUE;
     
      } else if (pCtrl->nFlags & ANF_DOCK_TOP) {
     
        SetFRect(&pCtrl->rect, 0.0, 0.0, (double)m_rcClient.right, szCtrl.cy);
        bChanged = TRUE;
     
      } else if (pCtrl->nFlags & ANF_DOCK_BOTTOM) {
     
        SetFRect(&pCtrl->rect, 0, m_rcClient.bottom-szCtrl.cy, m_rcClient.right, m_rcClient.bottom);
        bChanged = TRUE;
     
      } else if (pCtrl->nFlags & ANF_DOCK_LEFT) {
     
        SetFRect(&pCtrl->rect, 0, 0, szCtrl.cx, m_rcClient.bottom);
        bChanged = TRUE;
     
      } else if (pCtrl->nFlags & ANF_DOCK_RIGHT) {
     
        SetFRect(&pCtrl->rect, m_rcClient.right-szCtrl.cx, 0, m_rcClient.right, m_rcClient.bottom);
        bChanged = TRUE;
     
      } else if (pCtrl->nFlags & ANF_DOCK_LEFT_EX) {
     
        SetFRect(&pCtrl->rect, 0, pCtrl->rect.top, szCtrl.cx, pCtrl->rect.bottom);
        bChanged = TRUE;
     
      } else if (pCtrl->nFlags & ANF_DOCK_RIGHT_EX) {
     
        SetFRect(&pCtrl->rect, pCtrl->rect.left, pCtrl->rect.top, m_rcClient.right, pCtrl->rect.bottom);
        bChanged = TRUE;
     
      } else if (pCtrl->nFlags & ANF_DOCK_TOP_EX) {
     
        SetFRect(&pCtrl->rect, pCtrl->rect.left, 0, pCtrl->rect.right, pCtrl->rect.bottom);
        bChanged = TRUE;
     
      } else if (pCtrl->nFlags & ANF_DOCK_BOTTOM_EX) {
     
        SetFRect(&pCtrl->rect, pCtrl->rect.left, pCtrl->rect.top, pCtrl->rect.right, m_rcClient.bottom);
        bChanged = TRUE;
     
        };
     
      // handle anchoring
      if ((m_uiSizedBorders & ANF_LEFTRIGHT) && (m_szDelta.cx!=0) && (!bChanged)) {
     
        switch(pCtrl->nFlags & ANF_LEFTRIGHT) {
       
          case ANF_LEFT         : // nothing to do here, control moves automatically
                                  // with the left-border of the window (client-rect)
                                  break;
         
          case ANF_RIGHT        : pCtrl->rect.left+=m_szDelta.cx;
                                  pCtrl->rect.right=(pCtrl->rect.left+szCtrl.cx);
                                  bChanged = TRUE;
                                  break;
         
          case ANF_LEFTRIGHT    : pCtrl->rect.right+=m_szDelta.cx;
                                  bChanged = TRUE;
                                  break;
         
          default               : pCtrl->rect.left+=((double)m_szDelta.cx/2.0);
                                  pCtrl->rect.right=(pCtrl->rect.left+szCtrl.cx);
                                  bChanged = TRUE;
                                  break;
       
        };
     
      };
     
      if ((m_uiSizedBorders & ANF_TOPBOTTOM) && (m_szDelta.cy!=0)) {
     
        switch(pCtrl->nFlags & ANF_TOPBOTTOM) {
       
            case ANF_TOP        : // nothing to do here, control moves automatically
                                  // with the top of the window (client-rect);
                                  break;  
           
            case ANF_BOTTOM     : pCtrl->rect.top+=m_szDelta.cy;
                                  pCtrl->rect.bottom=(pCtrl->rect.top+szCtrl.cy);
                                  bChanged = TRUE;
                                  break;
                                 
            case ANF_TOPBOTTOM  : pCtrl->rect.bottom+=m_szDelta.cy;
                                  bChanged = TRUE;
                                  break;

            default             : pCtrl->rect.top+=((double)m_szDelta.cy/2.0);
                                  pCtrl->rect.bottom=(pCtrl->rect.top+szCtrl.cy);
                                  bChanged = TRUE;
                                  break;
        };
     
      };

      // now reposition the control, if its size/position has changed        
      if (bChanged!=FALSE) {

        szCtrl.cx = pCtrl->rect.right-pCtrl->rect.left;
        szCtrl.cy = pCtrl->rect.bottom-pCtrl->rect.top;
        ::DeferWindowPos(hDeferPos, pCtrl->hWnd, NULL, (int)pCtrl->rect.left, (int)pCtrl->rect.top, (int)szCtrl.cx, (int)szCtrl.cy, SWP_NOZORDER | SWP_NOACTIVATE);

      };  
   
    };
   
    ::EndDeferWindowPos(hDeferPos);

    PostProcess();
   
  };

 

by: AndyAinscowPosted on 2007-07-24 at 09:00:26ID: 19557441

I'd advise you to study that function and look up what each function it calls is doing.  A lot of the code isn't very suitable for use in a view.


(I don't like explaining every last detail - it is better in the long run to work out oneself what the code does.  You learn more.)

 

by: sternoceraPosted on 2007-07-25 at 01:36:51ID: 19563613

Andy,

That is reasonable. I didn't actually expect you to go through all that code and get back to me with the answer....You're not my employee.

The only reason I pasted the function was because you asked me to.

I'll look into it,

Thanks

 

by: AndyAinscowPosted on 2007-07-25 at 01:55:37ID: 19563712

From my side I asked you to post the function so that the experts here can look at it.  Maybe it was just a few lines of code with an obvious problem.


ps.  If you took offence then that was not my intention at all.  I've developed a nasty cold and am not at my best at present.

 

by: sternoceraPosted on 2007-07-25 at 01:57:55ID: 19563723

Andy,

No, not at all. You've been very reasonable, and very helpful. I havn't taken offence. What I said wasn't sarcasm or anything,

Thanks

 

by: itsmeandnobodyelsePosted on 2007-07-25 at 03:27:03ID: 19564068

>>>> I asked you to post the function so that the experts here can look at it.  
I looked at the above function and I would like to know the flags the (anchor) controls were created with. As far as I see the only changes of positions is made if the 'm_rcClient' rectangle had changed prior to calling that function. That seems to be a class member representing the client window of the formview in your case, which I don't know whether it was set correctly (or at all) in case of an update. If not, that could be a reasonable explanation why resizing failed.

Note, the m_rcClient was used for positioning for flags ANF_DOCK_ALL, ANF_DOCK_LEFT, ANF_DOCK_TOP, ANF_DOCK_RIGHT and ANF_DOCK_BOTTOM but not for the flags with suffix _EX.

>>>> A lot of the code isn't very suitable for use in a view.
It doesn't seem to me that the function makes things which were not senseful in a view - beside you would decline buttons in a view at all ...

The only thing what isn't considered is that the view form was adapted to the frame hence was different than it would have been in a dialog which gets its initial size from resource only. You could change that by adopting the frame to the view prior to calling ResizeParentToFit. But never forget to set the m_rcClient member after each change.

Regards, Alex


 

by: sternoceraPosted on 2007-07-25 at 03:46:12ID: 19564154

I did a simple test.

I amended this to my OnSize function:
AfxMessageBox ("You have resized your window");

I never see this message box. The function is never called.

Your thoughts?

 

by: sternoceraPosted on 2007-07-25 at 04:38:31ID: 19564387

Guys,

I forgot to include ON_WM_SIZE() in my message map. That was all. I once again find myself feeling stupid and grateful,

Regards

 

by: ee_autoPosted on 2009-09-17 at 01:18:49ID: 25353778

Question PAQ'd, 500 points refunded, and stored in the solution database.

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...