In the MFC Application Wizard, set the Application Type to Dialog Based Practical Learning: Using the Wizard to create a Dialog-Based Application 1.. Here is an example: The Paragraph
Trang 1Practical Learning: Creating a Top-Most Window
1 To create the dialog box with a thin border, check its Static Edge check box or set it
to True
2 To indicate that this dialog can accept dragged files, check its Accept Files check
box or set it to True
12.1.8 Creating the Dialog Resource File
As mentioned already, a dialog box means nothing except for the controls it is created to
host The controls are listed in a section that starts with the BEGIN and ends with the END keywords Here is an example:
If you design a dialog box and the first object of your application, you must save it before using it Even if you had decided to manually create the dialog box as a text file, you must save it before using it In both cases, whether saving the dialog box designed or the text file, saving it results in creating a resource file This file should have the rc extension
If your resource file is using some identifiers, which is the case for most or all controls you will use in your application, you must list them in a header file This file is traditionally called Resource.h or resource.h Each identifier must be listed using the following syntax:
#define Identifier Constant
When you save the resource file, Visual C++ automatically creates the resource header file and names it resource.h
After saving the resource file, it is still considered external to the application If you are using MSVC 6, you must add it to your project After it has been added to your project, you can continue working on the dialog box, adding, deleting, or manipulating the controls After doing that, if you save the resource, Visual C++ automatically makes the appropriate changes in the resource and the resource header files
Practical Learning: Saving the Resource File
1 If you are using MSVC 7, on the Standard toolbar, click the Save All button
If you are using MSVC 6:
a To save the dialog box, click the system Close button of the window that holds the dialog box
b This will display a window with a tree view that starts with Script1 Close its window also
Trang 2c You will receive a message box asking you whether you want to save the script Click Yes
d Locate the ExoDialog1 folder that was used to create the current project Display it in the Save In combo box
Change the name in the File Name with ExoDialog1
e Click Save
2 To add the resource to your application, on the main menu, click Project -> Add To Project -> Files…
3 Click ExoDialog1.rc and click OK
4 To verify that the dialog box has been added, in the Workspace, click the
ResourceView tab and expand the ExoDialog1 Resources node Then expand the
Dialog folder and double-click IDD_EXERCISE_DLG
5 If you are using MSVC 7, on the Standard toolbar, the Save All Then
12.1.9 Creating a Class for the Dialog
After creating the resource for the dialog box, you must create a class that will be used to handle its assignment To do this, you must derive a class from CDialog In the header file of the dialog’s class, define an enumerator whose only member is called IDD and initialize it with the identifier of the dialog box Because the identifier is listed in the resource header file, you must include this resource header in the file in which you are using the dialog’s identifier
Practical Learning: Create the Dialog’s Class
1 To create a class for the dialog box, open the Exercise.cpp created earlier and add the following:
Trang 3return TRUE;
} CExerciseApp theApp;
2 Save All
A dialog box is based on the CDialog class As seen above, when creating your dialog box, you can derive a class from CDialog The CDialog class itself provides three
constructors as follows:
CDialog();
CDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL);
CDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL);
The default constructor, CDialog(), can be used to declare a variable whose behavior is
not yet known or, for one reason or another, cannot yet be defined When creating your class, you should also declare at least a default constructor
The identifier of the dialog box, such as IDD_DIALO G1, can be used as the first
argument, nIDTemplate, of a CDialog() constructor to create a dialog box from an
existing resource
If you are using a Win32 template to create your dialog box, pass the name of this
template as a string to a CDialog() constru ctor, lpszTemplateName
When implementing your default constructor, initialize the parent CDialog constructor
with the IDD enumerator declared in your class If your dialog box has an owner, specify
it as the pParentWnd argument If you set it to NULL, the application will be used as the
dialog’s parent
If you dynamically create objects for your application using your dialog class, it is a good idea to also declare and define a destructor This would be used to destroy such dynamic objects
Most other methods of a dialog box depend on circumstances we have not yet reviewed
Practical Learning: Creating a Dialog Box
1 Declare a default constructor and a destructor for your dialog class and implement them as follows:
class CExerciseDlg : public CDialog
Trang 4{ public:
enum { IDD = IDD_EXERCISE_DLG };
CExerciseDlg();
~CExerciseDlg();
};
CExerciseDlg::CExerciseDlg() : CDialog(CExerciseDlg::IDD) {
} CExerciseDlg::~CExerciseDlg() {
}
2 Before using the new class, declare a variable of it as follows:
BOOL CExerciseApp::InitInstance() {
One of the scenarios in which you use a dialog box is to create an application that is centered around a dialog box In this case, if either there is no other window in your application or all the other windows depend on this central dialog box, it must be created
as modal Such an application is referred to as dialog-based There are two main techniques you can use to create a dialog-based application: from scratch or using one of Visual C++ wizards After creating a dialog resource and deriving
a class from CDialog, you can declare a variable of your dialog class To display your
dialog box as modal, you can call the CDialog::DoModal() method in your CWinApp::InitInstance() method Its syntax is:
virtual int DoModal();
This method by itself does nothing more than displaying a dialog box as modal We will learn that you can use this method to find out how the user had closed such a dialog box
Trang 5Practical learning: Displaying a Modal Dialog Box
1 To display the dialog box as modal, in the InitInstance() event of your CWinApp derived class, call the DoModal() method using your dialog variable:
} CExerciseDlg::~CExerciseDlg() {
} BOOL CExerciseApp::InitInstance() {
2 Test the application
Trang 63 Close it and return to MSVC
12.2.2 The MFC Wizard for a Dialog-Based Application
Microsoft Visual C++ provides an easier way to create an application that is mainly based on a dialog box To use this technique, start a new project and specify that you want to create an MFC Application In the MFC Application Wizard, set the Application Type to Dialog Based
Practical Learning: Using the Wizard to create a Dialog-Based Application
1 On the main menu, click File -> New -> Project
2 In the New Project dialog box, in the Templates list, click MFC Application
3 Set the Project Name to ExoDialog2
Trang 74 Clic k OK
5 In the MFC Application Wizard dialog box, click Application Type and, on the right
side, click the Dialog Based radio button
6 Click User Interface Features and click About Box to remove its check box
7 Under Dialog Title, select the text and replace it with Dialog Box Exercise
8 Click Advance Features to see its content
9 Click Generated Classes
10 In the Generated Classes list, click CExoDialog2App and, in the Class Name, replace
the text with CExerciseApp
11 In the Generated Classes list, click CExoDialog2Dlg
In the Class Name, replace the name with CExerciseDlg
In the h file edit box, replace the name of the file with ExerciseDlg.h
In the cpp file edit box, replace the name of the file with ExerciseDlg.cpp Make sure the Base Class is set to CDialog
Trang 812 Click Finish
13 Test the application and return to MSVC
12.2.3 A Modal Dialog Box in an Application
Some applications require various dialog boxes to complete their functionality When in case, you may need to call one dialog box from another and display it as modal Here is
an example:
The Paragraph dialog box of WordPad is a modal dialog box: when it is displaying, the user cannot use any other part of WordPad unless he or she closes this object first
Since a dialog box is created using a class, the first thing you must do is to include the
header file of the CDialog object whose box you want to call
To call one dialog box from another window, select the event (or message) from where you would make the call Declare a variable of the other class and use the
CDialog::DoModal() method to display the other object as a modal dialog box
Calling a dialog box from the menu of a frame-based application is done the same way as calling it from a dialog box
Trang 9Practical Learning: Adding a Dialog Box to an Existing Application
1 Start a new MFC Application project named SDIAndDlg
2 Create it as a Single Document and click Finish
3 To add a dialog box, on the main menu, click Project -> Add Resource…
4 In the Add Resource dialog box, double -click Dialog
5 To create a class for the new dialog box, right-click it and click Add Class…
6 In the MFC Class Wizard, specify the Class Name as CExerciseDlg
7 In the Base Class combo box, select CDialog and click Finish
8 Display the menu by double-clicking IDR_MAINFRAME under the Menu folder of the Resource View tab
9 Click View and click the first empty item under it Type – and press Enter to add a separator
10 In the menu item under the new separator, type &Exercise… and press Enter
11 Right-click the new Exercise menu item and click Add Event Handler…
12 In the Message Type, access the COMMAND item In the Class List, click CMainFrame Accept the Function Handler Name then click Finish Add And Edit
13 Change the file as follows:
// TODO: Add your command handler code here
CExerciseDlg Dlg;
Dlg.DoModal();
}
14 Execute the application On its main menu, click View -> Exercise…
15 After using the dialog box, close it and close the application to return to MSVC
12.3 Property Sheets and Wizards
12.3.1 Introduction to Property Pages
In some applications, you may want to add many but necessary and useful controls to a dialog box You can solve this problem in three main ways:
Trang 10?? You may have to tremendously increase the width and the height of your dialog box Although this solution works sometimes, it may have the disadvantage of producing a highly crowded dialog box
?? You can hide some controls and display them only when needed, such as in response to a user clicking a button The concept of this type of application involves an unpredictable and non-practical design It also eventually requires a lot of coding
?? The third solution involves the user of property pages
A property page is a dialog box, that can be positioned in front of, or behind of, another This has the advantage of providing various dialog boxes that are “physically” grouped as one entity Each part is represented by a tab The tabs are usually positioned in the top section and each is used to identify a particular page:
To use a property page, the user clicks one The page clicked besomes positioned in front
of the other(s) The user can click another tab to select a different page:
12.3.2 Creating Property Pages
A property page is designed from a dialog box and it must have the following characteristics:
?? Style: Child or WS_CHILD
?? Border: Thin or WS_POPUP
Trang 11?? Title Bar: True or WS_CAPTION
?? System Menu: False or no WS_SYSMENU
?? Visible: False or no WS_VIS IBLE
?? Disabled: True or WS_DISABLED
You can create each property page like that and with the same size If you create dialog boxes that have different sizes, the dimensions of the taller and/or wider will be applied
to all the other property pages when they come up
Visual C++ makes it easy to create resources for property pages by displaying the Add Resource dialog box, expanding the Dialog node and selecting one of the IDD_PROPPAGE_X items
After adding the resource for the property page, as done for a dialog box, you can add a class for it Unlike the regular dialog box, a property page is based on the
CPropertyPage class which itself is based on CDialog The CPropertyPage class is declared in the afxdlgs.h header file
Practical Learning: Creating Pro perty Pages
1 Using either MFC AppWizard (exe) or MFC Application, start a New Project named Geometry
2 Create it as Dialog-Based with no About Box and set the Dialog Title to Quadrilateral
3 Change the Class Name of the dialog to CQuadrilateral
4 Change the name of the header of the dialog to Quadrilateral.h and the name of the source file to Quadrilateral.cpp
Trang 125 Click Finish
6 On the dialog, click TODO and press Delete three times to delete the TODO line, the
OK and the Cancel buttons
7 While the dialog box is displaying, access its properties
Change its ID to IDD_QUADRILATERAL
If necessary, change its Caption to Quadrilateral Change its Style value to Child
Change its Border to Thin Remove the check mark of the System Menu check box or set it to False Set its Visible property to False or remove its check mark
If necessary, remove the check mark of the Disabled check box or set it to False
8 Save All
9 From the Controls toolbox, click the Edit Box button and click anywhere in the dialog box
10 Open the header file of the dialog
Change its base class to CPropertyPage Change the value of the IDD to IDD_QUADRILATERAL
class CQuadrilateral : public CPropertyPage
{ // Construction public:
CQuadrilateral(CWnd* pParent = NULL); // standard constructor // Dialog Data
//{{AFX_DATA(CQuadrilateral)
enum { IDD = IDD_QUADRILATERAL };
// NOTE: the ClassWizard will add data members here //}}AFX_DATA
11 Change the source file of the CQuadrilateral class as follows:
// Quadrilateral.cpp : implementation file //
#include "stdafx.h"
#include "Geometry.h"
#include "Quadrilateral.h"
Trang 13#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE static char THIS_FILE[] = FILE ;
#endif /////////////////////////////////////////////////////////////////////////////
// CQuadrilateral dialog CQuadrilateral::CQuadrilateral(CWnd* pParent /*=NULL*/)
: CPropertyPage(CQuadrilateral::IDD)
{ //{{AFX_DATA_INIT(CQuadrilateral)
// NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
} void CQuadrilateral::DoDataExchange(CDataExchange* pDX) {
ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP
END_MESSAGE_MAP() /////////////////////////////////////////////////////////////////////////////
// CQuadrilateral message handlers BOOL CQuadrilateral::OnInitDialog() {
CPropertyPage::OnInitDialog();
SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control }
// If you add a minimize button to your dialog, you will need the code below // to draw the icon For MFC applications using the document/view model, // this is automatically done for you by the framework
void CQuadrilateral::OnPaint() {
if (IsIconic()) {
CPaintDC dc(this); // device context for painting
Trang 14SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon dc.DrawIcon(x, y, m_hIcon);
} else {
CPropertyPage::OnPaint();
} } HCURSOR CQuadrilateral::OnQueryDragIcon() {
return (HCURSOR) m_hIcon;
17 Delete the TODO line
18 Change the ID of the new dialog to IDD_CIRCULAR and its Caption to Circular
19 On the Controls toolbox, click the Slider button and click anywhere on the dialog box
20 If you are using MSVC 6, right-click the Circular dialog box and click ClassWizard
A message box will display Read it Select Create A New Class and click OK
Trang 15Type CCircular and, in the Base Class combo box, select CPropertyPage
Click OK twice
If you are using MSVC 7, right-click the dialog box and click Add Class…
Type the Class Name as CCircular and, in the Base Class combo box, select CPropertyPage
Click Finish
21 Add another IDD_PROPPAGE_LARGE property page Delete its TODO line
Change its ID to IDD_G3D and its Caption to 3-Dimensions
Trang 1622 On the Controls toolbox, click the Check Box button and click anywhere on the dialog
23 Create or Add A New Class for the IDD_G3D dialog box
Name it CGeome3D Base it on the CPropertyPage class
24 Change the design of the IDR_MAINFRAME icon as follows:
25 Save All
12.3.3 Property Sheets
To implement its functionality, the property pages are put together and kept as an entity
by an object called a property sheet The property sheet acts as their parent Like other controls, we will see that the property pages must be added to a property sheet
There is no resource to create for a property sheet A property sheet is based on the
CPropertySheet class, which is not based on CDialog but it provides the same
functionality as dialog Therefore, a property sheet is sometimes called, or referred to as,
a dialog box Instead, CPropertySheet is based on the CWnd class Therefore, to implement your property page(s), you can simply declare a CPropertySheet variable and
use it to display the application or you can programmatically derive a class from
CPropertySheet The CPropertySheet class is declared in the afxdlgs.h header file
If you decide to directly use the CPropertySheet class, declare a variable for it where the
application will need to be displayed or instantiated, which could be in the
CWinApp::InitInstance() event To display the property sheet, call its DoModal()
method This could be done as follows:
BOOL CMyApp::InitInstance() {
CPropertySheet MySheet;
MySheet.DoModal();
}
Trang 17To specify your property pages as belonging to the property page, declare a variable for
each one of them Then, call the CPropertySheet::AddPage() method to add each
property page The syntax of this method is:
void AddPage(CPropertyPage *pPage);
This method takes the variable of each page and adds it as part of the property sheet Here
is an example:
BOOL CmyApp::InitInstance() {
If you want to have better access to the property sheet as a class, you should derive your
own class from CPropertySheet You will have the ability to use any or a combination
If you want to specify a title for the property sheet, you can call the
CPropertySheet::SetTitle() method Its syntax is:
void SetTitle(LPCTSTR lpszText, UINT nStyle = 0);
The first argument is a null terminated string that will be the new title If you want the caption to display the string starting with “Properties for”, pass a second argument as
PSH_PROPTITLE
Practical Learning: Creating a Property Sheet
1 In the Class View, right-click Geometry and click either New Class or Add -> Add Class…
2 If you are using MSVC 6, set the Class Type to MFC Class
If you are using MSVC 7, click MFC Class and click Open
Set the name of the class to CGeomeSheet
3 In the Base Class combo box, select CPropertySheet
Trang 184 Click OK or Finish
5 Change the source code of the CGeometryApp class as follows:
// Geometry.cpp : Defines the class behaviors for the application
#endif /////////////////////////////////////////////////////////////////////////////
// CGeometryApp BEGIN_MESSAGE_MAP(CGeometryApp, CWinApp) //{{AFX_MSG_MAP(CGeometryApp)
//}}AFX_MSG ON_COMMAND(ID_HELP, CWinApp::OnHelp) END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CGeometryApp construction
Trang 19CGeometryApp::CGeometryApp() {
} /////////////////////////////////////////////////////////////////////////////
// The one and only CGeometryApp object CGeometryApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CGeometryApp initialization BOOL CGeometryApp::InitInstance() {
AfxEnableControlContainer();
// Standard initialization
#ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL
#else Enable3dControlsStatic(); // Call this when linking to MFC statically
} else if (nResponse == IDCANCEL) {
} // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump
return FALSE;
}
6 Test the application
Trang 207 Return to MSVC and close the project (MSVC 6: File -> Close Workspace; MSVC 7: File -> Close Solution)
12.3.4 Wizard Pages
A wizard, like a property sheet, is a series of dialog boxes that are considered as one entity, tremendously saving the available space When put together, the dialog boxes are referred to as wizard pages Like the property pages, the wizard pages can help the programmer add more Windows controls than a single dialog box with the same dimension would allocate While the property pages are positioned one in front of the others in a z-axis, the wizard pages are positioned so that, when one displays, the others are completely hidden While a property page can be accessed by the user clicking its tab
to bring it to the front and send the others to the back, a wizard is equipped with buttons such as Back or Next
A wizard is created using the exact same approach as the property sheet Each involved dialog box is created with the same properties:
?? Style: Child
?? Border: Thin
?? Title Bar: True
?? System Menu: False
?? Visible: False
?? Disabled: True
Each page is based on the CPropertyPage class To display the wizard, use the CPropertySheet class in the exact same way as seen for the property pages above The
only difference is that, to make this a wizard, you must call the
CPropertySheet::SetWizardMode() method before calling DoModal() The syntax of the SetWizardMode() member function is:
void SetWizardMode();
Trang 21Practical Learning: Creating a Wizard
1 Open Windows Explorer or My Computer and display the contents of the parent folder that holds the previous exercise
2 In the right frame, right-click Geometry and click Copy
3 Right-click an unoccupied area in the same right frame and click Paste
4 Rename Copy of Geometry to WizardPages
5 Open the WizardPages project or solution
6 Access the CGeometry::InitInstance() event and change it as follows:
BOOL CGeometryApp::InitInstance() {
AfxEnableControlContainer();
// Standard initialization
#ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL
#else Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif CGeomeSheet GeoSheet("Geometric Calculations");
} else if (nResponse == IDCANCEL) {
} // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump
return FALSE;
}
7 Test the application
Trang 228 Return to MSVC
Trang 23Chapter 13: Control Design
? Forms
? Dialog Box’ Messages and Events
? Floating Windows
? Control Design
Trang 2413.1 Forms
13.1.1 Introduction
Like a dialog box, a form is the primary object used to host Windows contro ls to allow user interaction with the computer Like a dialog box, a form does not mean anything except for the controls it is hosting This means that a form by itself does not present any significant functionality but it can be equipped with characteristics that make it a valuable alternative to other view types
When using a form, the user typically interacts with the controls it is hosting These controls can be positioned anywhere on the form If there are too many controls or the controls are positioned so the occupied area is larger than the form can display at one time, the form would be equipped with scroll bars
A form is created using the CFormView class which is derived indirectly from CView through CScrollView
13.1.2 Form Creation
There are three main ways you can provide a form to an application
The easiest way to create a form is by using the AppWizard To do this, when creating
the application, set the Base Class to CFormView A document/view application would
be created with its view based on the CFormView class The wizard would have created
a Child window with no borders and no title bar (over all, you should not attempt to change the properties of this window) Also, if you create an application that supports databases, AppWizard would create a form that can be used on that database
If you have already created an application, for example based on CView, you can either
add a form view to the application, change the application's base view class into form view, or replace its view class with a form view If you add a form view to the application, the user would be prompted to select one of both documents when the applications comes up
The last option you have, which you should hardly do is to work from scratch in creating
a form view-based application The reason you should not spend time doing this is the amount of work involved that would not necessarily improve your application
Practical Learning: Creating a Form-Based Application
1 Display the New or the New Project dialog box and specify that you want to use MFC AppWizard or MFC Application
2 Set the Project Name to FormBased1
Trang 253 Click OK
4 Specify that you want to create a Single Document type of application
Trang 265 In the last step, in the Base Class combo box, select CformView
9 Press Ctrl + F5 to test the application
10 After viewing it, return to MSVC
11 Controls Designs on Forms and Dialog Boxes
13.2 Dialog Box Messages and Events
In this section, unless specified otherwise, the expressions “dialog box” or based object” refer to the regular dialog box, the property sheet, the property page, or the flat dialog-window that composes a form
“dialog-13.2.1 The Dialog Box as a Control Initializer
As the most regularly used host of Windows Controls, a dialog box most be able to handle messages that not only pertain to its own existence but also to the availability, visibility, and behaviors of the controls it is holding For example, if you create a control and position it on the dialog box, sometimes you will need to initialize, give it primary values Although the dialog box provides a constructor and even inherits the
WM_CREATE message along with the PreCreateWindow() event from its parent the CWnd class, if you need to initialize a control, the CDialog box and its cousins
CPropertySheet, CPropertyPage, and the form provide a special event you can use to do this
WM_INITDIALOG: The WM_INITDIALOG message fires the OnInitDialog() event
after a dialog, a property sheet, a property page, or a form has been created but before this
window is displayed It is the equivalent of the PreCreateWindow() event used by other
frame and view-based window This event should be your favorite place to initialize a control that is hosted by the dialog-based object Do not initialize controls in your
Trang 27dialog’s constructor Use the constructor only to allocate memory space for a dynamic
control using the new operator
If you create a dialog-based or a form-based application, AppWizard automatically
generates the WM_INITDIALOG message for you If you add a dialog box, a form, a
proeprty sheet, or a property page to an existing application, this message may not be
added automatically You would have to fire it In reality, the WM_INITDIALOG
message is inherited from the CDialog class Therefore, you would only be overriding it
Practical Learning: Generating Dialog Messages
1 Start a new MFC Application and name it DialogMessages
2 Create it as a Single Document and click Finish
3 To add a new object, display the Add Resource dialog box and double -click Dialog
4 Change its ID to IDD_DYNAMIC_DLG and its Caption to Dynamic Objects
5 Add a class for it Name it CDynamicDlg and base it on the CDialog class Click
Finish
6 To make sure you can display the dialog box, display the IDR_MAINFRAME menu Under View, add a separator Then add a menu item with the caption as
&Dynamic… and press En ter
8 Right-click the Dynamic menu item and click Add Event Handler…
9 Accept the Message type as COMMAND Accept the suggested Function Handler Name In the Class List, click CMainFrame then click Add and Edit
10 Implement the event as follows:
// MainFrm.cpp : implementation of the CMainFrame class //
// TODO: Add your command handler code here
CDynamicDlg Dlg;
Dlg.DoModal();
}
11 Test the application and return to MSVC
12 Click the Class View tab and, if necessary, expand the DynamicMessages node Right-click CDynamicDlg and click Add Variable…
13 In the Variable Type combo box, type CWnd * and, in the Variable Name edit box, type m_Panel
Trang 2814 Click Finish
15 In the constructor of the dialog, use the new operator to allocate memory for the dynamic control Then, in the destructor, destroy the control using the delete operator:
CDynamicDlg::CDynamicDlg(CWnd* pParent /*=NULL*/) : CDialog(CDynamicDlg::IDD, pParent)
, m_Panel(NULL) {
m_Panel = new CWnd;
} CDynamicDlg::~CDynamicDlg() {
delete m_Panel;
}
7 To fire the OnInitDialog event for the dialog, in the combo box of the Properties
window, CDynamicDlg should be displaying If not, in Class View, click CDynamicDlg
In the Properties window, click the Overrides button
8 Scroll down in the Proeprties window and click OnInitDialog Click its arrow and click <Add> OnInitDialog
Trang 299 Implement the event as follows:
BOOL CDynamicDlg::OnInitDialog() {
CDialog::OnInitDialog();
// TODO: Add extra initialization here
CRect Recto(10, 10, 176, 138);
m_Panel->Create("STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_DLGFRAME,
Recto, this, 0x166, NULL);
return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE
Trang 3013.2.2 Other Dialog-Based Windows Messages
WM_PAINT: After creating the dialog box, if you want to paint it or draw something on
it, such as changing its background color, use the WM_PAINT message If you create a
dialog or form-based application, this message is automatically generated by the wizard
If you add a dialog-based object to your application and need the OnPaint() event, you
would have to add it yourself
WM_CLOSE: As mentioned already, a regular dialog box, including a property sheet or
a wizard, is equipped with the system Close button on its title bar This allows the user to close it any time As a programmer, one of your jobs is to control your application, be able to predict “bad moves” from the user From example, imagine you create a dialog-based object without a Cancel button but with OK (like the most basic message box) If the user clicks the system Close button , you may not know what the
user did The WM_CLOSE message fires the OnClose() event when the user clicks the
system Close button It is important to understand that WM_CLOSE is a message
and not a method, meaning it sends a message, it does not take an action This implies
that the OnClose() event fires when the user makes an attempt to close the dialog but
before the dialog is actually closed
You can use the OnClose() event to find out what has been done on the dialog prior to
the user’s attempt to closing it You can also use it to deny closing the dialog, to warn the user about something, or to do anything that you judge necessary If you perform some processing, such as validating some values, when the user attempts to close the dialog box, if you still want to close the dialog, call the parent event handler with
CDialog::OnClose() In fact, this line of code is added to the event if you generate it
using the wizard If you want to conditionally close the dialog, you can write a conditional statement that can check whether something is written in order to close it If
you do not want to close the dialog box, do not call the parent CDialog::OnClose()
event
WM_DESTROY: Once a dialog, in fact any (CWnd) window object, has been closed, it
must be destroy so the memory it was using can be reclaimed If you want to do
something before the object is destroyed, use the WM_DESTROY to fire the OnDestroy() event
Practical Learning: Firing Windows Events
1 Open the DialogMessages application created above
In the Class View tab, click CDynamicDlg to display it in the combo box of the Properties window
To access the WM_CLOSE messages, in the Properties window, click the Messages
button
2 Click the WM_CLOSE item to display its combo box Click the arrow of the combo
box and click <Add> OnClose
3 To prevent the user from c losing the dialog box using the system Close button, implement the event as follows:
void CDynamicDlg::OnClose() {
Trang 31// TODO: Add your message handler code here and/or call default
MessageBox("In order to dismiss this dialog box, "
"click either OK or Cancel");
WM_CTLCOLOR: Once a control has been created, it can be displayed on the screen
At any time, whether before the control is displayed or after it has been displayed, if you need to perform some type of drawing such as changing its color, you can use the
WM_CTLCOLOR message which fires the OnCtlColor() event
Scroll Bar Messages: As we will learn when studying scroll bars and thumb -based
controls, a dialog-based object can be equipped with scroll bars, just like a frame of a view-based application We will also see that these controls do not handle their own scrolling messages Ther rely on their host
If a dialog object is equipped with one or two scroll bars or one of its controls is based on
scrolling operations, when the user clicks a scroll bar, the OnHScroll() or the OnVScroll() event is sent based on the WM_HSCROLL or the WM_VSCROLL
messages respectively
13.3 Floating Windows
Trang 3213.3.1 Introduction
A floating window is an object that is part of an application and behave as a semi-dialog box Such a window does not constitute an application by itself It is used to complete the application it is part of A floating window behaves like a dialog box with the main difference that the user does not have to close the floating window in order to access the rest of the application, which is the case for a modal dialog box Here is an application that uses many floating windows:
There are various types of floating windows used on different applications They include modeless dialog boxes, tool bars, and dialog bars
Practical Learning: Introducing Floating Windows
1 Start a new project named Floating
2 Create it as a Single Document and click Finish
13.3.2 The Modeless Dialog Box
A modeless dialog box allows the user to access the main application or any other possible object of the application even if this dialog box is displaying The user can decide to close it when the object is not needed anymore or keep it on as long as necessary Here is an example:
Trang 33The Find dialog
picture, the user
can still click and
activate any of the
windows in the
background
Because a modeless dialog box is closed when the user judges it necessary, making it possible to forget, the operating system needs to make sure that this object closes when its parent application closes so its memory resource can be freed and made available to other applications Based on this, the creation of a modeless dialog is a little different than that of the modal dialog box
There are two main techniques you can use to create a modeless dialog box You can first
declare a DLGTEMPLATE variable and “fill it up” This structure is defined as follows:
typedef struct { DWORD style;
After building the template from its variable, you can call the CDialog::CreateIndirect()
method to create the modeless object This method comes in two versions as follows:
BOOL CreateIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd = NULL); BOOL CreateIndirect(HGLOBAL hDialogTemplate, CWnd* pParentWnd = NULL);
Because of the amount of work involved with using this type of dialog box, we will ignore it
Another technique you can use consists of first creating a dialog resource and associating
a class to it To formally create a modeless dialog box and make it part of the application,
you can call the Create() method of the CDialog c lass It is provided in two syntaxes that
are:
BOOL Create(UINT nIDTemplate, CWnd* pParentWnd = NULL);
BOOL Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL);