Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ResizableLib - A Set of Classes to Ease the Development of Resizable Windows with MFC

0.00/5 (No votes)
3 Feb 2023 22  
Class library to make development of resizable windows a easier for the MFC developer and pleasant for the user
This class library is an attempt to make the development of resizable windows a little easier for the MFC developer and much more pleasant for the user.

Note: New releases will be available on GitHub.

A resizable dialog! A resizable property sheet!

A resizable Wizard 97 style dialog A resizable form view

News and Release Notes

I started all this back in year 2000 (as you can see from the old screenshots above), when I was still a student and just for the fun of it. But I always wanted to share it with other developers, receive their comments and learn from this experience.

Now I don't have too much time for my hobby projects anymore, but I'm glad this code still proves useful to many people.

After many years of a quasi-dormant state, some time around 2015, I decided to give this project another home at GitHub, where I also began contributing to a few opensource projects, mostly work related.

I hope that can bring a breath of fresh air to ResizableLib and help this old library to stay up to date with recent software developments and operating system versions, and maybe receive even more contributions from the developers community.

Please have a look at https://github.com/ppescher/resizablelib[^].

I have migrated the old CVS repository hosted at SourceForge, so all the small improvements since the last official release are now there, as long as all the previous development history.

Please note the following article and documentation is incomplete and still refers to old versions of the library, but I'm keeping it for historical reasons. Maybe I'll find some time to update it in the future.

ResizableLib - What is it & Why?

This class library is an attempt to make the development of resizable windows a little easier for the MFC developer and much more pleasant for the user. A resizable window in this context is a window, not necessarily top-level, that once resized either by the user or the developer, is able to automatically resize and reposition its child controls appropriately.

To make a resizable window, you can use this set of "low level" classes:

CResizableGrip Implements a size grip for use in top-level resizable windows
CResizableMinMax Implements size constraints and maximized window position
CResizableLayout Implements a layout manager to handle child windows resizing and repositioning
CResizableState CResizableWndState CResizableSheetState Provide basic save/restore methods and implementation for generic windows and property sheets or wizard dialogs

For the most common MFC classes, you can simply replace standard MFC classes with their "resizable" counterparts:

CResizableDialog Uses CResizableGrip, CResizableMinMax, CResizableLayout, CResizableState
CResizablePage Uses CResizableLayout
CResizableSheet Uses CResizableLayout, CResizableGrip, CResizableMinMax, CResizableState
CResizablePageEx Uses CResizableLayout
CResizableSheetEx Uses CResizableLayout, CResizableGrip, CResizableMinMax, CResizableState
CResizableFormView Uses CResizableLayout, CResizableGrip, CResizableMinMax, CResizableState
CResizableFrame Uses CResizableMinMax, CResizableState
CResizableMDIFrame Uses CResizableMinMax, CResizableState
CResizableMDIChild Uses CResizableMinMax, CResizableState

The main reason for this choice is to ease and speed up the development of new types of resizable windows, possibly extending my small set, and to avoid the repeated code of the first versions.

I also unified all the classes in a library project that you can easily add to your workspace, in order to use resizable windows. Obviously, you can still add just the files you need to your project, but using the library, you have a single place to update when new releases come.

Using the Library

If you already have version 1.1 or later, you need only to replace the old files with the new ones and recompile. Some minor incompatibilities should arise, due to changed implementation, please refer to the updated documentation and to the comments in the source code.

As a Stand Alone Project

To use the class library, perform the following steps:

  • Unzip the library source and put the ResizableLib directory in a place of your choice. I suggest to use the same directory where you create your Projects (e.g., C:\MyProjects) or your common path for 3rd-party libraries
  • Go to the FileView pane and right click on the root element, or choose the Project menu, then select Insert Project into Workspace....

The ResizableLib project in the workspace

  • Navigate to the place where you put the library, select the library Project file and check Dependency of specifying which Project will make use of the library:

