Binding the Resizing Behavior of Dialog and Control

Environment: Visual C++ 6.0

Using a resizable dialog is a great way to make a dialog behave like a traditional window, but sometimes there's a need to have a control resize along with the dialog, particularily when you're attempting to use the control as a psuedo-document view. Here's one solution on how to make the control's resizing behavior follow that of the dialog's. Because dialogs and controls inherit from CWnd, we'll use that knowledge to our advantage in order to attain the desired behavior. We'll hook into the dialog's WM_SIZE message, override the default message handler, and pass the dialog's updated size information on to the control. With this information we can then resize the control to completely fill the dialog client area, ensuring that the control will always fill the dialog client area regardless of the dialog size or what method was used to resize it.

Warning: This example is not intended for dialogs that contain multiple controls. While some of the steps of this example may apply to a solution for controlling the positioning of multiple controls in a dialog, that subject is beyond the scope of this example.

Step One: First, we'll need to set up our example by creating a resizable dialog that contains one control. In keeping with the theme of a psuedo-document view, we'll use the CEditBox control for our example. Fire up VC++ and create a new Dialog based App Wizard (.exe) project. Name it "Example". Remove all of the controls from the dialog (buttons and static text). Right click on the dialog and set the properties to include the following - Style: overlapping, Border: resizing, System Menu, Minimize/Maximize box, and ensure that Visible is checked. Now place a CEditBox control on the dialog form. Resize the CEditBox control so that it covers the entire dialog form. Right click on the control and set the properties to include the following - Multiline, Visible, Auto HScroll, and AutoVScroll. Now that we have all the things in place that are needed to explore a solution, let's test what we have so far. Execute the program and resize the dialog by dragging it's border, and by using the maximize and restore buttons. The dialog resizes as a typical window should. But the CEditBox control always remains the same size and in a fixed position. Let's fix this behavior to match that of the dialog's.

Step Two: We need a way of manipulating the CEditBox control's size attributes at runtime, so let's set up a control member variable. Open Class Wizard and select the Member Variables tab. Make sure CExampleDlg is the current class. Click on your control's ID. If you can't remember what it was, you'll be able to find it in the CEditBox control's properties (see Step One). Now click Add Variable. When the dialog box appears, ensure that the category is "control". Finally, name your control variable "m_editbox" and click OK to add the variable. Click OK to close the Class Wizard.

Step Three: Next, we need a way to let the CEditBox control know that the dialog has been resized and that it needs to resize itself, too. We'll do this by overriding the default message handler of the dialog's OnSize message. This method is called whenever the dialog is resized, and this is exactly where we want to implement our new control behavior. In the developer studio, go to Class View and right click on the CExampleDlg class. Select Add Windows Message Handler. When the dialog box appears, select WM_SIZE and make sure the Class or Object to handle is set to CExampleDlg. Click Add and Edit.

Step Four: The last thing we need to do before re-testing our example is to add the code for the desired behavior to our message handler.

void CExampleDlg::OnSize(UINT nType, int cx, int cy) 
{
 CDialog::OnSize(nType, cx, cy);

 // TODO: Add your message handler code here

 // ADD THE FOLLOWING CODE

 CRect rect;                               	
 GetWindowRect(&rect);	
 m_editbox.SetWindowPos(&m_editbox, 
                        0, 0, 
                        rect.right, 
                        rect.bottom, 
                        SWP_NOZORDER | SWP_SHOWWINDOW); 	      
}

Step Five: Execute the program. Resize the dialog.

Let's take a closer look at the code and see how it works:

// call the default message handler
CDialog::OnSize(nType, cx, cy);	

// create an instance of the CRect object
CRect rect;

// store the dialog's new size information in the object
GetWindowRect(&rect);

// set the control size to match the dialog client area size
m_editbox.SetWindowPos(&m_editbox, 
                       0, 0, 
                       rect.right, 
                       rect.bottom, 
                       SWP_NOZORDER | SWP_SHOWWINDOW);

