Click here to Skip to main content
15,885,244 members
Articles / Programming Languages / C#

Drop-dead easy layout management

,
Rate me:
Please Sign up or sign in to vote.
4.33/5 (15 votes)
3 Sep 2006CPOL2 min read 100.1K   2.2K   63  
Flexible control repositioning and resizing with an easy-to-use layout manager.
using System;
using System.Collections;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

namespace RavSoft
{
  /// <summary>
  /// An object that allows you to easily resize and reposition
  /// controls with the size of their container changes.  This version
  /// contains an improvement (provided by Eddie Zhou) that allows
  /// controls to be scaled in proportion to the change in the parent
  /// form's dimensions.
  /// </summary>
  /// <remarks>
  /// Copyright (c) 2006 Ravi Bhavnani (ravib@ravib.com) and
  ///                    Eddie Zhou (qingzhou100@yahoo.com)
  ///
  ///  You are allowed to include this source code in any product (commercial, shareware,
  ///  freeware or otherwise) when your product is released in binary form.  You are allowed
  ///  to modify the source code in any way you want except you cannot modify the copyright
  ///  details at the top of each module.  If you want to distribute source code with your
  ///  application, then you are only allowed to distribute versions released by the author.
  ///  This is to maintain a single distribution point for the source code.
  /// </remarks>
  public class LayoutManager
  {
    #region Properties

      /// <summary>
      /// Gets the LayoutManager's collection of items.
      /// </summary>
      public ArrayList Items {
        get {
          return m_items;
        }
      }

    #endregion

    #region Operations

      /// <summary>
      /// Initializes the layout manager.
      /// </summary>
      /// <param name="container">Container control.</param>
      public void init
        (Control container)
      {
        // Cache the operating context and initial dimensions
        m_container = container;
        m_nWidth = container.Width;
        m_nHeight = container.Height;
      }

      /// <summary>
      /// Aligns the items under the layout manager's control.
      /// </summary>
      public void alignItems()
      {
        // Ignore action if container has been minimized
        if (m_container is Form) {
            Form f = m_container as Form;
            if (f.WindowState == FormWindowState.Minimized) {
                return;
            }
        }

        // Compute change in dimensions
        int nDeltaWidth = m_container.Width - m_nWidth;
        int nDeltaHeight = m_container.Height - m_nHeight;
        m_nWidth = m_container.Width;
        m_nHeight = m_container.Height;

        // Align controls
        foreach (LayoutManagerItem lim in m_items)
          align (lim, nDeltaWidth, nDeltaHeight);
      }

    #endregion

    #region Helper methods

      /// <summary>
      /// Repositions/resizes a LayoutManagerItem.
      /// </summary>
      /// <param name="lim">The LayoutManagerItem.</param>
      /// <param name="nDeltaW">Change in container's width.</param>
      /// <param name="nDeltaH">Change in container's height.</param>
      void align
        (LayoutManagerItem lim,
         int nDeltaW,
         int nDeltaH)
      {
        // Get control's coordinates
        int nLeft = lim.Ctrl.Left;
        int nTop = lim.Ctrl.Top;
        int nRight = nLeft + lim.Ctrl.Width;
        int nBottom = nTop + lim.Ctrl.Height;

        // Modify coordinates
        nLeft += (int) ((nDeltaW * lim.AdjustLeftPct) / 100);
        nTop += (int) ((nDeltaH * lim.AdjustTopPct) / 100);
        nRight += (int) ((nDeltaW * lim.AdjustRightPct) / 100);
        nBottom += (int) ((nDeltaH * lim.AdjustBottomPct) / 100);

        //// Set control's new coordinates
        lim.Ctrl.Left = nLeft;
        lim.Ctrl.Top = nTop;
        lim.Ctrl.Width = nRight - nLeft;
        lim.Ctrl.Height = nBottom - nTop;
      }

    #endregion

    #region Fields

      /// <summary>Layout manager items to be aligned.</summary>
      ArrayList m_items = new ArrayList();

      /// <summary>The container control.</summary>
      Control m_container = null;

      /// <summary>Container's client width.</summary>
      int m_nWidth = 0;

      /// <summary>Container's client height.</summary>
      int m_nHeight = 0;

    #endregion
  }

