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.
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"
class CMFCWTLDLGDlg : public CDialog, public dimrad::CDialogResize<CMFCWTLDLGDlg>
{
...
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"
class CMFCWTLDLGDlg : public CDialog, public dimrad::CDialogResize<CMFCWTLDLGDlg>
{
...
public:
BEGIN_DLGRESIZE_MAP(CMFCWTLDLGDlg)
...
END_DLGRESIZE_MAP()
...
virtual BOOL OnInitDialog();
...
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)
END_MESSAGE_MAP()
...
Next, add a call of DlgResize_Init()
function to OnInitDialog()
function definition.
...
BOOL CMFCWTLDLGDlg::OnInitDialog()
{
CDialog::OnInitDialog();
...
DlgResize_Init();
return TRUE; }
...
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 whether CDialogResize
adds a size box to the bottom-right corner of the dialog. Pass true
to add the size box, or false
to not add it.bUseMinTrackSize
: This parameter controls whether CDialogResize
restricts the minimum size of the dialog. If you pass true
, the dialog is not allowed to be sized smaller than its initial size (as stored in the resource file). Pass false
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
: Pass true
- for scrolling in views, such as CFormView
.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.
Resize map for sample project:
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
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.