Insert ResizableLib into the workspace as a dependency of your project

  • Re-activate your Project in the FileView and open the Settings dialog (also from the Project menu).
  • Make sure your Project is selected in the treeview and that you have selected All Configurations in the combo box, then click on the C/C++ tab.
  • In the Category combo box, choose Preprocessor and add the library path to the Additional include directories edit box.

Include directories in the project settings

Now you are ready to start using the library or to rebuild your project if updating from the previous versions.

Note that this description will probably change for the next releases, because I'd like to distribute the library as standalone compilable project, not to be included in the workspace.

As Single Files, Part of Your Project

You just have to add the necessary files to your project, paying attention to the class dependencies. For example, if you want to use the resizable dialog class, you also have to include the low level classes.

There are some preprocessor directives in the library's stdafx.h include file to cope with the various Platform SDK versions of the header files and MFC (6.0). You may need to copy those lines to your project's stdafx.h file to make things work properly.

Notes on Building the Demo Projects

Each archive contains one directory with the VC++ project and workspace. Since each demo's workspace has a reference to the ResizableLib project, you should place all the extracted directories in the same parent directory, so the IDE won't complain about missing files.

Creating a Resizable Window [Out-of-Date]

A good example of use for the "low level" classes is the CResizableDialog class. However, for the lazy programmer, here is a small guide.

Add Layout Management

  • First of all, derive your class from CResizableLayout:
    C++
    class CMyResizableWindow : public CBaseWnd, public CResizableLayout
  • Implement GetResizableWnd pure virtual function this way:
    C++
    virtual CWnd* GetResizableWnd() { return this; };
  • Override the OnSize message handler to re-arrange child windows:
    C++
    void CMyResizableWindow::OnSize(UINT nType, int cx, int cy) 
    {
      CBaseWnd::OnSize(nType, cx, cy);
      
      // ...
        
      ArrangeLayout();
    }
  • Override the OnEraseBkgnd message handler to reduce flickering during resize operations:
    C++
    BOOL CMyResizableWindow::OnEraseBkgnd(CDC* pDC) 
    {
      EraseBackground(pDC);
    
      return TRUE;
    }
  • You may also need to override the OnDestroy message handler to clean up the layout if you want to use the MFC object to create the associated window multiple times (because the layout is still valid until object's destruction):
    C++
    void CMyResizableWindow::OnDestroy() 
    {
      RemoveAllAnchors();
    
      CBaseWnd::OnDestroy();
    }
  • You can now call AddAnchor or AddAnchorCallback to set the child windows' layout in one of the initialization functions, such as OnInitDialog or OnInitialUpdate.

Add Min/Max Size Handling

  • Derive your class from CResizableMinMax:
    C++
    class CMyResizableWindow : public CBaseWnd, public CResizableMinMax
  • Override the OnGetMinMaxInfo message handler to provide min/max information:
    C++
    void CMyResizableWindow::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) 
    {
      MinMaxInfo(lpMMI);
    }

Add Size Grip Support

  • Derive your class from CResizableGrip:
    C++
    class CMyResizableWindow : public CBaseWnd, public CResizableGrip
  • Implement GetResizableWnd pure virtual function this way:
    C++
    virtual CWnd* GetResizableWnd() { return this; };
  • Override the OnCreate message handler to create the grip:
    C++
    int CMyResizableWindow::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    {
      if (CBaseWnd::OnCreate(lpCreateStruct) == -1)
        return -1;
      
      // ...
    
      if (!CreateSizeGrip())
        return -1;
    
      return 0;
    }
  • Override the OnSize message handler to update the grip position:
    C++
    void CMyResizableWindow::OnSize(UINT nType, int cx, int cy) 
    {
      CBaseWnd::OnSize(nType, cx, cy);
      
      // ...
      
      UpdateSizeGrip();
    }

Add Save/Restore Support

  • Derive your class from CResizableState:
    C++
    class CMyResizableWindow : public CBaseWnd, public CResizableState
  • Implement GetResizableWnd pure virtual function this way:
    C++
    virtual CWnd* GetResizableWnd() { return this; };
  • Provide your own wrapper function that saves/restores the window state, especially if you need to add custom settings, or let the user call LoadWindowRect and SaveWindowRect.