  /// <summary>
  /// A control whose size and position is controlled by a
  /// LayoutManager.
  /// </summary>
  /// <remarks>
  /// Copyright (c) 2006 Ravi Bhavnani (ravib@ravib.com) and
  ///                    Eddie Zhou (qingzhou100@yahoo.com)
  ///  You are allowed to include this source code in any product (commercial, shareware,
  ///  freeware or otherwise) when your product is released in binary form.  You are allowed
  ///  to modify the source code in any way you want except you cannot modify the copyright
  ///  details at the top of each module.  If you want to distribute source code with your
  ///  application, then you are only allowed to distribute versions released by the author.
  ///  This is to maintain a single distribution point for the source code.
  /// </remarks>
  public class LayoutManagerItem {
    
    #region Constructor

      /// <summary>
      /// Constructs a LayoutManagerItem for a control.
      /// </summary>
      /// <param name="ctrl">The control.</param>
      /// <param name="leftAdjustPct">Adjust control's left edge by this %age change in container's width.</param>
      /// <param name="topAdjustPct">Adjust control's top edge by this %age change in container's height.</param>
      /// <param name="rightAdjustPct">Adjust control's right edge by this %age change in container's width.</param>
      /// <param name="bottomAdjustPct">Adjust control's bottom edge by this %age change in container's height.</param>
      public LayoutManagerItem
        (Control ctrl,
         uint leftAdjustPct,
         uint topAdjustPct,
         uint rightAdjustPct,
         uint bottomAdjustPct)
      {
        m_ctrl = ctrl;
        m_leftAdjustPct = leftAdjustPct;
        m_topAdjustPct = topAdjustPct;
        m_rightAdjustPct = rightAdjustPct;
        m_bottomAdjustPct = bottomAdjustPct;
      }

    #endregion

    #region Properties

      /// <summary>
      /// Gets the control associated with this LayoutManagerItem.
      /// </summary>
      public Control Ctrl {
        get {
          return m_ctrl;
        }
      }

      /// <summary>
      /// Gets the item's "adjust left percentage" property.
      /// </summary>
      public uint AdjustLeftPct {
        get {
          return m_leftAdjustPct;
        }
      }

      /// <summary>
      /// Gets the item's "adjust top percentage" property.
      /// </summary>
      public uint AdjustTopPct {
        get {
          return m_topAdjustPct;
        }
      }

      /// <summary>
      /// Gets the item's "adjust right percentage" property.
      /// </summary>
      public uint AdjustRightPct {
        get {
          return m_rightAdjustPct;
        }
      }

      /// <summary>
      /// Gets the item's "adjust bottom percentage" property.
      /// </summary>
      public uint AdjustBottomPct {
        get {
          return m_bottomAdjustPct;
        }
      }

    #endregion

    #region Fields

      /// <summary>The control.</summary>
      Control m_ctrl = null;

      /// <summary>Percentage by which control's left edge should be adjusted.</summary>
      uint m_leftAdjustPct = 0;

      /// <summary>Percentage by which control's top edge should be adjusted.</summary>
      uint m_rightAdjustPct = 0;

      /// <summary>Percentage by which control's right edge should be adjusted.</summary>
      uint m_topAdjustPct = 0;

      /// <summary>Percentage by which control's bottom edge should be adjusted.</summary>
      uint m_bottomAdjustPct = 0;


    #endregion
  }
}

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
Canada Canada
Ravi Bhavnani is an ardent fan of Microsoft technologies who loves building Windows apps, especially PIMs, system utilities, and things that go bump on the Internet. During his career, Ravi has developed expert systems, desktop imaging apps, marketing automation software, EDA tools, a platform to help people find, analyze and understand information, trading software for institutional investors and advanced data visualization solutions. He currently works for a company that provides enterprise workforce management solutions to large clients.

His interests include the .NET framework, reasoning systems, financial analysis and algorithmic trading, NLP, HCI and UI design. Ravi holds a BS in Physics and Math and an MS in Computer Science and was a Microsoft MVP (C++ and C# in 2006 and 2007). He is also the co-inventor of 3 patents on software security and generating data visualization dashboards. His claim to fame is that he crafted CodeProject's "joke" forum post icon.

Ravi's biggest fear is that one day he might actually get a life, although the chances of that happening seem extremely remote.

Written By
Web Developer
United States United States
Eddie Zhou

Comments and Discussions