MFC/C++ Helper Class for Window Resizing






4.91/5 (138 votes)
Gives you total control when it comes to resizing windows

Introduction
In MFC, resizing or repositioning controls could be quite bothersome. If you are familiar with the .NET platform, things are much more simplified with the use of the Anchor
and Dock
properties of the Control
class and design-time support for adding child controls to container controls. I tried to mimic some of these features of .NET, but the C++ way.
Background
There are other solutions available online (also on CodeProject.com) for this purpose. I think my solution stands out on its design, simplicity, and feature richness.
This solution allows you to do the following:
- Anchor dialog controls
- Create panels which contain other panels or UI controls
- Restrict the size of dialog controls or panels by using minimum size and maximum size properties
- Restrict the size of dialogs by using minimum size and maximum size properties
- Create horizontal or vertical split containers
- Freeze split containers so that users cannot use mouse to resize the panels
- Set a panel of split containers to be fixed so that when the dialog resizes, the fixed panel will remain unchanged
- Set the parent of dialog controls or panels (not related to Win32
SetParent
API) - Show a resize grip on the lower right corner of the dialog using Visual Style (if the application supports it)
- Show resize grips for splitter of split containers
- Dock dialog control within its parent panel
- Create flow layout panels
Let's take a brief look at how .NET does its resizing of child controls:
Anchor
- It allows a child control to be anchored to the left, top, right, or bottom edge, or any combination of these four options.Dock
- It allows a child control to be docked to the left, top, right, and bottom edges.- Visual Studio Designer Support - If you place a frame control on a Windows Form and then drag a button control on top of the frame, the button becomes the actual child of the frame and grandchild of the Windows Form. But in the resource editor of MFC, if you place the frame on the dialog template and then drag a button on top of the frame control, the button is actually an immediate child of the dialog template and not the frame. This means if you move the frame, the button will not move.
SplitContainer
- Creating splitter windows has never been this simple since the invention of this control. It has two panels which can host other controls inside.FlowLayout
- Represents a panel that dynamically lays out its contents horizontally or vertically.
So in .NET, all controls are children or grandchildren of the Form
; this creates a hierarchical structure of controls. When a parent is resized or repositioned, all its children are resized or repositioned according to their Anchor
or Dock
property settings.
In my solution, I create a hierarchical structure of rectangles (CRect
) instead. I have implemented the Anchor
, Panel
, SplitContainer
, Dock
, and FlowLayout
concepts.
There are several classes in this solution, but CWndResizer
is the only class that a developer will work with.
Typically, you will design your dialog template in the Visual Studio Resource Editor, and then in the dialog class implementation, you will have a member variable like this:
private:
CWndResizer m_resizer;
The samples included with this article uses the CDialog
class to demonstrate many features of this class. But this class can be used with any class derived from CWnd
(CDialog
, CPropertyPage
, CPropertySheet
, CFrmWnd
, CFormView
, etc.).
Before this class can do anything, you must call the Hook
method like this:
BOOL CExample1Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
BOOL bOk = m_resizer.Hook(this);
ASSERT(bOk == TRUE);
}
In this article, I will refer to this window (that is passed to the Hook
method) as "hooked-window".
By calling this method, it places a window procedure hook in the WndProc
chain.
When you call the Hook
method, it stores the client area of the hooked-window in a structure called CPanel
. A panel is mainly a rectangle area given in client coordinates of the hooked-window. A panel can have zero or more panels as children. During the creation of a panel, you assign a unique name for the panel. The name is used to refer to the panel or find a panel. The client area of the hooked-window is the root of the hierarchy, and it is named _root
.
Each panel has the Anchor
, MinSize
, and MaxSize
properties (along with some other properties). But you cannot directly set or get the properties of a panel; instead, you will use member methods of the CWndResizer
class.
The idea is that when a CPanel
is resized or repositioned, all its children are also resized and repositioned relatively.
Now, let's look at some code snippets.
The following code will anchor the OK and Cancel buttons of your dialog to the bottom-right corner:
BOOL CExample1Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
BOOL bOk = m_resizer.Hook(this);
ASSERT(bOk == TRUE);
bOk = m_resizer.SetAnchor(IDOK, ANCHOR_RIGHT | ANCHOR_BOTTOM);
ASSERT(bOk == TRUE);
bOk = m_resizer.SetAnchor(IDCANCEL, ANCHOR_RIGHT | ANCHOR_BOTTOM);
ASSERT(bOk == TRUE);
}
If you want to create a panel and set its Anchor
property to ANCHOR_HORIZONTALLY
, you will do this:
BOOL CExample1Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
BOOL bOk = m_resizer.Hook(this);
ASSERT(bOk == TRUE);
CRect rc(40, 40, 240, 240);
bOk = m_resizer.CreatePanel(_T("MyNewPanel"), &rc);
bOk = m_resizer.SetAnchor(_T("MyNewPanel"), ANCHOR_HORIZONTALLY);
ASSERT(bOk == TRUE);
ASSERT(bOk == TRUE);
}
About Clipping (Important)
This solution cannot clip any part of a dialog control or any part of a panel. A CPanel
object does not have any window (HWND
) associated with it in general. If a child panel is larger than its parent panel, the child's area that is outside the parent will be visible since neither the parent panel nor the child panel is actually a window. To circumvent this issue, we should set a reasonable minimum size of the parent panel by calling the SetMinimumSize
method so that the parent is never smaller than the child's minimum size. You should also consider setting the minimum size of the hooked-window as well such that it can contain all panels within its client area.
Using the Code
The sample application, created in VS2008, demonstrates many features of this class.
The CWndResizer
class has the following members:
Here are the details:
Method |
|
|||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Description | Creates a flow layout panel in the client area of the hooked-window (.NET analogy). | |||||||||||||||||||||||||
Parameters | panelName |
A unique name for this panel. This name is used to refer to this panel later on. | ||||||||||||||||||||||||
prcPanel |
A rectangle given in the hooked-window's client coordinate. | |||||||||||||||||||||||||
parrID |
An array of dialog control IDs. This method creates a panel with the combined area of the dialog controls specified in this array. | |||||||||||||||||||||||||
setAsChildren |
If this is TRUE , then this method will create panels for each of the dialog controls specified in parrID and make them children of its own. |
|||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
-or-
-or-
|
|||||||||||||||||||||||||
Remarks |
The You can specify the flow direction by calling the value of the Other panels can be a child of the |
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Creates a panel in the client area of the hooked-window. | |||||||||||||||||||||||||
Parameters | panelName |
An unique name for this panel. This name is used to refer to this panel later on. | ||||||||||||||||||||||||
prcPanel |
A rectangle given in the hooked-window's client coordinate. | |||||||||||||||||||||||||
parrID |
An array of dialog control IDs. This method creates a panel with the combined area of the dialog controls specified in this array. | |||||||||||||||||||||||||
setAsChildren |
If this is TRUE , then this method will create panels for each of the dialog controls specified in parrID and make them children of its own. |
|||||||||||||||||||||||||
panelID |
An ID of the dialog control. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
-or-
-or-
-or-
|
|||||||||||||||||||||||||
Remarks |
After a panel is created, by default, it will have the following initial settings:
About
About
|
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Creates a split container (.NET analogy). | |||||||||||||||||||||||||
Parameters | splitContainerName |
A unique name for this split container. This name is used to refer to this panel later on. | ||||||||||||||||||||||||
panelNameA |
Name of a panel that was created by a prior call to CWndResizer::CreatePanel or CWndResizer::CreateSplitContainer .
If the resulting panel is a horizontal split container, this refers to the left panel of the split container. Otherwise, it is the top panel of the split container. |
|||||||||||||||||||||||||
panelIDA |
An ID of a child control (window) of the hooked-window.
If the resulting panel is a horizontal split container, this refers to the left panel of the split container. Otherwise, it is the top panel of the split container. |
|||||||||||||||||||||||||
panelNameB |
Name of a panel that was created by a prior call to If the resulting panel is a horizontal split container, this refers to the right panel of the split container. Otherwise, it is the bottom panel of the split container. |
|||||||||||||||||||||||||
panelIDB |
An ID of a child control (window) of the hooked-window. If the resulting panel is a horizontal split container, this refers to the right panel of the split container. Otherwise, it is the bottom panel of the split container |
|||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
-or-
-or- The specified panels (rectangles) overlapped. -or- One or all of the specified panels have already been used to create the split container. |
|||||||||||||||||||||||||
Remarks |
If the Definition of CSplitContainerA If you move your mouse over the space (
|
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Gets the anchor of the specified panel (.NET analogy). | |||||||||||||||||||||||||
Parameters | panelName |
Name of a panel that was created by a prior call to CWndResizer::CreatePanel . |
||||||||||||||||||||||||
panelID |
An ID of a child control (window) of the hooked-window. | |||||||||||||||||||||||||
anchor |
Receive the anchor value. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. anchor contains a valid value. |
||||||||||||||||||||||||
FALSE |
Failed.
-or-
|
|||||||||||||||||||||||||
Remarks | Retrieves the anchor value of a panel. See SetAnchor for details. |
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Gets whether or not paint should be automatically handled by CWndResizer . |
|||||||||||||||||||||||||
Return values | TRUE |
Succeeded. anchor contains a valid value. |
||||||||||||||||||||||||
FALSE |
Failed.
-or-
|
|||||||||||||||||||||||||
Remarks | Please see SetAutoHandlePaint for details. |
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Gets the anchor of the specified panel (.NET analogy). | |||||||||||||||||||||||||
Parameters | panelName |
Name of a panel that was created by a prior call to CWndResizer::CreatePanel . |
||||||||||||||||||||||||
panelID |
An ID of a child control (window) of the hooked-window. | |||||||||||||||||||||||||
uDock |
Receive the dock value. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. anchor contains a valid value. |
||||||||||||||||||||||||
FALSE |
Failed.
-or-
|
|||||||||||||||||||||||||
Remarks | Retrieves the dock value of a panel. See SetDock for details. |
|||||||||||||||||||||||||
Method | BOOL GetFixedPanel(LPCTSTR splitContainer, short & panel); |
|||||||||||||||||||||||||
Description | Gets the name of the panel that is fixed (if any) (.NET analogy). | |||||||||||||||||||||||||
Parameters | splitContainerName |
Name of the split container that was created by a prior call to CWndResizer::CreateSplitContainer . |
||||||||||||||||||||||||
panel |
Receives the ID of the fixed panel. If this contains 1, then the left panel (or the top panel if splitContainer is a vertical split container) is fixed, or if it is 2, then the right panel (or the bottom panel if splitContainer is a vertical split container). Otherwise, splitContainer has no fixed panel. |
|||||||||||||||||||||||||
Return values | TRUE |
Succeeded. panel contains a valid value. |
||||||||||||||||||||||||
FALSE |
Failed. The -or-
|
|||||||||||||||||||||||||
Remarks | Retrieves the fixed panel ID of a a split container. See SetSetFixedPanel for details. |
|||||||||||||||||||||||||
Method | BOOL GetFlowDirection(LPCTSTR flowPanelName, short & direction); |
|||||||||||||||||||||||||
Description | Gets the flow direction of the FlowPanel (.NET analogy). |
|||||||||||||||||||||||||
Parameters | flowPanelName |
Name of the split container that was created by a prior call to CWndResizer::CreateFlowLayoutPanel . |
||||||||||||||||||||||||
direction |
Receives the flow direction of the FlowPanel . |
|||||||||||||||||||||||||
Return values | TRUE |
Succeeded. direction contains a valid value. |
||||||||||||||||||||||||
FALSE |
Failed.
-or-
|
|||||||||||||||||||||||||
Remarks | See SetFlowDirection for details. |
|||||||||||||||||||||||||
Method | BOOL GetFlowItemSpacingX(LPCTSTR flowPanelName, int & nSpace); |
|||||||||||||||||||||||||
Description | Gets the spacing between items in x-direction in the FlowPanel . |
|||||||||||||||||||||||||
Parameters | flowPanelName |
Name of the split container that was created by a prior call to CWndResizer::CreateFlowLayoutPanel . |
||||||||||||||||||||||||
nSpace |
Receives the space in pixels. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. panel contains a valid value. |
||||||||||||||||||||||||
FALSE |
Failed. The
-or-
|
|||||||||||||||||||||||||
Remarks | See SetFlowItemSpacingX for details. |
|||||||||||||||||||||||||
Method | BOOL GetFlowItemSpacingY(LPCTSTR flowPanelName, int & nSpace); |
|||||||||||||||||||||||||
Description | Gets the spacing between items in y-direction in the FlowPanel . |
|||||||||||||||||||||||||
Parameters | flowPanelName |
Name of the split container that was created by a prior call to CWndResizer::CreateFlowLayoutPanel . |
||||||||||||||||||||||||
nSpace |
Receives the space in pixels. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. panel contains a valid value. |
||||||||||||||||||||||||
FALSE |
Failed.
-or-
|
|||||||||||||||||||||||||
Remarks | See SetFlowItemSpacingY for details. |
|||||||||||||||||||||||||
Method | BOOL GetIsSplitterFixed(LPCTSTR splitContainerName , BOOL &fixed); |
|||||||||||||||||||||||||
Description | Gets whether or not the splitter is set to fixed for a split container (.NET analogy). | |||||||||||||||||||||||||
Parameters | splitContainerName |
Name of the split container that was created by a prior call to CWndResizer::CreateSplitContainer . |
||||||||||||||||||||||||
fixed |
Receives a boolean value. If this is TRUE , then the splitter is fixed; otherwise, the splitter is free to be moved by mouse. |
|||||||||||||||||||||||||
Return values | TRUE |
Succeeded. fixed contains a valid value. |
||||||||||||||||||||||||
FALSE |
Failed. The
-or-
|
|||||||||||||||||||||||||
Remarks | Retrieves a flag that indicates whether or not the splitter is free to be moved by mouse for a split container. See SetIsSplitterFixed for details. |
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Gets the maximum size of the specified panel (.NET analogy). | |||||||||||||||||||||||||
Parameters | panelName |
Name of a panel that was created by a prior call to CWndResizer::CreatePanel . |
||||||||||||||||||||||||
panelID |
An ID of a child control (window) of the hooked-window. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. size contains the valid value. |
||||||||||||||||||||||||
FALSE |
Failed. The
-or-
|
|||||||||||||||||||||||||
Remarks | If panelName or panelID refers to a panel that is part of the horizontal split container, then the CSize::cy member should be ignored. If panelName or panelID refers to a panel that is part of the vertical split container, then the CSize::cx member should be ignored. |
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Gets the minimum size of the specified panel (.NET analogy). | |||||||||||||||||||||||||
Parameters | panelName |
Name of a panel that was created by a prior call to CWndResizer::CreatePanel . |
||||||||||||||||||||||||
panelID |
An ID of a child control (window) of the hooked-window. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. size contains the valid value. |
||||||||||||||||||||||||
FALSE |
Failed. The size value should be ignored.
-or-
|
|||||||||||||||||||||||||
Remarks | If panelName or panelID refers to a panel that is part of a horizontal split container, then the CSize::cy member should be ignored. If panelName or panelID refers to a panel that is part of a vertical split container, then the CSize::cx member should be ignored. |
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Gets the name of the parent of the specified panel. | |||||||||||||||||||||||||
Parameters | panelName |
Name of a panel that was created by a prior call to CWndResizer::CreatePanel . |
||||||||||||||||||||||||
panelID |
An ID of a child control (window) of the hooked-window. | |||||||||||||||||||||||||
parentName |
Receives the name of the parent. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. parentName contains a valid value. |
||||||||||||||||||||||||
FALSE |
Failed. The
-or-
|
|||||||||||||||||||||||||
Remarks | If parentName is _root , it indicates that the panel is an immediate child of the hooked-window. |
|||||||||||||||||||||||||
Method | BOOL GetShowResizeGrip(); |
|||||||||||||||||||||||||
Description | Gets a flag indication if a resize grip will be drawn on the lower-right corner of the hooked-window. | |||||||||||||||||||||||||
Parameters | N/A |
No parameters. | ||||||||||||||||||||||||
Return values | TRUE |
It will draw a resize grip at the bottom-right corner of the dialog/window. | ||||||||||||||||||||||||
FALSE |
It will not draw a resize grip at the bottom-right corner of the dialog/window. | |||||||||||||||||||||||||
Remarks | This method never fails. | |||||||||||||||||||||||||
Method | BOOL GetShowSplitterGrip(LPCTSTR splitContainerName, BOOL & bShow); |
|||||||||||||||||||||||||
Description | Gets whether or not the splitter grip is visible for a split container. | |||||||||||||||||||||||||
Parameters | splitContainerName |
Name of the split container that was created by a prior call to CWndResizer::CreateSplitContainer . |
||||||||||||||||||||||||
bShow |
Receives a boolean value. If this is TRUE , then the splitter grip is visible, otherwise the splitter grip is hidden. |
|||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed. The
-or-
|
|||||||||||||||||||||||||
Remarks | N/A | |||||||||||||||||||||||||
Method | BOOL Hook(CWnd * pWnd); |
|||||||||||||||||||||||||
Description | Places a hook into the WndProc chain. |
|||||||||||||||||||||||||
Parameters | pWnd |
A pointer to a CWnd that you want to resize and its child controls. |
||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
-or- This method already has been called once. |
|||||||||||||||||||||||||
Remarks |
You must call this method before calling any other method. The window that the |
|||||||||||||||||||||||||
Method | BOOL InvokeOnResized(); |
|||||||||||||||||||||||||
Description | Simulates resizing of the hooked-window. | |||||||||||||||||||||||||
Parameters | N/A |
No parameters. | ||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
|
|||||||||||||||||||||||||
Remarks |
This method sends a After creating the necessary panels and settings anchors, you would want to call this to apply the settings initially. |
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Sets the anchor of the specified panel (.NET analogy). | |||||||||||||||||||||||||
Parameters | panelName |
Name of a panel that was created by a prior call to CWndResizer::CreatePanel . |
||||||||||||||||||||||||
panelID |
An ID of a child control (window) of the hooked-window. | |||||||||||||||||||||||||
anchor |
Anchor value. See remarks. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. anchor contains the valid value. |
||||||||||||||||||||||||
FALSE |
Failed.
-or-
|
|||||||||||||||||||||||||
Remarks |
Note: A panel will never grow less than its allowed minimum size and more than its allowed maximum size. |
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description |
Sets whether or not paint should be automatically handled by CWndResizer . |
|||||||||||||||||||||||||
Parameters | bHandle |
TRUE if CWndResizer is to automatically handle WM_PAINT message. Otherwise FALSE. |
||||||||||||||||||||||||
Return values | TRUE |
Always returns TRUE | ||||||||||||||||||||||||
FALSE |
Never returns FALSE. | |||||||||||||||||||||||||
Remarks | Here is an example:
BOOL CTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
BOOL bOk = FALSE;
bOk = m_resizer.Hook(this);
ASSERT( bOk);
// turning off auto paint handle
m_resizer.SetAutoHandlePaint(FALSE);
m_resizer.SetShowResizeGrip(TRUE);
bOk = m_resizer.InvokeOnResized();
ASSERT( bOk);
return TRUE;
}
void CTestDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// Your custom drawing
CRect rect(10, 20, 60, 60);
CBrush brush(RGB(0,0,0));
dc.FillRect(rect, &brush);
// call CWndResizer::Draw method so it can draw
// any classes derived from CVisualPanel
m_resizer.Draw(&dc); // <= calling Draw method
}
|
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Sets the dock of the specified panel (.NET analogy). | |||||||||||||||||||||||||
Parameters | panelName |
Name of a panel that was created by a prior call to CWndResizer::CreatePanel . |
||||||||||||||||||||||||
panelID |
An ID of a child control (window) of the hooked-window. | |||||||||||||||||||||||||
uDock |
Dock value. See remarks. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
-or-
|
|||||||||||||||||||||||||
Remarks |
|
|||||||||||||||||||||||||
Method | BOOL SetFixedPanel(LPCTSTR splitContainerName, short panel); |
|||||||||||||||||||||||||
Description | Sets one of the panels of a split container to be fixed (.NET analogy). | |||||||||||||||||||||||||
Parameters | splitContainerName |
Name of a panel that was created by a prior call to CWndResizer::CreateSplitContainer . |
||||||||||||||||||||||||
panel |
ID of the fixed panel. If this contains 1, then the left panel (or the top panel if splitContainer is a vertical split container) is fixed, or if it is 2, then the right panel (or the bottom panel if splitContainer is a vertical split container). Otherwise, splitContainer has no fixed panel. |
|||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
|
|||||||||||||||||||||||||
Remarks |
As the hooked-window is resized, the fixed panel remains the same and the other panel resizes. Note: A panel will never grow less than its allowed minimum size and more than its allowed maximum size. |
|||||||||||||||||||||||||
Method | BOOL SetFlowDirection(LPCTSTR flowPanelName, short direction); |
|||||||||||||||||||||||||
Description | Sets the flow direction of the FlowPanel (.NET analogy). |
|||||||||||||||||||||||||
Parameters | flowPanelName |
Name of the split container that was created by a prior call to CWndResizer::CreateFlowLayoutPanel . |
||||||||||||||||||||||||
direction |
Flow direction of the FlowPanel . |
|||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
-or-
|
|||||||||||||||||||||||||
Remarks | Set direction to 1 to indicate left-to-right direction, any other value will indicate top-to-bottom direction. |
|||||||||||||||||||||||||
Method | BOOL SetFlowItemSpacingX(LPCTSTR flowPanelName, int nSpace); |
|||||||||||||||||||||||||
Description | Sets spacing between items in x-direction in FlowPanel . |
|||||||||||||||||||||||||
Parameters | flowPanelName |
Name of the split container that was created by a prior call to CWndResizer::CreateFlowLayoutPanel . |
||||||||||||||||||||||||
nSpace |
Space in pixels. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed. The
-or-
|
|||||||||||||||||||||||||
Remarks | If the flow direction is left-to-right, nSpace indicates the space between two items in the x-direction, otherwise it indicates the space between two columns of items. |
|||||||||||||||||||||||||
Method | BOOL SetFlowItemSpacingY(LPCTSTR flowPanelName, int & nSpace); |
|||||||||||||||||||||||||
Description | Gets the spacing between items in y-direction in the FlowPanel . |
|||||||||||||||||||||||||
Parameters | flowPanelName |
Name of the split container that was created by a prior call to CWndResizer::CreateFlowLayoutPanel . |
||||||||||||||||||||||||
nSpace |
Space in pixels. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
-or-
|
|||||||||||||||||||||||||
Remarks | If the flow direction is left-to-right, nSpace indicates the space between two items in the y-direction, otherwise it indicates the space between two rows of items. |
|||||||||||||||||||||||||
Method | BOOL SetIsSplitterFixed(LPCTSTR splitContainerName , BOOL fixed); |
|||||||||||||||||||||||||
Description | Sets whether or not the splitter is set to fixed for a split container (.NET analogy). | |||||||||||||||||||||||||
Parameters | splitContainerName |
Name of the split container that was created by a prior call to CWndResizer::CreateSplitContainer . |
||||||||||||||||||||||||
fixed |
A boolean value. If this is TRUE , then the splitter is fixed, otherwise the splitter is free to be moved by mouse. |
|||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
|
|||||||||||||||||||||||||
Remarks | If the splitter is set to fixed, user cannot move the splitter using mouse. | |||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Sets the maximum size of the specified panel (.NET analogy). | |||||||||||||||||||||||||
Parameters | panelName |
Name of a panel that was created by a prior call to CWndResizer::CreatePanel . |
||||||||||||||||||||||||
panelID |
An ID of a child control (window) of the hooked-window. | |||||||||||||||||||||||||
size |
Minimum size of the panel. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
-or-
|
|||||||||||||||||||||||||
Remarks | If panelName or panelID refers to a panel that is part of a horizontal split container, then the cy member of size should be ignored. If panelName or panelID refers to a panel that is part of a vertical split container, then the cx member of size should be ignored. |
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Sets the minimum size of the specified panel (.NET analogy). | |||||||||||||||||||||||||
Parameters | panelName |
Name of a panel that was created by a prior call to CWndResizer::CreatePanel . |
||||||||||||||||||||||||
panelID |
An ID of a child control (window) of the hooked-window. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
-or-
|
|||||||||||||||||||||||||
Remarks | If panelName or panelID refers to a panel that is part of a horizontal split container, then the cy member of size should be ignored. If panelName or panelID refers to a panel that is part of a vertical split container, then the cx member of size should be ignored. |
|||||||||||||||||||||||||
Method |
|
|||||||||||||||||||||||||
Description | Sets the name of the parent of the specified panel. | |||||||||||||||||||||||||
Parameters | panelName |
Name of a panel that was created by a prior call to CWndResizer::CreatePanel . |
||||||||||||||||||||||||
panelID |
An ID of a child control (window) of the hooked-window. | |||||||||||||||||||||||||
parentID |
Name of the parent. | |||||||||||||||||||||||||
parentName |
Name of the parent. | |||||||||||||||||||||||||
Return values | TRUE |
Succeeded. parentName contains a valid value. |
||||||||||||||||||||||||
FALSE |
Failed. The size value should be ignored.
-or-
|
|||||||||||||||||||||||||
Remarks |
This should not be thought of as the Win32 Set |
|||||||||||||||||||||||||
Method | void SetShowResizeGrip(BOOL show = TRUE); |
|||||||||||||||||||||||||
Description | Sets a flag indication if a resize grip will be drawn on the lower-right corner of the hooked-window. | |||||||||||||||||||||||||
Parameters | show |
TRUE if the resize grip should be drawn, otherwise FALSE . |
||||||||||||||||||||||||
Return values | N/A |
No return values. | ||||||||||||||||||||||||
Remarks | This method never fails. | |||||||||||||||||||||||||
Method | BOOL SetShowSplitterGrip(LPCTSTR splitContainerName, BOOL bShow); |
|||||||||||||||||||||||||
Description | Sets a flag indication whether to show or hide a gripper for the splitter of a split container. | |||||||||||||||||||||||||
Parameters | splitContainerName |
Name of the split container that was created by a prior call to CWndResizer::CreateSplitContainer . |
||||||||||||||||||||||||
bShow |
TRUE if the resize grip should be drawn, otherwise hidden. |
|||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
-or-
|
|||||||||||||||||||||||||
Remarks | This method never fails. | |||||||||||||||||||||||||
Method | BOOL Unhook(); |
|||||||||||||||||||||||||
Parameters | N/A |
No parameters. | ||||||||||||||||||||||||
Return values | TRUE |
Succeeded. | ||||||||||||||||||||||||
FALSE |
Failed.
|
|||||||||||||||||||||||||
Remarks |
You do not have to call this method. This method is atomically called when the hooked-window receives a |
Points of Interest
This solution does not require you to calculate any numbers on your part. This solution encapsulates all the functionalities in the CWndResizer
.
One can re-design it such that it exposes other objects (CPanel
, CSplitContainer
, etc.). The reason I designed it this way is because I did not want the user to have to know too many objects, and to simplify memory allocation and de-allocation.
Another thing is that it depends on MFC classes (CWnd
etc.); again, you can remove all references to MFC classes and use pure Win32 APIs.
History
- 13 Jan 2011: Article updated to include new features,
Docking
andFlowLayoutPanel
- 25 Feb 2011:
CWndResizer::UnHook
method changed as per member 2272507's comments - 16 Mar 2011: Updated demo and source code
- 23 May 2011: Updated demo and source code
- 1 Aug 2011: Updated demo and source code
- 17 Aug 2011: Updated demo and source code - now supports scrolling on
CFormView
- 7 Dec 2011: Updated demo and source code
- 25 Jan 2013: New example added (Example 11) and a bug fixed
- 28 Jun 2013: Updated source code
- 9 Nov 2013: Error in Example 9 was fixed after reported by users
- 20 Oct 2014: Added three new methods:
Draw(CPaintDC * pDC)
,GetAutoHandlePaint()
andSetAutoHandlePaint(BOOL bHandle)
. These help when you have your custom painting. See documentation above for details. - 20 Oct 2014: Reported bugs fixed