Class Reference [out-of-date]

CResizableLayout

CResizableLayout::AddAnchor

C++
void AddAnchor(HWND hWnd, CSize sizeTypeTL, CSize sizeTypeBR = NOANCHOR)
void AddAnchor(UINT nID, CSize sizeTypeTL, CSize sizeTypeBR = NOANCHOR)

Adds a child window to the layout list and set the anchor type for the top-left and bottom-right corners of the control. During a resizing operation, the control's corners are kept at fixed distance from the dialog point you specify: argument's cx member is the horizontal position, while cy is vertical, in percentage.

If you have overlapping controls, you should order calls to this function from the outer controls to the inner ones, to let the clipping routines to work correctly.

A set of useful constant values, provided also for compatibility, is defined:

C++
const CSize
  NOANCHOR(-1,-1),
  TOP_LEFT(0,0), TOP_CENTER(50,0), TOP_RIGHT(100,0),
  MIDDLE_LEFT(0,50), MIDDLE_CENTER(50,50), MIDDLE_RIGHT(100,50),
  BOTTOM_LEFT(0,100), BOTTOM_CENTER(50,100), BOTTOM_RIGHT(100,100);
I think their meaning is self-explained. Using NOANCHOR for top-left corner is not allowed, so it will generate an 'assertion failed' in the Debug version.

CResizableLayout::AddAnchorCallback

C++
void AddAnchorCallback(UINT nCallbackID)

Adds a placeholder to the layout with the given callback ID. This is useful when the control you want to add, or its "anchorage", can change at run-time.

You must override ArrangeLayoutCallback to provide layout information.

CResizableLayout::RemoveAnchor

C++
BOOL RemoveAnchor(HWND hWnd)
BOOL RemoveAnchor(UIND nID)
Removes a window from the layout, given its handle or control ID.

There is not a corresponding function for callback items.

CResizableLayout::RemoveAllAnchors

C++
void RemoveAllAnchors()
Removes all the windows from the layout. Usually called in OnDestroy.

CResizableLayout::GetAnchorPosition

C++
BOOL GetAnchorPosition(HWND hWnd, const CRect &rectParent, 
   CRect &rectChild, UINT* lpFlags = NULL)
BOOL GetAnchorPosition(UINT nID, const CRect &rectParent, 
   CRect &rectChild, UINT* lpFlags = NULL)
Calculates the size and position of an anchored control for the given parent window's size. The returned flags should be used in a call to SetWindowPos. The return value is TRUE if the first argument identifies an anchored control, FALSE otherwise.

CResizableLayout::ArrangeLayout

C++
void ArrangeLayout()

Adjusts the size and position of the child windows you added to the layout list with AddAnchor according to the size of the parent window. Usually called in your OnSize handler.

CResizableLayout::ArrangeLayoutCallback

C++
virtual BOOL ArrangeLayoutCallback(LayoutInfo& layout)

Override this function to provide layout information for a given callback ID. When the function is called, the layout structure contains the callback ID for which layout information is requested. You have to fill in the rest of the structure. The return value is TRUE if the structure contains valid information, FALSE otherwise.

You should test the value of the nCallbackID structure member and pass the control to the base implementation if you didn't add that ID. If you don't provide layout information, the default implementation returns FALSE and no action is taken.

When this function is called, non-callback items are in their new position after resizing, but you can't assume the same for the previous callback items.

CResizableLayout::GetTotalClientRect

C++
virtual void GetTotalClientRect(LPRECT lpRect)

Override this function to provide the client area the class uses to perform layout calculations, both when adding controls and when rearranging layout.

This function is used by the class, and should be used by derived classes too, in place of the standard GetClientRect. It can be useful for windows with scrollbars or expanding windows, to provide the total client area, even those parts which are not visible.

CResizableLayout::ClipChildren

C++
void ClipChildren(CDC *pDC)

Not recommended when compatibility with WinXP themes is needed.

See EraseBackground, GetClippingRegion.

Excludes child windows from the clipping area of the given DC. Usually called in your OnEraseBkgnd to have a flicker-free resizing.

