Using WTL's Built-in Dialog Resizing Class for MFC






4.78/5 (10 votes)
WTL programming for MFC developers - resizing dialogs & formviews

Introduction
Once, I wanted to write resizing dialog in the program written for MFC. Having seen that is ready on this theme, I found the CDialogResize class. The class is good and easy to use, but is written for WTL. I tried to write it in WTL, basically it is quite good, but with MFC it is more habitual. So I decided to copy CDialogResize
under MFC. The name didn't change, for my classes I use namespace dimrad
.
Adding CDialogResize
You begin by adding CDialogResize
to the inheritance list of your dialog class.
// CMFCWTLDLGDlg dialog
class CMFCWTLDLGDlg : public CDialog, public dimrad::CDialogResize<CMFCWTLDLGDlg>
CDialogResize
is declared in mfcdialogresize.h, so add that header to your include
s if it isn't there already.
Next, add a new resize map to the dialog class that lists which controls in the dialog will be resized.
#include "mfcdialogresize.h"
// CMFCWTLDLGDlg dialog
class CMFCWTLDLGDlg : public CDialog, public dimrad::CDialogResize<CMFCWTLDLGDlg>
{
...
// Resizing map
public:
BEGIN_DLGRESIZE_MAP(CMFCWTLDLGDlg)
...
END_DLGRESIZE_MAP()
...
}
I'll describe how to fill in this map in the "Setting up the resize map" section.
Next, overload function OnInitDialog()
, if you haven't done it already. And add function OnSize()
to process WM_SIZE
message.
#include "mfcdialogresize.h"
// CMFCWTLDLGDlg dialog
class CMFCWTLDLGDlg : public CDialog, public dimrad::CDialogResize<CMFCWTLDLGDlg>
{
...
// Resizing map
public:
BEGIN_DLGRESIZE_MAP(CMFCWTLDLGDlg)
...
END_DLGRESIZE_MAP()
...
// Overloads
virtual BOOL OnInitDialog();
...
// Generated message map functions
DECLARE_MESSAGE_MAP()
...
afx_msg LRESULT OnSize(WPARAM wParam, LPARAM lParam);
...
}
That's all for your dialog header file. Now let's open the implementation file.
First add a new message map entry for WM_SIZE
message.
...
BEGIN_MESSAGE_MAP(CMFCWTLDLGDlg, CDialog)
...
ON_MESSAGE(WM_SIZE, &OnSize)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
...
Next, add a call of DlgResize_Init()
function to OnInitDialog()
function definition.
...
BOOL CMFCWTLDLGDlg::OnInitDialog()
{
CDialog::OnInitDialog();
...
// TODO: Add extra initialization here
DlgResize_Init();
return TRUE; // return TRUE unless you set the focus to a control
}
...
And at last, add an implementation of OnSize()
function.
...
LRESULT CMFCWTLDLGDlg::OnSize(WPARAM wParam, LPARAM lParam)
{
BOOL bHandled = FALSE;
return dimrad::CDialogResize<CMFCWTLDLGDlg>::OnSize
(WM_SIZE, wParam, lParam, bHandled);
}
...
Ok the class is ready. It does nothing, but you can use it many times from this point. Usually it is necessary to change only a class name also in a template CDialogResize<>
.
Initializing CDialogResize
CDialogResize
is initialized by calling DlgResize_Init()
. Its prototype is:
void DlgResize_Init(
bool bAddGripper = true,
bool bUseMinTrackSize = true,
DWORD dwForceStyle = WS_CLIPCHILDREN,
bool bUseScrollView = false,
SIZE *pszMin = NULL,
int client_cx = 0,
int client_cy = 0);
The parameters are:
bAddGripper
: This controls whetherCDialogResize
adds a size box to the bottom-right corner of the dialog. Passtrue
to add the size box, orfalse
to not add it.bUseMinTrackSize
: This parameter controls whetherCDialogResize
restricts the minimum size of the dialog. If you passtrue
, the dialog is not allowed to be sized smaller than its initial size (as stored in the resource file). Passfalse
if you don't want to restrict the dialog's minimum size.dwForceStyle
: Specifies window styles to apply to the dialog. The default value is usually sufficient.bUseScrollView
: Passtrue
- for scrolling in views, such asCFormView
.pszMin
: Specifies window minimal size.client_cx
: Specifies space size from left.client_cy
: Specifies space size from top. Used when dialog has a menu or another unresizable window.
Setting Up the Resize Map
The dialog resize map tells CDialogResize
which controls to move or size. An entry looks like this:
DLGRESIZE_CONTROL(ControlID, Flags)
ControlID
is the ID of the dialog control. The possible flags and their meanings are:
DLSZ_SIZE_X
: Resize the width of the control as the dialog resizes horizontally.DLSZ_SIZE_Y
: Resize the height of the control as the dialog resizes vertically.DLSZ_MOVE_X
: Move the control horizontally as the dialog resizes horizontally.DLSZ_MOVE_Y
: Move the control vertically as the dialog resizes vertically.DLSZ_REPAINT
: Invalidate the control after every move/resize so it repaints every time.
Note that you cannot move and size a control in the same dimension. If you specify, say DLSZ_MOVE_X
and DLSZ_SIZE_X
together, the size flag is ignored.
You can also group controls together so that they move and size proportionally to each other.
BEGIN_DLGRESIZE_GROUP()
...
END_DLGRESIZE_GROUP()
Features of resize map:
- The control can meet more than once.
- The control not included in group moves rather its current position.
- The control included in group is resized taking into account its initial position, but without a current position.
- It is possible to include the control in several groups. Though its position will be affected only by the last group, this reception allows to influence with difficulty others controls. But it is not necessary to forget about sense of proportion.
- There cannot be enclosed groups of controls.
// Resizing map
public:
BEGIN_DLGRESIZE_MAP(CMFCWTLDLGDlg)
DLGRESIZE_CONTROL(IDC_TAB1, DLSZ_SIZE_X | DLSZ_SIZE_Y)
DLGRESIZE_CONTROL(IDC_BUTTON1, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_BUTTON2, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_BUTTON3, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_STATIC1, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_X | DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDCANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y)
END_DLGRESIZE_MAP()
Reference
I have taken some information from the article, Using WTL's Built-in Dialog Resizing Class because it was the basis of my work.
History
- 30th September, 2011: Initial version