Note: the SWP_NOZORDER flag must be included or the control will not resize. The flag causes the first parameter of SetWindowPos to be ignored and retains the current z-order of the window. In the example the first parameter is a reference to m_editbox, but this parameter can be any valid pointer to CWnd or a class that inherits from it.



Comments

  • Border: resizing

    Posted by Legacy on 10/30/2002 12:00am

    Originally posted by: Leonid

    I'm using my dialog resource template for several dialogs.
    Because of this I don't want to change border style in template, but in program code. Is this possible? What must I do?
    Thank you very much.

    Reply
  • HWnd in FormView

    Posted by Legacy on 09/29/2002 12:00am

    Originally posted by: Mada

    I can't get the Handle for my CListCtrl in the FormView.
    So i Can't use SetWindowPos.
    Any Comment's?

    Reply
  • Error: Makes control too big

    Posted by Legacy on 08/23/2001 12:00am

    Originally posted by: John Dwyer

    This example actually resizes the control bigger than the dialog box.  This is because GetWindowRect() returns screen coordinates, but SetWindowPos() uses client coordinates.
    
    

    This snippet of code switches dialog rect to client coordinates for the contained control
    .....
    CRect rect;
    CRect clientRect;

    CDialog::OnSize(nType, cx, cy);

    GetWindowRect(&rect);

    clientRect.top = 0;
    clientRect.left = 0;
    clientRect.right = rect.right - rect.left;
    clientRect.bottom = rect.bottom - rect.top;
    m_editRich.SetWindowPos(&m_editRich, 0, 0, clientRect.right,
    clientRect.bottom, SWP_NOZORDER | SWP_SHOWWINDOW);
    ....

    Reply
  • There is an easier way...

    Posted by Legacy on 07/30/2001 12:00am

    Originally posted by: Lee

    A long piece of text, L.D.Nelson, for not doing a lot. 
    
    I find the following works just as well and is easier to addapt for multiple controls.

    void CExampleDlg::OnSize(UINT nType, int cx, int cy)
    {
    CDialog::OnSize(nType, cx, cy);

    // TODO: Add your message handler code here
    m_editbox.MoveWindow, 0, 0, cx, cy);
    }

    Reply
  • Problem in FormView

    Posted by Legacy on 07/05/2001 12:00am

    Originally posted by: Selvaraj

    Hi

    Nice Work. Please let me know modifications if i use CFormView.

    Thanks
    Selva

    Reply
  • Maximize

    Posted by Legacy on 05/04/2001 12:00am

    Originally posted by: Nuno Rapaz

    How can i maximize all the interior of the dialog wnd when i push (i don�t know if i can say this in english)the maximize button

    Reply
  • Problem in first step

    Posted by Legacy on 04/10/2001 12:00am

    Originally posted by: Zoltan Csizmadia

    Sometimes you cannot cover the dialog with the control in
    the resource editor!

    void CYourDialog::FitControlToClientArea()
    {
    CRect rect;
    GetClientRect(&rect);

    if ( m_editbox.GetSafeHwnd() != NULL )
    m_editbox.MoveWindow(&rect);
    }

    BOOL CYourDialog::OnInitDialog()
    {
    CDialog::OnInitDialog();
    ...
    FitControlToClientArea();
    }

    void CYourDialog::OnSize(...)
    {
    CDialog::OnSize(...);

    FitControlToClientArea();
    }

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: October 29, 2014 It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this webcast, Gene Kim discusses these survey findings and shares woeful tales of artifact management gone wrong! Gene also shares examples of how high-performing DevOps …

  • On-demand Event Event Date: December 18, 2014 The Internet of Things (IoT) incorporates physical devices into business processes using predictive analytics. While it relies heavily on existing Internet technologies, it differs by including physical devices, specialized protocols, physical analytics, and a unique partner network. To capture the real business value of IoT, the industry must move beyond customized projects to general patterns and platforms. Check out this webcast and join industry experts as …

Most Popular Programming Stories

More for Developers

RSS Feeds