CResizableLayout::GetClippingRegion

C++
void GetClippingRegion(CRgn* pRegion)

Obtains the clipping region for the current layout. Windows that needs the parent to paint the background, such as some types of Static controls or transparent windows, belongs to the region, while the others are clipped out.

You may use this region, for example, in calls to PaintRgn or FillRgn to paint the parent's background.

CResizableLayout::EraseBackground

C++
void EraseBackground(CDC* pDC)

Paints the layout's clipping region using the default brush for the parent window. Usually called in your OnEraseBkgnd to have a flicker-free resizing.

CResizableLayout::InitResizeProperties

C++
virtual void InitResizeProperties(CResizableLayout::LayoutInfo& layout)

Used to set the initial resize properties of an anchored control, that are stored in the properties member of the LayoutInfo structure.

C++
// wether to ask for resizing properties every time
BOOL bAskClipping;
BOOL bAskRefresh;
// otherwise, use the cached properties
BOOL bCachedLikesClipping;
BOOL bCachedNeedsRefresh;
The various flags are used to specify whether the resize properties (clipping, refresh) can change at run-time, and a new call to the property querying functions is needed at every layout adjustment, or they are static properties, and the cached value is used when needed.

The default implementation sets "clipping" as static, calling LikesClipping only once, and "refresh" as dynamic, causing NeedsRefresh to be called every time. This should be right for most situations, but you can override this function if needed.

Note: The default implementation of this and the following overridable functions also sends a registered message to the anchored control, giving it the opportunity to specify its resize properties, which takes precedence if supported. See the files ResizableMsgSupport.* for details.

CResizableLayout::LikesClipping

C++
virtual BOOL LikesClipping(const LayoutInfo &layout)

Used to determine if an anchored control can be safely clipped, that is it's able to repaint its background. The return value is TRUE if clipping can occur for this window, FALSE otherwise.

The default implementation tries to identify "clippable" windows by class name and window's style. Override this function if you need more control on clipping. Note that not clipped windows often tend to flicker.

CResizableLayout::NeedsRefresh

C++
virtual BOOL NeedsRefresh(const LayoutInfo &layout, 
   const CRect &rectOld, const CRect &rectNew)

Used to determine if a child window needs repainting when moved/resized. The return value is TRUE if this window must be repainted, FALSE otherwise.

The default implementation tries to identify windows that need refresh by class name and window's style. Override this function if you need different behavior or if you have custom child windows.

CResizableGrip

CResizableGrip::CreateSizeGrip

C++
BOOL CreateSizeGrip(BOOL bVisible = TRUE, BOOL bTriangular = TRUE, 
   BOOL bTransparent = FALSE)
You call this function to create the size grip, usually in your OnCreate message handler. You can specify the initial visibility, whether to use a triangular shape or a transparent background. The return value is non-zero if the grip was created successfully, zero otherwise.

CResizableGrip::SetSizeGripShape

C++
void SetSizeGripShape(BOOL bTriangular)
Changes the grip's shape to a triangle or a rectangle.

CResizableGrip::SetSizeGripBkMode

C++
BOOL SetSizeGripBkMode(int nBkMode)
Sets the background mode of the size grip. Accepts the same values as the SetBkMode function: OPAQUE or TRANSPARENT. The return value is zero if an error occurred, non-zero otherwise.

CResizableGrip::SetSizeGripVisibility

void SetSizeGripVisibility(BOOL bVisible)

Sets the grip's default visibility. The actual state depends on the current show count, that is modified by calls to ShowSizeGrip and HideSizeGrip.

CResizableGrip::ShowSizeGrip

C++
void ShowSizeGrip(DWORD* pStatus, DWORD dwMask = 1)

Increases the current show count, if the visibility status is not already on. Changes to the actual grip's visibility are effective only after a call to UpdateSizeGrip.

The DWORD variable pointed to by pStatus, masked by dwMask, holds the visibility status with respect to a particular condition meaningful only to the caller. The initial value of this visibility status must be zero (off) to allow to temporarily show the grip, non-zero (on) to allow to temporarily hide the grip.

