How to make a resizable dialog bar in Microsoft Foundation Classes (MFC) (143255)
The information in this article applies to:
- The Microsoft Foundation Classes (MFC), when used with:
- Microsoft Visual C++, 32-bit Editions 2.0
- Microsoft Visual C++, 32-bit Editions 2.1
- Microsoft Visual C++, 32-bit Editions 2.2
- Microsoft Visual C++, 32-bit Editions 4.0
- Microsoft Visual C++, 32-bit Enterprise Edition 5.0
- Microsoft Visual C++, 32-bit Enterprise Edition 6.0
- Microsoft Visual C++, 32-bit Professional Edition 5.0
- Microsoft Visual C++, 32-bit Professional Edition 6.0
- Microsoft Visual C++, 32-bit Learning Edition 6.0
- Microsoft Visual C++ .NET (2002)
- Microsoft Visual C++ .NET (2003)
This article was previously published under Q143255 Note Microsoft Visual C++ .NET 2002 and Microsoft Visual C++ .NET 2003 support both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model. The information in this article applies only to unmanaged Visual C++ code. SUMMARY The default MFC implementation of CDialogBar does not allow
for the dialog bar to be resizable when it is floating. If the dialog bar
contains controls that are sensibly resized, the programmer may want to make
the dialog bar resizable by using the technique described in this article.
To make the dialog bar resizable when using versions of MFC earlier
than version 4.0:
- Change the style of the mini frame window enclosing the
floating dialog bar so that it is resizable.
- Override CDialogBar to provide a CalcFixedLayout, which
allows the dialog bar and its controls to be resized.
To make the dialog bar resizable when using MFC version 4.0 or
later, you can use the built-in support for resizable control bars. However,
dialog bars do not get this behavior by default. To make a dialog bar
resizable:
- Use the new CBRS_SIZE_DYNAMIC style when creating the
dialog bar.
- Add code to an override of the new CalcDynamicLayout()
function.
MORE INFORMATION
For more information about how to create a DialogBar class, click the following article number to view the article in the Microsoft Knowledge Base:
185672
How to initialize child controls in a derived CDialogBar
For versions of MFC earlier than version 4.0 CDialogBar contains an embedded member variable m_sizeDefault of
type CSize. On creation, m_sizeDefault is set to the size of the dialog
template embedded in the dialog bar. Whenever the dialog bar is resized or
repositioned, MFC calls CDialogBar::CalcFixedLayout(). This member function is
intended to return the appropriate size of the control bar; for CDialogBar,
CalcFixedLayout() usually returns m_sizeDefault. This causes the dialog bar to
always snap back to its default size. To create a resizable dialog
bar, you must ensure that the following things are handled in some manner by an
application:
- The CMiniDockFrameWnd surrounding the floating dialog bar
must have its window styles changed so that it is resizable.
- A member variable must be added to a class derived from
CDialogBar to represent the appropriate floating size.
- CalcFixedLayout() must be overridden in this class to set
and return the floating size of the dialog bar when the dialog bar is being
resized.
With the appropriate tests, both 1 and 3 can be implemented in
CalcFixedLayout(). See the "Sample Code" section of this article for an example
of this. For MFC version 4.0 and later In MFC 4.0 and higher, control bars support the new
CBRS_SIZE_DYNAMIC style. CBRS_SIZE_DYNAMIC allows a floating control bar to be
dynamically resized when the user drags the control bar's border. The virtual
function CControlBar::CalcDynamicLayout() has been added to determine the size
that a control bar should be resized to. CalcDynamicLayout() is
called for CBRS_SIZE_DYNAMIC control bars when the border of a floating control
bar is dragged and when the control bar is docked or floated. The default
CControlBar implementation simply calls CalcFixedLayout(), which prevents
control bar objects from resizing unless CalcDynamicLayout() is overridden.
CDialogBar does not override CalcDynamicLayout(), so by default, dialog bars
are not resizable. Therefore, to make a resizable dialog bar using
MFC 4.0:
- Create a new class derived from CDialogBar and override the
CalcDynamicLayout() function. Depending on the behavior you want, it may be
necessary to add a member variable to the class.
- Create an instance of this class using the
CBRS_SIZE_DYNAMIC style bit. Dialog bars are typically created in
CMainFrame::OnCreate():
if (!m_wndDialogBar.Create(this, IDD_DIALOGBAR,
CBRS_TOP | CBRS_SIZE_DYNAMIC, 777))
{
TRACE0("Failed to create dialogbar\n");
return -1;
}
m_wndDialogBar.EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndDialogBar);
Note You must use the WS_CHILD style with the IDD_DIALOGBAR dialog
template. Do not use the WS_VISIBLE style or any other style. See the
"Sample Code" section in this article for a examples of this. Sample codeSample code for MFC versions prior to Visual C++ 4.0
/* Compile options needed: Default
*/
// RSZDLGBR.H : header file
//
class CResizableDlgBar : public CDialogBar
{
// Construction
public:
BOOL Create( CWnd* pParentWnd, UINT nIDTemplate, UINT nStyle,
UINT nID, BOOL = TRUE);
BOOL Create( CWnd* pParentWnd, LPCTSTR lpszTemplateName,
UINT nStyle, UINT nID, BOOL = TRUE);
// Attributes
public:
CSize m_sizeDocked;
CSize m_sizeFloating;
BOOL m_bChangeDockedSize; // Indicates whether to keep
// a default size for docking
// Operations
public:
// Overrides
virtual CSize CalcFixedLayout(BOOL bStretch, BOOL bHorz);
// Implementation
public:
};
/////////////////////////////////////////////////////////////////////
// RSZDLGBR.CPP : implementation file
//
#include "stdafx.h"
#include <afxpriv.h>
#include "ResizableDlgBar.h"
#include "resource.h"
////////////////////////////////////////////////////////////////////
// CResizableDlgBar Construction/Destruction
BOOL CResizableDlgBar::Create( CWnd* pParentWnd, UINT nIDTemplate,
UINT nStyle, UINT nID, BOOL bChange)
{
if(!CDialogBar::Create(pParentWnd,nIDTemplate,nStyle,nID))
return FALSE;
m_bChangeDockedSize = bChange;
m_sizeFloating = m_sizeDocked = m_sizeDefault;
return TRUE;
}
BOOL CResizableDlgBar::Create( CWnd* pParentWnd,
LPCTSTR lpszTemplateName,
UINT nStyle, UINT nID, BOOL bChange)
{
if (!CDialogBar::Create( pParentWnd, lpszTemplateName,
nStyle, nID))
return FALSE;
m_bChangeDockedSize = bChange;
m_sizeFloating = m_sizeDocked = m_sizeDefault;
return TRUE;
}
////////////////////////////////////////////////////////////////////
// Overloaded functions
CSize CResizableDlgBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
if (IsFloating())
{
// Get the parent mini frame wnd
CMiniDockFrameWnd* pFrame =
((CMiniDockFrameWnd*)m_pDockBar->GetParent());
CRect rcFrame;
pFrame->GetClientRect(&rcFrame);
// Is its size (0,0)? If so, it was just floated
CSize sizerc(rcFrame.right - rcFrame.left,
rcFrame.bottom - rcFrame.top);
if (!((sizerc.cx <= 0) && (sizerc.cy <= 0)))
return ((m_bChangeDockedSize) ?
m_sizeDocked = m_sizeFloating = sizerc :
m_sizeFloating = sizerc);
else
{
// Modify Style when dialog bar is first floated
pFrame->ModifyStyle(MFS_MOVEFRAME, WS_THICKFRAME, 0);
m_dwStyle |= MFS_THICKFRAME;
m_dwStyle |= WS_THICKFRAME;
m_dwStyle &= ~MFS_MOVEFRAME;
// Return last floated size
return m_sizeFloating;
}
}
if (bStretch) // if not docked stretch to fit
return CSize(bHorz ? 32767 : m_sizeDocked.cx,
bHorz ? m_sizeDocked.cy : 32767);
else
return m_sizeDocked;
}
Sample code for MFC included with Visual C++ 4.0 and above
/* Compile options needed: Default
*/
// ResizableDlgBar.h : header file
//
class CResizableDlgBar : public CDialogBar
{
// Construction
public:
BOOL Create( CWnd* pParentWnd, UINT nIDTemplate, UINT nStyle,
UINT nID, BOOL = TRUE);
BOOL Create( CWnd* pParentWnd, LPCTSTR lpszTemplateName,
UINT nStyle, UINT nID, BOOL = TRUE);
// Attributes
public:
CSize m_sizeDocked;
CSize m_sizeFloating;
BOOL m_bChangeDockedSize; // Indicates whether to keep
// a default size for docking
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CResizableDlgBar)
//}}AFX_VIRTUAL
virtual CSize CalcDynamicLayout( int nLength, DWORD dwMode );
// Implementation
public:
// Generated message map functions
protected:
//{{AFX_MSG(CResizableDlgBar)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////
// ResizableDlgBar.cpp : implementation file
//
#include "stdafx.h"
#include "ResizableDlgBar.h"
////////////////////////////////////////////////////////////////////
// CResizableDlgBar Construction/Destruction
BOOL CResizableDlgBar::Create( CWnd* pParentWnd, UINT nIDTemplate,
UINT nStyle, UINT nID, BOOL bChange)
{
if(!CDialogBar::Create(pParentWnd,nIDTemplate,nStyle,nID))
return FALSE;
m_bChangeDockedSize = bChange;
m_sizeFloating = m_sizeDocked = m_sizeDefault;
return TRUE;
}
BOOL CResizableDlgBar::Create( CWnd* pParentWnd,
LPCTSTR lpszTemplateName, UINT nStyle,
UINT nID, BOOL bChange)
{
if (!CDialogBar::Create( pParentWnd, lpszTemplateName,
nStyle, nID))
return FALSE;
m_bChangeDockedSize = bChange;
m_sizeFloating = m_sizeDocked = m_sizeDefault;
return TRUE;
}
////////////////////////////////////////////////////////////////////
// Overloaded functions
CSize CResizableDlgBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
// Return default if it is being docked or floated
if ((dwMode & LM_VERTDOCK) || (dwMode & LM_HORZDOCK))
{
if (dwMode & LM_STRETCH) // if not docked stretch to fit
return CSize((dwMode & LM_HORZ) ? 32767 : m_sizeDocked.cx,
(dwMode & LM_HORZ) ? m_sizeDocked.cy : 32767);
else
return m_sizeDocked;
}
if (dwMode & LM_MRUWIDTH)
return m_sizeFloating;
// In all other cases, accept the dynamic length
if (dwMode & LM_LENGTHY)
return CSize(m_sizeFloating.cx, (m_bChangeDockedSize) ?
m_sizeFloating.cy = m_sizeDocked.cy = nLength :
m_sizeFloating.cy = nLength);
else
return CSize((m_bChangeDockedSize) ?
m_sizeFloating.cx = m_sizeDocked.cx = nLength :
m_sizeFloating.cx = nLength, m_sizeFloating.cy);
}
BEGIN_MESSAGE_MAP(CResizableDlgBar, CDialogBar)
//{{AFX_MSG_MAP(CResizableDlgBar)
// NOTE - the ClassWizard will add and remove mapping macros
here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////
// CResizableDlgBar message handlers
/////////////////////////////////////////////////////////////////////
REFERENCES MFC Technical Note 31.
Modification Type: | Major | Last Reviewed: | 10/9/2006 |
---|
Keywords: | kbcode kbFAQ kbhowto kbMFCCtrlBar KbUIDesign KB143255 kbAudDeveloper |
---|
|