Note: A single DWORD variable can hold up to 32 conditions just by changing the associated mask.

CResizableGrip::HideSizeGrip

C++
void HideSizeGrip(DWORD* pStatus, DWORD dwMask = 1)

Decreases the current show count, if the visibility status is not already off. Changes to the actual grip's visibility are effective only after a call to UpdateSizeGrip.

Every call to ShowSizeGrip should be matched by a call to HideSizeGrip, according to the condition the visibility status represents.

CResizableGrip::IsSizeGripVisible

C++
BOOL IsSizeGripVisible()
Used to tell if the size grip should be actually visible, according to the current show count.

CResizableGrip::UpdateSizeGrip

C++
void UpdateSizeGrip()
Recalculates the grip's position when the containing window is resized and shows or hides the grip as needed. You usually call this function in your OnSize handler or after a call to ShowSizeGrip or HideSizeGrip.

CResizableMinMax

CResizableMinMax::MinMaxInfo

C++
void MinMaxInfo(LPMINMAXINFO lpMMI)
Updates the MINMAXINFO structure according to current min/max settings.

CResizableMinMax::SetMaximizedRect

C++
void SetMaximizedRect(const CRect& rc)

Sets the rectangular area that the window will occupy when maximized. Default is the standard size and position set by the system (the workspace area of the screen).

CResizableMinMax::ResetMaximizedRect

C++
void ResetMaximizedRect()

Reverts the effect of a previous call to SetMaximizedRect, that is maximizing the window will produce the standard behavior.

CResizableMinMax::SetMinTrackSize

C++
void SetMinTrackSize(const CSize& size)

Sets the minimum size of the window when resized. This setting does not affect the behavior of a minimize operation, which always produce the expected result.

CResizableMinMax::ResetMinTrackSize

C++
void ResetMinTrackSize()

Reverts the effect of a previous call to SetMinTrackSize, that is the standard minimum size is set by the system.

CResizableMinMax::SetMaxTrackSize

C++
void SetMaxTrackSize(const CSize& size)

Sets the maximum size of the dialog when resized. Default is the standard size set by the system (the workspace area of the screen). Note that this setting affects the behavior of a maximize operation and maximized size is clipped to this value by the system.

CResizableMinMax::ResetMaxTrackSize

C++
void ResetMaxTrackSize()

Reverts the effect of a previous call to SetMaxTrackSize, that is the standard maximum size is set by the system.

CResizableState

CResizableState::LoadWindowRect

C++
BOOL LoadWindowRect(LPCTSTR pszSection, BOOL bRectOnly)

Loads the window's size, position and state from the given section in the application's profile settings (either the registry or a INI file). If bRectOnly is TRUE, the window's minimized/maximized state is not restored.

CResizableState::SaveWindowRect

C++
BOOL SaveWindowRect(LPCTSTR pszSection, BOOL bRectOnly)

Saves the window's size, position and state to the given section in the application's profile settings (either the registry or a INI file). You should use the same value you use in the LoadWindowRect function for the bRectOnly argument.

Present and Future - Alpha Release 1.4a

I've been working on the 1.4 version for months and yet I'm not able to release anything. This is very disappointing! I had to do something... that's why I'm releasing this incomplete alpha version. There are so many improvements in the library that I don't even remember - thank God I used CVS - and I believe it's better to release something instead of waiting another six month or worse.

I passed the last weeks to start documenting the code using Doxygen, but there are still so many things to do:

  • Complete the Doxygen documentation
  • Update the articles and talk about technical details, since the class reference will have its place in the Doxygen generated files
  • Test some of the most problematic new features (disabled in 1.4a) for the full release
  • Make better demo projects to show the features and help test them

It takes too long to do all of this by myself. I would really appreciate any little help the most experienced users of this library could offer me. Otherwise, you'll just have to wait longer...

Known Issues

I try to do my best to fix bugs and/or to find workarounds for new problems, but there's surely something I forgot or I didn't have the time to look at.

  • Wizard97-style resizable dialogs still have some minor drawing issues, especially with WinXP themes enabled, but I think I got them working pretty well.
  • Flickering has been greatly reduced but it's still there.

    Some controls, such as some types of Static, the GroupBox and transparent windows, relies on the parent window to paint the background. This causes the controls to be over-painted with the background color before they can redraw themselves. And that's precisely what flickering is.

    Improvements in version 1.4a include a new feature that reduces flickering when resizing occurs on the left or top edges of a window. This may cause issues in projects that used version 1.3, because controls that would stay on the top-left corner could be left not anchored. Now you have to call AddAnchor for all the child windows.

  • Standalone documentation not ready yet.

    Since version 1.1 and before I added a Docs directory to the project, with a basic Doxygen configuration file. But the source code needs Doxygen compliant comments to actually produce something more than the class hierarchy.

    In version 1.4a, I started using the Doxbar addin for VC++ 6 and now some of the core classes are documented. Just run Doxygen in the library project directory.

To Do

  • Experiment with double-buffering techniques to completely remove flickering.

    Oz Solomonovich helped me to solve the problems with WinXP themes and clipping regions. He also made me aware of a trick you can use to force windows to draw on a specific DC, possibly enabling a double-buffered repainting (the hard way).

    In version 1.4a, I was trying to use XP native double-buffering, but it leads to many issues that need testing and time to be solved. This is disabled with a preprocessor macro by default, so that the code can still be used safely.

  • Test the new features with old Windows platforms.

    I tried to keep backward compatibility with all Win32 platforms, but I don't have old Windows versions installed anymore, so I can't be sure everything is ok.

    In version 1.4a, I also introduced additional code and preprocessor directives to help tailor the code to specific platforms. The principle is, when you choose a target Windows platform with the usual "WINVER and friends" macros, the library produces code that enables features specific to that platform, but degrades gracefully when run on older platforms.

  • Update the demo projects to use XP visual styles and possibly make them nicer.

    Version 1.4a includes manifest files for XP visual styles.

  • Test the library with Unicode and add Unicode build configurations to the project.

    Version 1.4a includes Unicode build configurations. It needs testing though.

  • Start using Doxygen style comments and convert existing ones, also using the documentation in this page.

    Well, this has been started in version 1.4a and the official 1.4 version won't be released until it's complete.

  • Make the library project actually produce a standalone compiled library or possibly a DLL, just like any good class library, with different output names for the Debug and Release versions.

    I'm not sure about this, but I guess it would be easier to just use the library in some project. Also help in this direction is welcome.

Plans

  • A WTL, and possibly SDK, version of the library

    Alexander D. Alexeev has contributed a WTL port of an old version, I think 1.1, that gave me some ideas for the library. I'd like to update his port to the new version and possibly avoid repeated code. This makes me thinking about an SDK port to use as a base implementation for both the MFC and WTL versions.

    I made experiments with a template version of the library and proved the above idea is feasible, but it's surely a long-term task. Definitely after the official 1.4 version is released.

  • A standalone reference guide for the library (using Doxygen).

    This is on it's way for the next official release.

Conclusion

This class library is an effort to make a more reusable solution to the problem of resizable windows. And it's a bigger and bigger an effort as development goes on. I still have ideas to improve this library, but definitely lack the time to do it. I hate to see those fixed size dialogs, or worse those resizable windows that flicker badly, so I really hope to see more resizable windows out there and that look good!

I don't want to say "use my library", because the same things can surely be done in a better way, but at least use something that works as good as ResizableLib.

Thanks to all the happy users and especially to all those people who sent fixes or bug reports. As you can see, there are always many things to do... so contributions are definitely welcome!

This library is now distributed under the terms of Artistic License, that allows for use in commercial applications. You just can't sell this work as part of a library and claim it's yours. This also means that credits are not required, but they would be nice! :)

The CVS tree is now hosted on Source Forge.

Updates

11th June, 2001

  • Initial public release

15th July, 2001

  • Changed grip implementation, now using a scrollbar child window
  • Overriding OnNcHitTest and OnPaint no more required
  • Grip is now triangular, allowing backgrounds different from simple gray
  • Added "callback anchors" to the layout class, for property sheets integration
  • Callbacks allow adding a variable window and anchor type to the layout
  • Added Wizard97, FormView and complete PropertySheet support
  • Updated documentation for new functions

18th August, 2001

  • Improved clipping capability: overlapping controls handled properly if AddAnchors calls are in the correct order
  • Removed second loop in ArrangeLayout, now using SWP_NOCOPYBITS
  • Fixed a bug during initial style change to enable resizing, now client rect is preserved
  • Fixed bug with transparent toolbars
  • License changed to "Artistic License", CVS repository now on SourceForge

29th October, 2001

Version 1.1 (CVS Tag: SF_1_1)
  • Fixed a bug with CTRL+Tab while navigating Wizard dialogs
  • Added static build configurations to all projects
  • Some cosmetic stuff

13th July, 2002

Version 1.2 (CVS Tag: SF_1_2)
  • Changed layout implementation, now using 2 lists and a map.
  • Changed LayoutInfo structure: added class name, removed refresh flags
  • Now NeedsRefresh function is called every time the layout is updated and not once during AddAnchor
  • Improved anti-flickering for Static controls (needs testing)
  • Added functions to support dynamic windows and to retrieve a control's position and size in the layout
  • Changed grip implementation, now using a MFC derived class
  • Fixed background problems with WinXP themes (needs testing)
  • Updated documentation (this page)

27th October, 2002

Version 1.3 (CVS Tag: SF_1_3)
  • Changed ArrangeLayout to update all controls at once, even callbacks
  • Changed LayoutInfo structure: added resize properties support
  • Changed grip functions, allowing more customization, added transparent background
  • Added grip, window's state save/restore, and min/max size handling
  • Added classes for frame windows (SDI, MDI) to handle min/max size constraints (not working with splitters yet)
  • Added initial support for custom windows by means of a registered message
  • Fixed overlapping group boxes, incorrectly clipping siblings controls (old code had not been removed)
  • Fixed grip, now handling system parameters changes
  • Fixed the problems with scrolling windows (FormView)
  • Updated documentation (this page), added a ChangeLog to this release

9th June, 2004

Version 1.4 Alpha (CVS Tag: CP_1_4_alpha - Git Tag: v1.4a)
  • Alpha Release, Incomplete
  • Latest release available on SourceForge and CodeProject

Moved Repository and Development to Github

4th January, 2018

Version 1.5.1 (Git Tag: v1.5.1)
This long due release contains many fixes and improvements over the last public release, with contributions from CodeProject and GitHub users. All this time also means I partly forgot what problems the single commits were meant to solve, but here is a rough list of the changes:
  • Migrated repository from CVS to Git and moved development from SourceForge to GitHub
  • Migrated all projects and solutions to VS2015, with support for XP build
  • Added convenience function to anchor remaining controls
  • Added manifest to all demo projects to enable visual styles
  • Fixed a bug with menu redraw and non-client area calculations
  • Fixed resource leak for clipping region
  • Fixed max track size calculations with splitter windows
  • Fixed compilation of resizable combo box
  • Fixed resizable combo list box appearance
  • Fixed a bug with minimized then restored frames
  • Fixed layout preset for child (modeless) property sheets
  • Fixed project settings for ANSI builds
  • Fixed wizard97 header redraw (missing in CommCtrls >= 6.00)
  • Fixed maximized size not constrained by track size when window border is not resizable
  • Contributed fixes and other minor changes (see GitHub release notes)

28th April, 2019

Version 1.5.2 (Git Tag: v1.5.2)
Small bugfix release with a few contributions:
  • Fix AddAllOtherAnchors() incorrectly moving the SizeGrip
  • Contributions with other fixes and minor changes

30th June, 2020

Version 1.5.3 (Git Tag: v1.5.3)
Mainly cosmetic changes to the source code and update of project files, with a few fixes:
  • Fixed dialog resize could cause some static text to be clipped or disappear
  • Fixed new and '97 style wizard dialogs redraw issues

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