Sei sulla pagina 1di 197

MicrosoftVisualC++/MFCFile

Processing:TheFileDialogBox

TheFileDialog

Introduction

MFC
Dialog
FileOpenDialog
...

One of the common dialog boxes provided by Microsoft


Windowsisforfileprocessing.TheFiledialogboxisused
toopenorsaveafile.IntheMFClibrary,theFiledialog
box is implemented by a class namedCFileDialog. The
CFileDialog class is derived by the CCommonDialog
class:

TheCFileDialogclassisequippedwithaconstructorwhosesyntaxis:
CFileDialog(BOOLbOpenFileDialog,

LPCTSTRlpszDefExt=NULL,

LPCTSTRlpszFileName=NULL,

DWORDdwFlags=OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,

LPCTSTRlpszFilter=NULL,

CWnd*pParentWnd=NULL)
TheCFileDialogconstructorrequiresoneargument:thebOpenFileDialog.

FileSaving
Oneoftheoperationsyoucanallowausertoperformonafileistosaveit,either
after creating it or after saving it. If you want to save a file, pass the first
argumentoftheCFileDialogconstructorasFALSE.Hereisanexample:
voidCExerciseDlg::OnBnClickedFileBtn()
{

CFileDialog*dlg=newCFileDialog(FALSE)
}

FileOpening
As opposed to saving a file, you can allow the user to open one of more files. To
createaFiledialogboxthattheusercanusetoopenafile,passthefirstargument
oftheCFileDialogconstructorasTRUE.Hereisanexample:
voidCExerciseDlg::OnBnClickedFileBtn()
{

CFileDialog*dlg=newCFileDialog(TRUE)
}

FileDialogProperties

Introduction
There are various ways you can configure the File dialog box. Its constructor is
equipped with many arguments and some arguments allow many options. As we
willsee,youcanalsousetheWin32toperformoperationsontheMFC'sFiledialog
box.
The options on the File dialog box are referred to as flags. To support them, the
dwFlags parameter of the CFileDialog constructor allows you to create a
combinationofoptionsusingthe|operator.

TheWin32FileDialogStructure
TheonlymembervariablethattheFileDialoghasiscalledm_ofn.Itisanobject
derived from a Win32 class (or structure) named OPENFILENAME. In fact, the
MFCdoesn'tdomiraclesthan the Win32 would. The MFC only provides some type
of"translation"oftheWin32libraryonthisissue.
TheOPENFILENAMEclassisdefinedasfollows:
typedefstructtagOFN{
DWORDlStructSize
HWNDhwndOwner
HINSTANCEhInstance
LPCTSTRlpstrFilter
LPTSTRlpstrCustomFilter
DWORDnMaxCustFilter
DWORDnFilterIndex
LPTSTRlpstrFile
DWORDnMaxFile
LPTSTRlpstrFileTitle
DWORDnMaxFileTitle
LPCTSTRlpstrInitialDir
LPCTSTRlpstrTitle
DWORDFlags
WORDnFileOffset
WORDnFileExtension
LPCTSTRlpstrDefExt
LPARAMlCustData
LPOFNHOOKPROClpfnHook
LPCTSTRlpTemplateName
#if(_WIN32_WINNT>=0x0500)
void*pvReserved
DWORDdwReserved
DWORDFlagsEx
#endif//(_WIN32_WINNT>=0x0500)
}OPENFILENAME,*LPOPENFILENAME
To use this structure, access the m_ofn member of the CFileDialog variable, then
accesstheOPENFILENAMEmemberyou want and assign the desired value to it.
Thiscanbedoneasfollows:
voidCExerciseDlg::OnBnClickedFileBtn()
{

CFileDialog*dlg=newCFileDialog(TRUE)

dlg>m_ofn.Member=Value
ToletyougettheOPENFILENAMEobjectthattheuserisusing,theCFileDialog
classprovidestheGetOFN() member function. Its comes in two versionswhoses
syntaxesare:

constOPENFILENAME&GetOFN()const
OPENFILENAME&GetOFN()
Itisimportanttoknowthatnotallmembersbehaveasexpectedbecausethereare
changes,andtherehavebeenchanges,inoperatingsystemsovertheyears.

DisplayingtheFileDialogBox
InordertouseaFiledialogbox,theusermustopenit.Thiscanbedonebycalling
theCFileDialog::DoModal()memberfunction.Itssyntaxis:
virtualINT_PTRDoModal()
Hereisanexampleofcallingthismemberfunction:
voidCExerciseDlg::OnBnClickedFileBtn()
{

CFileDialog*dlg=newCFileDialog(TRUE)

dlg>DoModal()
}
When it comes up, the File dialog displays two buttons regularly available on a
normaldialogbox.Ifthefileisbeingopened,thebuttonsareOpenandCancel.If
the user is saving a file, the buttons are Save and Cancel. In both cases, the
compiler system automatically specifies the buttons based on the first argument
youpassedtotheCFileDialogcopnstructor.
After using the dialog box, either to open or to save a file, the user can click
Open/Save or Cancel. If the user clicks Open or Save, the dialog box is (partly)
equippedtovalidatetheoperation.Forexample,iftheuserclicksOpen,thedialog
boxisconfiguredtomakesurethattheuserselectedafile.IftheuserclicksSave,
heorsheshouldhavegivenanametothefile.
To dismiss the dialog box without continuing with the intendedoperation,theuser
can click Cancel. If the user clicks Cancel, the dialog box throws a
CommDlgExtendedError exception. This error allows you to find out what
happened:maybetheuserdidn'tclickCancel,maybethedialogboxwasnoteven
created, maybe this, maybe that. This error allows you to diagnose a potential
problemanddealwithit.Ifyoudon'twanttogothroughthis,youcanjustcancel
theoperationyourself.

TheTitleoftheFileDialogBox

By default, if you declare a CFileDialog variable and pass the first argument as
TRUE, when it displays, the dialog box's title shows "Open". If you pass the first
argument as FALSE, the dialog box's title would display Save As. The operating
systemallowsyoutospecifyatitleofyourchoice.Thiscanbedonebyassigninga
stringtothelpstrTitlemembervariableoftheOPENFILENAMEstructurethroughthe
CFileDialog::m_ofnmember.Hereisanexample:

voidCExerciseDlg::OnBnClickedFileBtn()
{

CFileDialog*dlg=newCFileDialog(TRUE)

dlg>m_ofn.lpstrTitle=L"It'sTimetoOpentheFile"

dlg>DoModal()

TheLocationofaFile
Filesmustbemeticulouslyorganizedinacomputersotheycanbeeasilyretrieved
andused.InMicrosoftWindows,filesareorganizedasatree.Therootofafileisa
drive.Thefileisstoredinthecurrentcomputer,itisconsideredlocal.Afilecanbe
located in another computer that is connected to the computer that is trying to
accessthefile.
Afilecanbestoredonlocaldrivebutmostofthetime,undertheroot,theremore
many directories. In the Microsoft Windows dialect, these are also called folders.
Folders can contain subfolders and subfolders can contain other subfolders. A
filecan be stored on the root, inside a directory created on the root, or inside a
subdirectory or a directory. A file can also be stored in a drive or a directory on
anothercomputer.
Thelocationofafileisacombinationoftherootanddirectoriesthatconstituteits
ancestry.WhenusingtheFiledialogbox, the user can select a local or a network
drive to save or open a file, provided the permissions allow him to perform the
operation.
In the strict sense, the file name is a long string that starts from its drive all the
waytoits"normal"name.Thisisalsoreferredtoasitspath.Togetthepathofthe
beingdealtwith,youcancalltheCFileDialog::GetPathName()memberfunction.
Itssyntaxis:
CStringGetPathName()const

TheNameofaFile
Asfarasauserisconcerned,themostimportantaspectofafileisitsname.When
savingafile,theusermustenteranameintheFileNameofthedialogbox.When
opening a file, the user must select it by its name. If you want, you can enter a
defaultfilenamefor the user when the dialog box comes up. To do this, pass the
desired string as the third argument to the CFileDialog variable. Here is an
example:
voidCExerciseDlg::OnBnClickedFileBtn()
{

CFileDialog*dlg=newCFileDialog(FALSE,NULL,L"Exercise")

dlg>DoModal()
This time, when the dialog box displays, the file name box would show the string
fromthethirdargument.
To let you get the name of the file the user is dealing with or dealt with on the
dialog box, you can call the CFileDialog::GetFileName() member function. Its
syntaxis:

CStringGetFileName()const

TheExtensiontoaFile
Besidesitsname,themostimportantdetailofafileisitsextension.Thisis1oracombinationof
2,3,4,ormorecharactersthat end the full name of a file. The extension is separated from the
actualname of a file by a period. For example, the extension of a Microsoft Word file is .docx.
TheextensionofaPerlfileispl.
When you display a File dialog box to the user, you have many options to specify a default file
extensiontofilterthetypesoffilestheuserwoulddealwith.Toassistyou,theCFileDialogclass
providesasecondargument:lpszDefExt.Ifyoudecidetouseit.Passthedesiredextension.This
is mostly useful when saving a file, in which case if the user gives only a name to the file but
doesn't select an extension, when the user clicks Save, the operating system would apply the
valueofthelpszDefExtargumenttoit.Hereisanexampleofspecifyingadefaultfileextension:
voidCExerciseDlg::OnBnClickedFileBtn()
{

CFileDialog*dlg=newCFileDialog(FALSE,L".txt")

dlg>DoModal()
If you don't want to specify a default file extension, pass the second argument as NULL. After
dealingwiththeFiledialogbox(whether opening or saving a file), if the user clicks the Save or

the Open button, to let you find out the extension of that file, you can call the
CFileDialog::GetFileExt()memberfunction.Itssyntaxis:
CStringGetFileExt()const

FilteringFiles
You can create an application that deals with only one type of file and you specify the type of
extension. Or you can create application that can handle many types of files. In this case, you
wouldallow a user to specify the type of file to open or save. In reality, a file extension is the
primary means of a user to categorize a file. If your application can deal with various types of
files,whenopeningorsavingafile,youcanassisttheuserbygivinganextensiontothefile.In
fact,youcancreateaseriesoffileextensionsthattheuserwouldselectfrom.
A filter is one or more strings that specify or restrict the types of files the user can use when
openingfilesorwhensavingone.Foratextbasedapplication,youmayallowonlytextfiles,that
is, files with a txt extension. For a rich textbased application, you may allow only Rich Text
Format files, which are files with rtf extension. On the other hand, if you are creating an
applicationforwebfiles,youcanallowasmanyfileextensionsasnecessary,suchashtm,html,
php,asp,etc.Asyoumayrealize,textfilesorwebfilesarealltextbasedfiles.Thismeansthat
if you create a textbased or richtext based application, you should allow the users to decide
whetherthefiletheyaretryingtoopencanbe"read"byatextbasedcontrol.
TocreatealistoffileextensionsforyourFiledialogbox,createoneoracombinationsofvalues
whereeachusesthefollowingformula:
Prompt|Extension
Ifsavingafile,thePromptisasectionthatdefineswhattheuserwouldseeintheSaveAsType
combobox:

If opening the file, the Prompt would display in a combo box on the right side of the File Name
box:

AnexamplewouldbeTextFiles.Suchastringdoesnotlettheuserknowwhatactualextension
thefilewoulduse.Therefore,asacourtesy,youcanspecify,betweenparentheses,theextension
thatwouldbeappliedifthisextensionisused.Therefore,thePromptcanbeText Files (*.txt).

Inthiscase,theextensionusedwouldbe.txt.Theasterisk*letstheuserknowthatwhateveris
provided as the file name would be used in place of the asterisk. The period indicates the
separationfromthefiletoitsextension.Thismeansthatthecharactersontheleftoftheperiod
wouldbethefilename,thecharactersontherightsideoftheperiodwouldbeusedastheactual
fileextension.
Tospecifytheextensionthattheoperatingsystemwouldusetoassociatetothefile,youprovide
asecondpartofthestringasExtension.InMicrosoftWindows,mostextensionsaremadeofthree
characters. Some applications use a 2letter extensions (for example Perl files have a .pl
extension and C# files use .cs) and some others use 4 letters (such as .html for some HTML
files).Thisdepends.Anexampleofastringthatspeciesanextensionis:
TextFiles(*.txt)|*.txt
Youshouldendafilewith||.IfyouwanttoprovidevariousextensionstoyourSavedialogbox,
youcanseparatethemwitha|symbol.Anexamplewouldbe:
HTMLFiles(*.htm)|*.htm|ActiveServerPages(*.asp)|*.asp|PerlScript(*.pl)|*.pl||
TospecifythefilterusedbytheFiledialogbox,youcanpassitsstringasthefourthargumentto
theCFileDialogconstructor.Hereisanexample:
voidCExerciseDlg::OnBnClickedFileBtn()
{

CFileDialog*dlg=newCFileDialog(TRUE,L"txt",NULL,NULL,

L"HTMLFiles(*.htm)|*.htm|"

L"ActiveServerPages(*.asp)|*.asp|"

L"ApacheFiles(*.php)|*.php|"

L"PerlScript(*.pl)|*.pl|"

L"AllFiles||")

dlg>DoModal()
Thiswouldproduce:

OpeningManyFiles
By default, the File dialog box allows a user to select one file and open it. If you want, you can
makeitpossibletoopenmanyfilesatonce.Tostart,addtheOFN_ALLOWMULTISELECTflagto
eithertheappropriatememberoftheOPENFILENAMEvariableoraddittothefourthargumentof
theCFileDialogconstructor.Hereisanexample:
voidCExerciseDlg::OnBnClickedFileBtn()
{

CFileDialog*dlg=newCFileDialog(TRUE,L"txt",NULL,OFN_ALLOWMULTISELECT)

dlg>DoModal()
Whenthishasbeendone,theusercanpresstheCtrlorShiftkeystoselectthefiles.

MicrosoftVisualC++/MFCFile
Processing:TheOpenWithDialog
Box

Description

C++MFC
VisualC++
Dialog
...

Inatypicalcomputer,mostfiletypesareregisteredwith
known applications so the user can appropriately open a
file.Sometimestheusermaybeinthepresenceofafile
thatnoapplicationisautomaticallyconfiguredtoopen.In
somecases,theusercanusetheOpenWithdialogboxto
selectanapplicationtoopenthefile.

To display the Open With dialog box, you can call the SHOpenWithDialog()
function.Itssyntaxis:
HRESULTSHOpenWithDialog(
__in_optHWNDhwndParent,
__inconstOPENASINFO*poainfo
)
Hereisanexample:
voidCExerciseDlg::OnBnClickedOpenwithBtn()
{

OPENASINFOoai
oai.pcszFile=L"C:\\Exercise\\Something.bmp"
oai.pcszClass=NULL
oai.oaifInFlags=OAIF_ALLOW_REGISTRATION
SHOpenWithDialog(m_hWnd,&oai)
}
Thiswouldproduce:

WindowsControls:TheFontDialog
Box

IntroductiontotheFontDialogBox

MFC
FontWindowsXP
C++Example
...

Description
To support easy selection of font, Microsoft Windows
providestheFontdialogbox:

TousetheFontdialogbox,theusershouldfirsthavetextthatneedsto,andcan,
be formatted. Once the dialog box displays, a user can select a font by its name,
its style, its size, one or both effects (Underline or Strikeout), and a color. After
makingthenecessarychanges,theusercanclickOKtoapplythechangesorclick
Canceltoignoretheselectedattributes.

CreatingaFontDialogBox
To suport the font dialog box, the MFC library provides a class named
CFontDialog.TheCFontDialogclassisderivedfromtheCCommonDialogclass.
TheCFontDialogclassisequippedwithtwoconstructorswhosesyntaxesare:
CFontDialog(
LPLOGFONTlplfInitial=NULL,
DWORDdwFlags=CF_EFFECTS|CF_SCREENFONTS,
CDC*pdcPrinter=NULL,
CWnd*pParentWnd=NULL
)
CFontDialog(
constCHARFORMAT&charformat,
DWORDdwFlags=CF_SCREENFONTS,
CDC*pdcPrinter=NULL,
CWnd*pParentWnd=NULL
)
To create a font dialog box, declare variable or a pointer of type CFontDialog.
Thisiscanbedoneinthefunctionoreventwherethedialogboxwouldbeneeded.
Hereisanexample:
voidCExerciseDlg::OnBnClickedFont()
{

//TODO:Addyourcontrolnotificationhandlercodehere

CFontDialogdlg
}
Ifyouwantthedialogboxtobeavailabletoallfunctionsandeventsofaunit,you

candeclareitsvariableintheheaderoftheclassthatwoulduseit.
To support the font dialog box, the Win32 library provides a structure named
CHOOSEFONT.

CharacteristicsofaFontDialogBox

Introduction
Atdesigntime,thefontdialogboxhardlyneedsanychangeofpropertiestowork.
Theonlytimeyouwouldsetitspropertiesisifyoujudgethatitsdefaultproperties
arenotconformtoyourparticularscenario.Forexample,ifyouareprovidingfont
formatting for a control and you want users to control the font characteristics of
individuallettersorparagraph,thereshouldbenothingtochangeatdesigntime.
TosupportarelationshipwiththeWin32'sfontdialogbox,theCFontDialogclassis
equippedwithamembervariablenamedm_cf:
CHOOSEFONTm_cf
Once, and however, you have a CFontDialog instance, you can display the Font
dialog box by calling the DoModal() member function. The font dialog box is
equippedwithtwoprimarybuttons:OKandCancel.Afterusingit,iftheuserclicks
OK,thisimpliesthatiftherewerechangesoffont,size,color,etc,theuserwants
them committed to the document. If the user clicks Cancel, this means that you
shouldignoreanyactionsthatwereperformedonthedialogbox.TheDoModal()
member function is of type INT_PTR. It returns IDOK if the user clicks OK.
Otherwise, if the user clicks Cancel, it would return IDCANCEL. Therefore, after
theuserhasusedit,youshouldfindoutifsheclickedOKorCancelbeforeapplying
her changes. This inquiry is usually performed with an if conditional statement as
follows:
if(dlgFont>DoModal()==IDOK)
{

//WhattodoiftheuserclickedOK
}

TheFontFromtheDialogBox
As its name indicates, the font dialog box is used to configure or get a font. To
support its characteristics, the CFontDialog class is equipped with various
member functions. After the user has used a font dialog box and clicked OK, you
canfindoutwhatcharacteristicswereset.

AGILE

TESTING

SOFTWARE

Try Our Award-Winning Agile Project Management & Planning Tool Today!

Home

Copyright20102011FunctionX,Inc.

WindowsControls:TheColorDialog
Box

IntroductiontotheColorDialogBox

Description
C++Example
Colors
MFC
...

To provide the selection of colors on Microsoft Windows


applications, the operating system provides a common
dialog box appropriate for such tasks. The Color dialog
box is used by various reasons to let the user set or
changeacolorofanobjectsuchasthebackgroundcolor
ofacontrolorthecolorusedtopaintanobject.

Whenitdisplays,bydefault,thedialogboxappearsasfollows:

Thisdisplaysaconstantlistofcolorstotheuser.Ifnoneoftheavailablecolorsis
appropriateforthetaskathand,theusercanclicktheDefineCustomColorsbutton
toexpandthedialogbox:

The expanded Color dialog box allows the user to either select one of the preset
colorsortocustomcreateacolorbyspecifyingitsred,green,andbluevalues.
Theusercanchangethecolorinfourdifferentareas.Thetopleftsectiondisplaysa
listof48predefinedcolors.Ifthedesiredcolorisnotinthatsection,theusercan
click and drag the mouse in the multicolored palette. The user can also drag the
rightbarthatdisplaysarangebasedonthecolorofthepalettetheusercanscroll
upanddownbydraggingthearrow.Formoreprecision,theusercantypetheRed,

GreenandBluevalues.Eachusesaintegralvaluethatrangesfrom1to255.

CreatingaColorDialogBox
To support the color dialog box, the Win32 library provides a structure named
CHOOSECOLORanddefinedasfollows:
typedefstruct{
DWORDlStructSize
HWNDhwndOwner
HWNDhInstance
COLORREFrgbResult
COLORREF*lpCustColors
DWORDFlags
LPARAMlCustData
LPCCHOOKPROClpfnHook
LPCTSTRlpTemplateName
}CHOOSECOLOR,*LPCHOOSECOLOR
To build a color dialog box, you must declare a variable of this structure and
appropriately initialize it. To actually display the dialog box, you must call the
ChooseColor()function.Itssyntaxis:
BOOLWINAPIChooseColor(__inoutLPCHOOSECOLORlpcc)
To support the color dialog box, the MFC library provides the CColorDialogclass
thatisderivedfromaclassnamedCCommonDialog.TheCCommonDialogclass
isderivedfromCDialog.
Togetacolordialogbox,declareavariableoftypeCColorDialog.Todisplaythe
dialogbox,calltheDoModal()memberfunctiontheclassinheritsfromCDialog.
Hereisanexample:
voidCExerciseDlg::OnBnClickedColorBtn()
{
//TODO:Addyourcontrolnotificationhandlercodehere
CColorDialogdlg
dlg.DoModal()
}

CharacteristicsoftheColorDialogBox

IntroductiontoUsingtheColorDialogBox
TheCColorDialogclasshasoneconstructorwhosesyntaxis:
CColorDialog(
COLORREFclrInit=0,
DWORDdwFlags=0,
CWnd*pParentWnd=NULL
)
As mentioned already, to display a color dialog box, you can call the
CColorDialog::DoModal() member function. After a person has used the dialog
box,ifheorsheclicksOKorpressesEnter,thedialogboxreturnstheIDOKvalue.
Iftheuserclicks Cancel or presses Esc, the DoModal() member functionreturns
IDCANCEL.

TheWin32DialogBox
TorepresenttheWin32'scolordialogbox,theCColorDialogclassisequipped
withamembervariablenamedm_cc:
CHOOSECOLORm_cc
This member variable allows you to manipulate the characteristics of a color
dialogboxusingthemembersoftheCHOOSECOLORstructure.

TheColor
The most important and most obvious property of the color dialog box is its
color. When the dialog box displays, you may want it to show a certain color
asasuggestionoritcanbeacoloryouspecifyforanyreason.Tospecifythe
defaultcolor,whendeclaringtheCColorDialogbox,passthefirstargumentto
theconstructor.Hereisanexample:
voidCExerciseDlg::OnBnClickedColorBtn()
{
//TODO:Addyourcontrolnotificationhandlercodehere
CColorDialogdlg(RGB(25,125,155))
}
Afterusingthedialogbox,youmaywanttogetthecolortheuserselected.To
provide this information, the CColorDialog class is equipped with the
GetColor()memberfunction.Itssyntaxis:
COLORREFGetColor()const

Hereisanexampleofcallingthismemberfunction:
voidCExerciseDlg::OnBnClickedColorBtn()
{

//TODO:Addyourcontrolnotificationhandlercodehere

CColorDialogdlg

if(dlg.DoModal()==IDOK)

SetBackgroundColor(dlg.GetColor())

TheSizeoftheDialogBox
Youcancontroltheregularorfullsizeofthedialogbox.Tospecifythedefault
size when the color dialog box comes up, pass the second argument. For
example, to display the dialog box in its full size, pass the second argument
withaCC_FULLOPENvalue.Hereisanexample:
voidCExerciseDlg::OnBnClickedColorBtn()
{
//TODO:Addyourcontrolnotificationhandlercodehere
CColorDialogdlg(208468,CC_FULLOPEN)
if(dlg.DoModal()==IDOK)

SetBackgroundColor(dlg.GetColor())
}

CustomColors
Ifyouwanttosupplytheuserwithasetofcolorsofyourchoice,youcando
this using a list of custom colors. To support this, the CHOOSECOLOR
structure is equipped with a member named lpCustColors. The
COLORREF::lpCustColors member is an array of 16 COLORREF values.
After creating that array, assign it to this member variable. Here is an
example:
voidCExerciseDlg::OnBnClickedColorBtn()
{

//TODO:Addyourcontrolnotificationhandlercodehere

CColorDialogdlg

COLORREFcRef[]={RGB(0,5,5),

RGB(0,15,55),

RGB(0,25,155),

RGB(0,35,255),

RGB(10,0,5),

RGB(10,20,55),

RGB(10,40,155),

RGB(10,60,255),

RGB(100,5,5),

RGB(100,25,55),

RGB(100,50,155),

RGB(100,125,255),

RGB(200,120,5),

RGB(200,150,55),

RGB(200,200,155),

RGB(200,250,255)}

dlg.m_cc.lpCustColors=cRef

dlg.m_cc.Flags|=CC_FULLOPEN

if(dlg.DoModal()==IDOK)

SetBackgroundColor(dlg.GetColor())

PHP

CODE

GENERATOR

Generate PHP code for any local or remote database.

Home

Copyright20102011FunctionX,Inc.

WindowsControls:TheMFCColor
DialogBox

IntroductiontotheMFCColorDialogBox

Description
C++MFC
ColorMFC
Dialog
...

To provide a modern object for color selection, the MFC


library now has a new color dialog box. The MFC color
dialog box is a property sheet made of two property
pages,threebuttons,andapreviewarea:

The Standard property page allows a user to select a color by clicking one of the
hexagonalcoloredshapes.Tocreateorspecifyacolorbasedonitsredgreenblue
components,theusercanclicktheCustomtab:

In the Custom property page, the user has many options. To select a color, the
user can click or browse the Colors panel. To specify the numeric values of the
desiredcolor,theusercanusethespinbuttonsinthebottomsection.
OneoftheoptionsthattheMFCcolorsdialogboxhasoveritsWin32counterpartis
theabilitytoselectacolorfromanywhereonthescreen.Toproceed,theusercan
click the Select button, then move the mouse to the object or area that has the
desiredcolor,andclick.
After selecting or specifying a color, the user can click OK or press Enter. To

dismissthedialogboxregardlessofwhatwasdoneonit,theusercanclickCancel
orpressEsc.

CreatinganMFCColorsDialogBox
To support the MFC colors dialog box, the MFC library provides a class named
CMFCColorDialog. Therefore, to create colors dialog box, declare a variable of
thisclass.Thiscanbedoneasfollows:
voidCExerciseDlg::OnBnClickedColors()
{
//TODO:Addyourcontrolnotificationhandlercodehere
CMFCColorDialogdlgColors
}

CharacteristicsoftheMFCColorsDialogBox

Introduction
The CMFCColorDialog class is derived from CDialogEx. Based on this, to
presentthedialogboxtotheuser,callitsDoModal()memberfunction.Here
isanexample:
voidCExerciseDlg::OnBnClickedColors()
{
//TODO:Addyourcontrolnotificationhandlercodehere
CMFCColorDialogdlgColors
dlgColors.DoModal()
}
After using the dialog box, if the user clicks OK, the DoModal() member
functionreturnsIDOK.Inthiscase,youcangetthevaluesfromthedialogbox
anduseitasyouseefit.

TheInitialColoroftheDialogBox
Beforedisplayingthecolorsdialogbox,youcanspecifywhatprimarycolorthe
dialogboxshouldselect.Toassistyouwiththis,theCMFCColorDialogclass
hasthefollowingconstruction:
CMFCColorDialog(
COLORREFclrInit=0,
DWORDdwFlags=0,
CWnd*pParentWnd=NULL,
HPALETTEhPal=NULL
)

Asyoucansee,allargumentsareoptional.TheclrInitargumentallowsyouto
specifytheinitialcolorthatthedialogboxwouldselect.Hereisanexample:
voidCExerciseDlg::OnBnClickedColors()
{
//TODO:Addyourcontrolnotificationhandlercodehere
CMFCColorDialogdlgColors(268405)
dlgColors.DoModal()
}

TheCurrentColoroftheDialogBox
Besidestheconstructor,toletyousettheinitialorcurrentcolorofthedialog
box,theCMFCColorDialogclassisequippedwithamemberfunctionnamed
SetCurrentColor.Itssyntaxis:
voidSetCurrentColor(COLORREFrgb)

Hereisanexampleofcallingit:
voidCExerciseDlg::OnBnClickedColors()
{
//TODO:Addyourcontrolnotificationhandlercodehere
CMFCColorDialogdlgColors
dlgColors.SetCurrentColor(702416)
dlgColors.DoModal()
}

GettingtheColoroftheDialogBox
After using the dialog box, the user can click OK, in which case DoModal()
would return IDOK. In this case, to let you identify the color the user would
have selected, the CMFCColorDialog class provides the Color() member
function.Itssyntaxis:
COLORREFGetColor()const
Here is an example of calling that member function and using the color the
userselected:
voidCExerciseDlg::OnBnClickedColors()
{
//TODO:Addyourcontrolnotificationhandlercodehere
CMFCColorDialogdlgColors
if(dlgColors.DoModal()==IDOK)

SetBackgroundColor(dlgColors.GetColor())
}

Home

Copyright20102011FunctionX,Inc.

MFCDialogBoxes:DialogBars

Overview
AdialogbarisanobjectofthefamilyofControl
Bars. These are objects used to complete an
interfacewhentheframeneedsextrarealestate
to carry the desired controls of an application.
One of the main justifications of control bars is
thattheusercandisplayorhidethematwill.
Adialogbarisasortofintermediarybetweena
dialog box and a toolbar. Like a dialog box or a
toolbar, a dialog bar is mainly used as a
containerorhostofothercontrols.

CreatingaDialogBar
Likeadialogbox,adialogbariscreatedfromadialogbasedresource.Tocreateadialogbox,
toolbar,youcandisplaytheAddResourcedialogbox,expandtheDialognodeanddoubleclick
Dialog bar. This would add a borderless dialog resource to your application. You have two
options:youcankeepthedialogbarasisoryoucanderiveaclassfromit.Keepingthedialog
bar as created is probably easier because it is ready to be recognized by the other classes,
namelytheframeandthedocument,ofyourapplication.
To add a dialog bar to your project, in the frame header class, you can declare a CDialogBar
variable. To display and attach it to your interface, you can programmatically create it in the
OnCreate()eventofyourframeclassusingoneoftheoverloadedCDialog::Create()method:
virtualBOOLCreate(
CWnd*pParentWnd,
LPCTSTRlpszTemplateName,
UINTnStyle,
UINTnID
)

virtualBOOLCreate(
CWnd*pParentWnd,
UINTnIDTemplate,
UINTnStyle,
UINTnID
)

PracticalLearning:IntroducingDialogBars
1. CreateanMFCApplicationnamedExoBarthenclickOKandFinish
2. Toaddadialogbox,onthemainmenu,clickProject>AddResource...
3. ExpandtheDialognodeandclickDialogBar

4. ClickNew
5. ChangeitsIDtoIDD_TOOLBOX
6. DeletetheTODOline
7. Resizethedialogbartohaveatallerheightandanarrowerwidth
8. AddaButtontothedialogbar.ChangeitsIDtoIDC_SUBMIT_BTNanditsCaptiontoSubmit

9. RightclicktheSubmitbuttonandclickAddEventHandler...
10. IntheClassList,clicktheviewclass

11. ClickAddandEdit
12. Implementtheeventasfollows:

voidCExoBarView::OnBnClickedSubmitBtn()
{

//TODO:Addyourcontrolnotificationhandlercodehere

AfxMessageBox("Thankyouforyourconsideration\n"

"YourapplicationhasbeensubmittedtoHumanResources\n"

"Oncewehavereviewed,wewillcontactyou")
}
13. AccesstheheaderfileofyourframeanddeclareaCDialogBarvariablenamedm_wndToolboxinthe
samesectionwherethetoolbarandthestatusbararedeclared:

//MainFrm.h:interfaceoftheCMainFrameclass
//
#pragmaonce
classCMainFrame:publicCMDIFrameWnd
{

DECLARE_DYNAMIC(CMainFrame)
public:

CMainFrame()
//Attributes
public:
//Operations
public:
//Overrides
public:

virtualBOOLPreCreateWindow(CREATESTRUCT&cs)
//Implementation
public:

virtual~CMainFrame()
#ifdef_DEBUG

virtualvoidAssertValid()const

virtualvoidDump(CDumpContext&dc)const
#endif
protected://controlbarembeddedmembers

CStatusBarm_wndStatusBar
CToolBarm_wndToolBar
CDialogBar
m_wndToolbox

//Generatedmessagemapfunctions
protected:

afx_msgintOnCreate(LPCREATESTRUCTlpCreateStruct)

DECLARE_MESSAGE_MAP()
}
14. Accessthesourcefileoftheframeclassandcreatethedialogbarasfollows:

intCMainFrame::OnCreate(LPCREATESTRUCTlpCreateStruct)
{

if(CMDIFrameWnd::OnCreate(lpCreateStruct)==1)

return1

if(!m_wndToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP

|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||

!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

TRACE0("Failedtocreatetoolbar\n")

return1//failtocreate

m_wndToolBar.SetWindowText("Standard")

//CreatethedialogbarusingoneofitsCreate()methods
if(!m_wndToolbox.Create(this,

IDD_TOOLBOX,

CBRS_LEFT|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY,

IDD_TOOLBOX))
{

TRACE0(_T("Failedtocreatethetoolbox\n"))

return1
}

//Whenthedialogbarisundocked,displayacaptiononitstitlebar
m_wndToolbox.SetWindowText("Toolbox")

if(!m_wndStatusBar.Create(this)||

!m_wndStatusBar.SetIndicators(indicators,

sizeof(indicators)/sizeof(UINT)))
{

TRACE0("Failedtocreatestatusbar\n")

return1//failtocreate
}
//TODO:Deletethesethreelinesifyou
//don'twantthetoolbartobedockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY)
//Allowthedialogbartobedockable
//ontheleftortherightoftheframe
m_wndToolbox.EnableDocking(CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT)

EnableDocking(CBRS_ALIGN_ANY)

DockControlBar(&m_wndToolBar)
DockControlBar(&m_wndToolbox)

return0

15. Testtheapplication

PropertySheetsandPropertyPages

IntroductiontoPropertySheetsandPropertyPages

Description
VisualC++
MFC
C++Example
...

Apropertysheetisacontrolmadeoformoretabscalledpropertypage.
Apropertysheetcanhavejustonetab,thatis,justonepropertypage.
Hereisanexample:

In most other cases, a property page appears in a group with other pages. It functions like a
group of pieces of paper placed on top of each other. Each piece is represented by a tab that
allowstheusertoidentifyit:

To use a property page, the user clicks the header, also called tab, of the desired page. This
bringsthatpageupandsendstheother(s)inthebackground:

Iftheuserneedsaccesstoanotherpage,heorshecanclickthedesiredtab,whichwouldbring
thatpageinfrontandsendthepreviouslyselectedpagetotheback.
Thepagesaregroupedandhostedbyanobjectcalledapropertysheet.Thepropertypagesofa
propertysheetaresimplyusedtocarryorholdothercontrols.Themajorideaofusingaproperty
sheetisitsabilitytohavemanycontrolsavailableinarelativelysmallerarea.
Therearetwotypesofpropertysheets:modalandmodeless.Amodelesspropertysheetdoesnot
displaybuttons.Amodalpropertysheetisequippedwithcommandbuttonsthatallowtheuserto
makeadecisionafterselectingitemsonthepagesorchangingthevaluesofthepage'scontrols.
Bydefault,aftercreatingapropertysheet,itisequippedwiththeOK,theCancel,andtheApply
buttons.

PracticalLearning:IntroducingPropertySheets
1. StartMicrosoftVisualStudio
2. Tocreateanewapplication,onthemainmenu,clickFile>NewProject...
3. Intheleftlist,clickVisualC++.Intherightlist,clickMFCApplication
4. ChangetheNametoAlgebra1
5. ClickOK
6. InthefirstpageoftheMFCApplicationWizard,readthetextandclickNext
7. Inthesecondpageofthewizard,clickDialogBased
8. ClickNext
9. Inthethirdpage,clickAboutBoxtoremoveitscheckmarkandclickNext
10. Inthefourthpageofthewizard,clickNext
11. InthefifthpageofthewizardandintheGeneralClasseslist,clickCAlgebra1Dlg
12. IntheClassName,changethenameoftheclasstoCQuadrilateralDlg
13. Changethe.hFiletoQuadrilateralDlg.h
14. Changethe.cppFiletoQuadrilateralDlg.cpp

15. ClickFinish

16. Onthedialogbox,clicktheTODOlineandpressDelete
17. WhiletheOKbuttonisselected,pressDelete
18. AlsodeletetheCancelbutton
19. IftheResourceViewisnotvisible,onthemainmenu,clickView>OtherWindows>
ResourceView.
IntheResourceView,rightclickAlgebra1.rcandclickAddResource...
20. IntheAddResourcedialogbox,clickBitmap

21. ClickImport...
22. Fromtheresourcesthataccompanytheselessons,selectquadrilateral.bmp
23. ClickOpen
24. Ifthepicturedisplays,closeit.
IntheResourceView,expandtheBitmapnodeandclickIDBobject
25. InthePropertieswindow,clickID,typeIDB_QUADRILATERALandpressEnter
26. Inthesameway,importthecircular.bmpandchangeitsIDtoIDB_CIRCULAR
27. Importthedimensional.bmpandchangeitsIDtoIDB_DIMENSIONAL3
28. IntheToolbox,clickthePictureControlbutton

andclickthedialogbox

29. InthePropertieswindow,clickTypeandselectBitmap
30. ClickImage.ThenclickthearrowofitscomboboxandselectIDB_QUADRILATERALand
heightenthedialogboxsothebitmapwoulddisplaycompletely

CreatingaPropertyPage
As mentioned already, a property is made of property pages. There are many steps you must
followtocreateapropertysheetanditspropertypages.
ApropertypageisanobjectortypeCPropertyPage,whichisaclassderivedfromCDialog:
classCPropertyPage:publicCDialog
In reality, you should start by creating a dialog box for each property page. Set the size as you
wish. If you are creating manyproperty pages, their dialog boxes don't have to have the same
size (but it is better if they do). If they have different sizes, when the property sheet receives
them, it will apply the largest width of one of the dialog boxes and the highest height of the
propertypagestoapplyittotheotherpropertypages.
Besidesthesizeofthedialogbox,eachmusthavethefollowingproperties(setintheProperties
window):
Border:Thin
Disabled:True
Style:Child
TitleBar:True
Besidesthese,setthecaptiontothestringyouwanttodisplayonthetab.
Insteadofcreatingtedialogboxofapropertypagefromscratch,MicrosoftVisualC++provides

alreadyformatted objects ready to be designed. To use one of them, display the Add Resource
dialog box and expand the Dialog node. Under Dialog, select either IDD_PROPPAGE_LARGE,
IDD_PROPPAGE_MEDIUM,orIDD_PROPPAGE_SMALL:

As their names indicate, the sizes of the dialog boxes depend on the option. After selecting the
desiredoption,clickNew.Thiswouldcreateadialogboxwiththenecessaryoptionsalreadyset.
Youcanthendesignthedialogboxasyouseefit.
After designing the dialog box, create its associated dialog box. When doing this, set the base
classtoCPropertyPage.

PracticalLearning:CreatingPropertyPages
1. Clickthebodyofthedialogboxetomakesureithasfocus.
InthePropertieswindow,changethefollowingcharacteristics:
Border:Thin
Caption:Quadrilateral
Disabled:True
ID:IDD_QUADRILATERAL_DLG
Style:Child
2. IntheSolutionExplorer,expandtheprojectandtheHeaderFilesnode.Doubleclick
QuadrilateralDlg.h
3. Changethedocumentasfollows:
//QuadrilateralDlg.h:headerfile
//
#pragmaonce
//CQuadrilateralDlgdialog
classCQuadrilateralDlg:publicCPropertyPage
{
//Construction
public:

CQuadrilateralDlg(CWnd*pParent=NULL)//standardconstructor
//DialogData

enum{IDD=IDD_QUADRILATERAL_DLG}

protected:
virtualvoidDoDataExchange(CDataExchange*pDX)//DDX/DDVsupport

//Implementation
protected:

HICONm_hIcon

//Generatedmessagemapfunctions
virtualBOOLOnInitDialog()
afx_msgvoidOnPaint()
afx_msgHCURSOROnQueryDragIcon()
DECLARE_MESSAGE_MAP()

4. AccesstheQuadrilateralDlg.cppfileandchangeitasfollows:
//QuadrilateralDlg.cpp:implementationfile
//
#include"stdafx.h"
#include"Algebra1.h"
#include"QuadrilateralDlg.h"
#include"afxdialogex.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#endif
//CQuadrilateralDlgdialog
CQuadrilateralDlg::CQuadrilateralDlg(CWnd*pParent/*=NULL*/)

:CPropertyPage(CQuadrilateralDlg::IDD)
{

m_hIcon=AfxGetApp()>LoadIcon(IDR_MAINFRAME)
}
voidCQuadrilateralDlg::DoDataExchange(CDataExchange*pDX)
{

CPropertyPage::DoDataExchange(pDX)
}

BEGIN_MESSAGE_MAP(CQuadrilateralDlg,CPropertyPage)

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()
//CQuadrilateralDlgmessagehandlers
BOOLCQuadrilateralDlg::OnInitDialog()
{

CPropertyPage::OnInitDialog()

SetIcon(m_hIcon,TRUE)
SetIcon(m_hIcon,FALSE)

//Setbigicon
//Setsmallicon

//TODO:Addextrainitializationhere

returnTRUE//returnTRUEunlessyousetthefocustoacontrol

voidCQuadrilateralDlg::OnPaint()
{
if(IsIconic())
{

CPaintDCdc(this)//devicecontextforpainting

SendMessage(WM_ICONERASEBKGND,

reinterpret_cast<WPARAM>(dc.GetSafeHdc()),0)

//Centericoninclientrectangle
intcxIcon=GetSystemMetrics(SM_CXICON)
intcyIcon=GetSystemMetrics(SM_CYICON)
CRectrect
GetClientRect(&rect)
intx=(rect.Width()cxIcon+1)/2
inty=(rect.Height()cyIcon+1)/2

//Drawtheicon

dc.DrawIcon(x,y,m_hIcon)
}
else
{

CPropertyPage::OnPaint()
}
}
HCURSORCQuadrilateralDlg::OnQueryDragIcon()
{
returnstatic_cast<HCURSOR>(m_hIcon)
}
5. IntheResourceView,expandthenameoftheproject.ExpandAlgebra1.rc.ExpandDialog.
RightclickDialogandclickInsertDialog
6. Onthenewdialogbox,clickOKandpressDelete
7. AstheCancelbuttonisselected,pressDelete
8. InthePropertieswindow,changethefollowingcharacteristicsofthedialogbox:
Border:Thin
Caption:CircularShapes
Disabled:True
ID:IDD_CIRCULAR_DLG
Style:Child
9. AddapicturecontrolandsetitsbitmaptoIDB_QUADRILATERAL

10. IntheResourceView,rightclickthenameoftheprojectandclickAddResource...
11. ClickBitmapandclickImport...
12. Selectcircular.bmpandclickOpen
13. Tocreateaclassforthedialogbox,rightclickthebodyofthedialogboxandclickAdd
Class...
14. SettheClassNametoCCircularDlg
15. SettheBaseClasstoCPropertyPage

16. ClickFinish
17. Tocreateanewpropertypage,intheResourceView,rightclickDialogandclickAdd
Resource...
18. IntheAddResourcedialogbox,expandDialogandclickIDD_PROPPAGE_LARGE
19. ClickNew
20. InthePropertieswindow,changethefollowingcharacteristics:
Caption:3Dimensional
ID:IDD_DIMENSION3_DLG
21. AddapicturecontrolandsetitsbitmaptoIDB_QUADRILATERAL

22. RightclickthebodyofthedialogboxandclickAddClass...
23. SettheClassNametoCDiamension3Dlg
24. SettheBaseClasstoCPropertyPage
25. ClickFinish

CreatingaPropertySheet
Apropertysheetisthehostofpropertypages.ApropertysheetisbasedontheCPropertySheet
class,whichisderivedfromCWnd:
classCPropertySheet:publicCWnd
Togetapropertysheet,createaclassthatisderivedfromCPropertySheet.Toassociateeach
property page to the property sheet, you must call the AddPage() member function of the
CPropertySheetclass.Itssyntaxis:
voidAddPage(CPropertyPage*pPage)
You can call this member function where the property sheet is created. This could be in the
constructoroftheCPropertySheetderivedclass.

PracticalLearning:CreatingaPropertySheet
1. Tocreateanewclass,onthemainmenu,clickProject>AddClass...

2. ClickMFCClassandclickAdd
3. SettheClassNametoCAlgebraSheet
4. SettheBaseClasstoCPropertySheet

PHP code
generator
Generate PHP code for
any database.
AJAX,charts,dynamic
forms and more

5. ClickFinish
6. ChangetheAlgebraSheet.hdocumentasfollows:
#pragmaonce
#include"QuadrilateralDlg.h"
#include"CircularDlg.h"
#include"Diamension3Dlg.h"
//CAlgebraSheet
classCAlgebraSheet:publicCPropertySheet
{
DECLARE_DYNAMIC(CAlgebraSheet)
public:
CAlgebraSheet(UINTnIDCaption,

CWnd*pParentWnd=NULL,

UINTiSelectPage=0)
CAlgebraSheet(LPCTSTRpszCaption,

CWnd*pParentWnd=NULL,

UINTiSelectPage=0)
virtual~CAlgebraSheet()
private:
CQuadrilateralDlgdlgQuadrilateral
CCircularDlgdlgCircular
CDiamension3DlgdlgDiamension3
protected:
DECLARE_MESSAGE_MAP()
}
7. AccesstheRepairOrderSheet.dppfileandchangetheconstructorthattakesastringasitsfirst
argumentasfollows:
CAlgebraSheet::CAlgebraSheet(LPCTSTRpszCaption,

CWnd*pParentWnd,

UINTiSelectPage)

:CPropertySheet(pszCaption,pParentWnd,iSelectPage)
{

this>AddPage(&dlgQuadrilateral)

this>AddPage(&dlgCircular)

this>AddPage(&dlgDiamension3)
}

DisplayingaPropertySheet
A property sheet is primarily a dialog box. As such, to display it, you can simply call the
DoModal()memberfunctionoftheCDialogclass.

PracticalLearning:DisplayingaPropertySheet
1. IntheSolutionExplorer,doubleclickAlgebra1.cpp
2. Changethefileasfollows:
//Algebra1.cpp:Definestheclassbehaviorsfortheapplication.
//

#include"stdafx.h"
#include"Algebra1.h"
#include"QuadrilateralDlg.h"
#include"AlgebraSheet.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#endif
...NoChange
BOOLCAlgebra1App::InitInstance()
{

//InitCommonControlsEx()isrequiredonWindowsXPifanapplication

//manifestspecifiesuseofComCtl32.dllversion6orlatertoenable

//visualstyles.Otherwise,anywindowcreationwillfail.

INITCOMMONCONTROLSEXInitCtrls

InitCtrls.dwSize=sizeof(InitCtrls)

//Setthistoincludeallthecommoncontrolclassesyouwanttouse

//inyourapplication.

InitCtrls.dwICC=ICC_WIN95_CLASSES

InitCommonControlsEx(&InitCtrls)

CWinApp::InitInstance()

AfxEnableControlContainer()

//Createtheshellmanager,incasethedialogcontains
//anyshelltreevieworshelllistviewcontrols.
CShellManager*pShellManager=newCShellManager

//Standardinitialization
//Ifyouarenotusingthesefeaturesandwishtoreducethesize
//ofyourfinalexecutable,youshouldremovefromthefollowing
//thespecificinitializationroutinesyoudonotneed
//Changetheregistrykeyunderwhichoursettingsarestored
//TODO:Youshouldmodifythisstringtobesomethingappropriate
//suchasthenameofyourcompanyororganization
SetRegistryKey(_T("LocalAppWizardGeneratedApplications"))

//CQuadrilateralDlgdlg
CAlgebraSheetdlg(L"ElementaryAlgebra")

m_pMainWnd=&dlg

//Deletetheshellmanagercreatedabove.
if(pShellManager!=NULL)
{

deletepShellManager
}

//Sincethedialoghasbeenclosed,returnFALSEsothatweexitthe
//application,ratherthanstarttheapplication'smessagepump.
returnFALSE

INT_PTRnResponse=dlg.DoModal()
if(nResponse==IDOK)
{

//TODO:Placecodeheretohandlewhenthedialogis

//dismissedwithOK
}
elseif(nResponse==IDCANCEL)
{

//TODO:Placecodeheretohandlewhenthedialogis

//dismissedwithCancel
}

3. Toexecutetheapplication,pressF5

4. Closethedialogboxandreturntoyourprogrammingenvironment

CharacteristicsofaPropertySheetanditsPropertyPages

Introduction
Apropertysheetisprimarilyadialogbox.Assuchitappearsasarectangularboxwithoneormoretabs
andbuttons.IntheWin32library,apropertypageiscreatedfromastructurenamedPROPSHEETPAGE.
To give you a connection to that structure, the CPropertyPage is equipped with a member variable
namedm_psh:
PROPSHEETPAGEm_psp
In the Win32 library, a property sheet is created from a structure named PROPSHEETHEADER. This
structureisrepresentedinCPropertySheetclassbyapropertynamedm_psh:
CPropertySheet::m_psh
Them_pshgivesaccesstotheWin32characteristicsofapropertysheet.

TheButtonsofaPropertySheet
Initsnormaldesign,apropertyisusuqllyequippedwithanOKandacancelbutton.Insomecases,itmay
haveanApplybutton.Thefunctionalityofthebuttonsofapropertysheetare:
TheOKbuttonallowstheusertovalidateanychange(s)madeonthecontrol(s)ofthepropertypage(s)
andclosethedialogbox.Forexample,iftheuserchangestextfromaneditboxandclicksOK,the
applicationthatcalledthedialogwillhavetheopportunitytoacknowledgethechangeandact
accordingly,andthepropertysheetwouldbeclosed
IftheuserclicksCancel,thechange(s)madeonthepropertypage'scontrol(s)wouldbediscarded,not
takenintoconsideration,andthepropertysheetwouldbeclosed
IfthepropertysheethasanApplybutton,whenthepropertysheetcomesup,theApplybuttononthe
propertypageisdisabled.Iftheuserchangessomethingonthecontrolsofthepropertypage(s),the
Applybuttonwouldbecomeenabled.OncetheApplybuttonisenabled,theusercanuseit.Iftheuser
clickstheApplybutton,1)anychange(s)madeonthecontrol(s)is(are)senttotheobjectthatcalled
thepropertysheet,2)theApplybuttonbecomesdisabledagain,3)thedialogboxremainsopened.
ThisdescriptionisconformingtothestandardsorsuggestionsoftheMicrosoftWindowsoperating
system.
Inreality,youarecompletelyfreetodowhatyouwantwiththebuttonsonthepropertysheet:
Youcanhidethem
Youcandisplaythem
Youcancompletelydelete(destroy)anyunneededbutton
Youcanaddasmanybuttonsasyoujudgenecessaryandasthebottomareacanafford
Youcanchangethecaptionsofthebuttons
Someoftheseissueswealreadyknowhowtodo.WealreadyknowthateachcontrolofanMFCapplication
has an identifier. The buttons automatically added to a property sheet are identified as IDOK for the OK
button and IDCANCEL for the Cancel button. If a property sheet has an Apply button, its identifier is
ID_APPLY_NOW.IfthepropertysheethasaHelpbutton,theidentifierofthatbuttonisIDHELP.
To manipulate any of these buttons, you can call the CWnd::GetDlgItem() member function to get a
handletothedesiredbuttonanddowhatyouwantwithit.Hereisanexamplecodeyoucanusetochange
thecaptionofabutton,hideanotherbutton,orsimplydestroyanother:
BOOLCGeomeSheet::OnInitDialog()
{
BOOLbResult=CPropertySheet::OnInitDialog()
//TODO:Addyourspecializedcodehere
//ChangethecaptionoftheOKbutton
CButton*btnOK
btnOK=reinterpret_cast<CButton*>(GetDlgItem(IDOK))
btnOK>SetWindowText("Sumbit")
//HidetheApplybutton
CButton*btnApply
btnApply=reinterpret_cast<CButton*>(GetDlgItem(ID_APPLY_NOW))

btnApply>ShowWindow(FALSE)
//DestroytheHelpbutton
CButton*btnHelp
btnHelp=reinterpret_cast<CButton*>(GetDlgItem(IDHELP))
btnHelp>DestroyWindow()
returnbResult
}
Toaddabutton,declareapointertoCButtonandcallitsCreate()memberfunctiontoinitialize.Wehave
seen various examples of how to dynamically create a control. If you decide to dynamically create a
button,someoftheissuesyouwouldhavetodealwithherearethelocationandprobablythesizeofthe
newbutton,whichhavelittletodowithprogrammingbutwithgeometry.Hereisanexample:
BOOLCGeomeSheet::OnInitDialog()
{
BOOLbResult=CPropertySheet::OnInitDialog()
//TODO:Addyourspecializedcodehere
//Apointertobuttonwewillneed
CButton*btnApply
//WewillneedtolocationanddimensionsoftheApplybutton
CRectRectApply
//GetahandletotheApplybutton
btnApply=reinterpret_cast<CButton*>(GetDlgItem(ID_APPLY_NOW))
//GetthelocationandthedimensionsoftheApplybutton
btnApply>GetWindowRect(&RectApply)
//Convertthelocationanddimensionstoscreencoordinates
ScreenToClient(&RectApply)
CButton*Whatever=newCButton
Whatever>Create("&Whatever",WS_CHILD|WS_VISIBLE,

CRect(6,RectApply.top,85,

RectApply.top+RectApply.Height()),

this,0x188)
returnbResult
}
Anotherissueyouwoulddealwithiseachofthemessagessentbyyourdynamicbutton.Manipulatingone
buttonhasnoinfluenceontheother(s).Forexample,ifyoudestroytheCancelbutton,theOKbuttondoes
notmovetotheright.Youwouldhavetorepositionanybuttonasyoujudgeitnecessary.
We have already mentioned that, by standard and by design, the Apply button is disabled when the
propertysheetcomesup.Itissupposedtobecomeenabledoncetheusergetsanycontrol"dirty"thatis,
once a control, any control, is not the same as it was when the dialog box came up, the Apply button
becomes available. To enable this control programmatically, once a control becomes dirty, call the
CPropertyPage::SetModified().Itssyntaxis:
voidSetModified(BOOLbChanged=TRUE)
Thismemberfunctioniscalledbythecontrolwhosevalueyouwanttovalidateoncetheuserhasmodified
it.WhentheuserclickstheOKbutton,theCPropertyPage::OnOK()eventfires.Bydesign,thechanges
made on the controls are acknowledged. The controls receive the status of "clean". The property sheet
closes.
When the user clicks the Cancel button, the CPropertyPage::OnCancel() event fires. By design, the
changesmadeonthecontrolsaredismissed.Thecontrolsvaluesarekeptastheywerewhentheproperty
sheetdisplayedaslongastheuserdidnotpreviouslyclickApplysincethepropertysheetwasopened.The
propertysheetcloses.
When the user clicks the Apply button, the CPropertyPage::OnApply() event fires. The changes that
weremadeonthecontrolsareacknowledged.Thepropertysheetstaysopened.
Once again, these behaviors are the default suggested by the standard but you can change them as you
wish, although you should remain with these suggestions because your users may be more familiar with
them.

PracticalLearning:ConfiguringtheButtonsofaPropertySheet
1. Onthemainmenu,clickProject>ClassWizard...
2. IntheClassNamecombobox,selectCAlgebraSheet
3. ClicktheVirtualFuntionstab
4. IntheVirtualFunctionslist,doubleclickOnInitDialog

5. ClickEditCode
6. TodeletetheApplyandtheHelpbuttons,changethefileasfollows:
BOOLCAlgebraSheet::OnInitDialog()
{

BOOLbResult=CPropertySheet::OnInitDialog()

//TODO:Addyourspecializedcodehere
//Wewillneedapointertoeachbutton
CButton*btnOK,*btnCancel,*btnApply,*btnHelp
//WewillneedtolocationanddimensionsofApplyandHelp
CRectRectApply,RectHelp

//PuttheCancelbuttonwheretheHelpbuttonwas
btnCancel>SetWindowPos(NULL,RectHelp.left,RectHelp.top,0,0,

SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW)

returnbResult

//GethandlestotheOKandCancelbuttons
btnOK=reinterpret_cast<CButton*>(GetDlgItem(IDOK))
btnCancel=reinterpret_cast<CButton*>(GetDlgItem(IDCANCEL))
//GetahandletotheApplybutton
btnApply=reinterpret_cast<CButton*>(GetDlgItem(ID_APPLY_NOW))
//GetthelocationandthedimensionsoftheApplybutton
btnApply>GetWindowRect(&RectApply)
//GetahandletotheHelpbutton
btnHelp=reinterpret_cast<CButton*>(GetDlgItem(IDHELP))
//GetthelocationandthedimensionsoftheHelpbutton
btnHelp>GetWindowRect(&RectHelp)
//DismisstheApplyandtheHelpbuttons
btnApply>DestroyWindow()
btnHelp>DestroyWindow()
//Convertthelocationanddimensionstoscreencoordinates
ScreenToClient(&RectApply)
ScreenToClient(&RectHelp)
//PuttheOKbuttonwheretheApplybuttonwas
btnOK>SetWindowPos(NULL,RectApply.left,RectApply.top,0,0,

SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW)

7. Totesttheapplication,pressF9

8. Closetheapplicationandreturntoyourprogrammingenvironment

PHP

CODE

GENERATOR

Generate PHP code for any local or remote database.

Home

Copyright2010FunctionX,Inc.

MFCPropertySheetsandPropertyPages

IntroductiontotheMFCPropertySheet

Description
MFC
VisualC++
C++Example
...

TheclassicpropertysheetshavebeenpartoftheMicrosoftWindows
operating system for a long time. Applications functionalities and
requirements have seen an increase in the last few years withnew
aesthetic features. To keep the trend, the new MFC brought new
controls.Oneofthemisanewtypeofpropertysheet.

TheMFCpropertysheetaddsnewbehaviorstotheclassicpropertysheetinthewaysthetabs
displayortheircontentsareaccessed.

PracticalLearning:IntroducingMFCPropertySheets
1. StartMicrosoftVisualStudio
2. Tocreateanewapplication,onthemainmenu,clickFile>NewProject...
3. Intheleftlist,clickVisualC++.Intherightlist,clickMFCApplication
4. ChangetheNametoLifePlanning
5. ClickOK
6. InthefirstpageoftheMFCApplicationWizard,readthetextandclickNext
7. Inthesecondpageofthewizard,clickDialogBased
8. ClickNext
9. Inthethirdpage,clickNext
10. Inthefourthpageofthewizard,clickNext
11. Inthefifthpageofthewizard,clickFinish
12. Onthedialogbox,clicktheTODOlineandpressDelete

CreatinganMFCPropertyPage
The MFC property sheet and its property page(s) are primarily created like the classic
property sheet. In fact, a property page is created as a dialog box with the following
characteristics:
Border:Thin
Caption:Setthestringyouwanttodisplayonthetab(orbutton)
Disabled:True
Style:Child
TitleBar:True
An MFC property page is based on a class named CMFCPropertyPage that is derived from
CPropertyPage.Therefore,tocreateanMFCpropertypage:
a. Createadialogboxresourcewiththecharacteristicsofapropertypage
b. Addaclasstothedialogbox.TheclassmustbederivedfromCMFCPropertyPage
c. Optionallyaddthefunctionalities(controls,events,etc)youwantthepropertypageto
execute

PracticalLearning:CreatingMFCPropertyPages
1. Onthemainmenu,clickProject>ClassWizard...
2. ClickAddClass
3. SettheClassNametoCComputerScience
4. SettheBaseClasstoCMFCPropertyPage

5. ClickFinish
6. ClickAddClass
7. SettheClassNametoCInformationTechnology
8. SettheBaseClasstoCMFCPropertyPage
9. ClickFinish
10. ClickAddClass
11. SettheClassNametoCHistory
12. SettheBaseClasstoCMFCPropertyPage
13. ClickFinish
14. ClickAddClass
15. SettheClassNametoCCulinaryServices
16. SettheBaseClasstoCMFCPropertyPage
17. ClickFinish
18. ClickAddClass
19. SettheClassNametoCCareers
20. SettheBaseClasstoCMFCPropertyPage
21. ClickFinish
22. ClickOK
23. IntheResourceView,rightclickLifePlanningandclickAddResource...
24. IntheAddResourcedialogbox,expandtheDialognode
25. ClickIDD_PROPPAGE_LARGE
26. ClickNew
27. InthePropertieswindow,changethefollowingcharacteristics:
Caption:ComputerScience
ID:IDD_COMPUTERSCIENCE
28. OntheToolboxclickButtonandclickthedialogbox
29. AccesstheComputerScience.hfileandchangeitasfollows:
#pragmaonce
//CComputerScience
classCComputerScience:publicCMFCPropertyPage
{

DECLARE_DYNAMIC(CComputerScience)
//DialogData

enum{IDD=IDD_COMPUTERSCIENCE}
public:

CComputerScience()

virtual~CComputerScience()
protected:

DECLARE_MESSAGE_MAP()
}
30. IntheResourceView,rightclickLifePlanningandclickAddResource...
31. IntheAddResourcedialogbox,expandtheDialognode
32. ExpandDialogandclickIDD_PROPPAGE_LARGE

33. ClickNew
34. InthePropertieswindow,changethefollowingcharacteristics:
Caption:InformationTechnology
ID:IDD_INFORMATIONTECHNOLOGY
35. OntheToolboxclickCheckBoxandclickthedialogbox
36. AccesstheInformationTechnology.hfileandchangeitasfollows:
#pragmaonce
//CInformationTechnology
classCInformationTechnology:publicCMFCPropertyPage
{

DECLARE_DYNAMIC(CInformationTechnology)
//DialogData

enum{IDD=IDD_INFORMATIONTECHNOLOGY}
public:

CInformationTechnology()

virtual~CInformationTechnology()
protected:

DECLARE_MESSAGE_MAP()
}
37. IntheResourceView,rightclickLifePlanning.rcandclickAddResource...
38. IntheAddResourcedialogbox,expandtheDialognode
39. ExpandDialoganddoubleclickIDD_PROPPAGE_SMALL
40. InthePropertieswindow,changethefollowingcharacteristics:
Caption:History
ID:IDD_HISTORY
41. OntheToolboxclickEditControlandclickthedialogbox
42. AccesstheHistory.hfileandchangeitasfollows:
#pragmaonce
//CHistory
classCHistory:publicCMFCPropertyPage
{

DECLARE_DYNAMIC(CHistory)
//DialogData

enum{IDD=IDD_HISTORY}
public:

CHistory()

virtual~CHistory()
protected:

DECLARE_MESSAGE_MAP()
}
43. IntheResourceView,rightclickLifePlanningandclickAddResource...
44. IntheAddResourcedialogbox,expandtheDialognode
45. ExpandDialoganddoubleclickIDD_PROPPAGE_MEDIUM
46. InthePropertieswindow,changethefollowingcharacteristics:
Caption:CulinaryServices
ID:IDD_CULINARYSERVICES
47. OntheToolboxclickPictureControlandclickthedialogbox
48. AccesstheCulinaryServices.hfileandchangeitasfollows:
#pragmaonce
//CCulinaryServices
classCCulinaryServices:publicCMFCPropertyPage
{

DECLARE_DYNAMIC(CCulinaryServices)
//DialogData

enum{IDD=IDD_CULINARYSERVICES}
public:

CCulinaryServices()

virtual~CCulinaryServices()
protected:

DECLARE_MESSAGE_MAP()
}
49. IntheResourceView,rightclickLifePlanningandclickAddResource...
50. IntheAddResourcedialogbox,expandtheDialognode
51. ExpandDialoganddoubleclickIDD_PROPPAGE_LARGE
52. InthePropertieswindow,changethefollowingcharacteristics:
Caption:Careers
ID:IDD_CAREERS
53. OntheToolboxclickStaticTextandclickthedialogbox

54. AccesstheCareers.hfileandchangeitasfollows:
#pragmaonce
//CCareers
classCCareers:publicCMFCPropertyPage
{

DECLARE_DYNAMIC(CCareers)
//DialogData

enum{IDD=IDD_CAREERS}
public:

CCareers()

virtual~CCareers()
protected:

DECLARE_MESSAGE_MAP()
}

CreatinganMFCPropertySheet
An MFC property sheet is primarily a normal property sheet. In fact, the class used for it is
namedCMFCPropertySheetand it is directly derived from CPropertySheet.Therefore, to
createanMFCpropertysheet,createanMFCclassbasedonCMFCPropertySheet.
Tospecifythepagesofthepropertysheet,intheconstructorofyourpropertysheetclassor
just before displaying the property sheet, call the CPropertySheet::AddPage() method for
eachpropertypage.
Todisplaythepropertysheet,calltheCDialog::DoModal()memberfunctionitinheritsfrom
itsparent.

PracticalLearning:CreatinganMFCPropertySheet
1. Onthemainmenu,clickProject>ClassWizard...
2. ClickAddClass
3. SettheClassNametoCLifePlanningSheet
4. SettheBaseClasstoCMFCPropertySheet
5. ClickFinish
6. ClickOK

CharacteristicsofanMFCPropertySheet

CharacteristicsofMFCPropertyPages
The MFC property page gets most of its functionality from its parent: the Win32's property
pagethatisimplementedthroughtheCPropertyPage.Still,theCMFCPropertyPagehasits
ownconstructorthatisdifferentfromitsparentclass.Theconstructorcomesintwoversions
whosesyntaxesare:
CMFCPropertyPage(UINTnIDTemplate,UINTnIDCaption=0)
CMFCPropertyPage(LPCTSTRlpszTemplateName,UINTnIDCaption=0)
Thefirstargument,whichisalsotheonlyonerequired,iseithertheresourceIDofthedialog
boxorthenameofthetemplatethatholdsthecharacteristicsofthedialogboxtemplate.The
secondargument,whichisoptional,isthestringIDofthecaption.

PracticalLearning:ConfiguringMFCPropertyPages
1. AccesstheComputerScience.cppfileandchangetheconstructorasfollows:
//ComputerScience.cpp:implementationfile
//
#include"stdafx.h"
#include"LifePlanning.h"
#include"ComputerScience.h"
//CComputerScience
IMPLEMENT_DYNAMIC(CComputerScience,CMFCPropertyPage)
CComputerScience::CComputerScience()

:CMFCPropertyPage(CComputerScience::IDD)
{
}
CComputerScience::~CComputerScience()
{
}
BEGIN_MESSAGE_MAP(CComputerScience,CMFCPropertyPage)
END_MESSAGE_MAP()
//CComputerSciencemessagehandlers
2. AccesstheInformationTechnology.cppfileandchangetheconstructorasfollows:
IMPLEMENT_DYNAMIC(CInformationTechnology,CMFCPropertyPage)

CInformationTechnology::CInformationTechnology()

:CMFCPropertyPage(CInformationTechnology::IDD)
{
}
3. AccesstheHistory.cppfileandchangetheconstructorasfollows:
CHistory::CHistory()

:CMFCPropertyPage(CHistory::IDD)
{
}
4. AccesstheCulinaryServices.cppfileandchangetheconstructorasfollows:
CCulinaryServices::CCulinaryServices()

:CMFCPropertyPage(CCulinaryServices::IDD)
{
}
5. AccesstheCareers.hfileandchangeitasfollows:
CCareers::CCareers()

:CMFCPropertyPage(CCareers::IDD)
{
}

IntroductiontotheLooksofanMFCPropertySheet
ThemostfundamentaldifferencebetweenaclassicpropertysheetandanMFCpropertysheet
is on how the latter displays its property pages. To allow the options, the
CMFCPropertySheetclassisequippedwiththeSetLook()memberfunction.Itssyntaxis:
voidSetLook(PropSheetLooklook,intnNavControlWidth=100)
Only the first argument is required and it specifies how the property pages should be
accessed. To set the option, call the CMFCPropertySheet enumeration and access the
desiredmember (next sections). The second argument is optional and it doesn't apply to all
options(wewillcomebacktoitinthenextsections).

PracticalLearning:IntroducingtheLookofanMFCProperty
Sheet
AccesstheLifePlanningSheet.hfileandchangeitasfollows:
#pragmaonce
#include"ComputerScience.h"
#include"InformationTechnology.h"
#include"History.h"
#include"CulinaryServices.h"
#include"Careers.h"

//CLifePlanningSheet
classCLifePlanningSheet:publicCMFCPropertySheet
{
DECLARE_DYNAMIC(CLifePlanningSheet)
public:
CLifePlanningSheet()
virtual~CLifePlanningSheet()
private:
CComputerScience

CInformationTechnology
CHistory

CCulinaryServices
CCareers

pgeComputerScience
pgeInformationTechnology
pgeHistory
pgeCulinaryServices
pgeCareers

protected:
DECLARE_MESSAGE_MAP()
}

TheClassicLookofanMFCPropertySheet
Asmentionedalready,anMFCpropertyisprimarilyaWin32propertysheet.Ityoujustwant
to create a normal property sheet, before it can display, simply call its AddPage()member
functionandaddthedesiredpropertypages.Hereareexamples:
CExerciseSheet::CExerciseSheet()
{
AddPage(&pgeFirst)
AddPage(&pgeSecond)
AddPage(&pgeThird)
}
In
the
same
way,
to
create
the
classic
property
sheet,
call
the
CMFCPropertySheet::SetLook() member function and specofy the PropSheetLook_Tabs
option.Hereareexamples:
CExerciseSheet::CExerciseSheet()
{
AddPage(&pgeFirst)

AddPage(&pgeSecond)
AddPage(&pgeThird)

SetLook(CMFCPropertySheet::PropSheetLook_Tabs)
}
Theresultwouldbethesame.

PracticalLearning:SettingtheClassicLook
1. AccesstheLifePlanningSheet.cppfileandchangeitasfollows:
CLifePlanningSheet::CLifePlanningSheet()
{
AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
SetLook(CMFCPropertySheet::PropSheetLook_Tabs)
}
2. Displaythefirstdialogboxandaddabuttontoit
3. UsingthePropertieswindow,changeitscharacteristicsasfollows:
Caption:PlanYourLife...
ID:IDC_PLAN_YOUR_LIFE
4. Doubleclickthebutton
5. Changethefileasfollows:
//LifePlanningDlg.cpp:implementationfile
//
#include"stdafx.h"
#include"LifePlanning.h"
#include"LifePlanningDlg.h"
#include"afxdialogex.h"
#include"LifePlanningSheet.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#endif
//CLifePlanningDlgdialog
...NoChange
voidCLifePlanningDlg::OnBnClickedPlanYourLife()
{
//TODO:Addyourcontrolnotificationhandlercodehere
CLifePlanningSheetdlgLifePlanning
dlgLifePlanning.SetTitle(L"CareerPlanningandLifeAchievement")
dlgLifePlanning.DoModal()
}
6. Toexecute,pressF5
7. ClickthePlanYourLife...

8. Closethepropertysheet
9. Closethedialogboxandreturntoyourprogrammingenvironment

TheOneNoteLookofanMFCPropertySheet
To make the tabs more appealling, you can make them look like those of the Microsoft
OneNote application. To get this option, call the SetLook() member function and apply the
PropSheetLook_OneNoteTabsoption.

PracticalLearning:SettingtheOneNoteLook
1. AccesstheLifePlanningSheet.cppfileandchangeitasfollows:
CLifePlanningSheet::CLifePlanningSheet()

{
//1.Classicpropertysheet
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
SetLook(CMFCPropertySheet::PropSheetLook_Tabs)*/

//2.MicrosoftOneNotetabs
AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
AddPage(&pgeHistory)
AddPage(&pgeCulinaryServices)
SetLook(CMFCPropertySheet::PropSheetLook_OneNoteTabs)
}
2. Toexecute,pressF5
3. ClickthePlanYourLife...
4. ClicktheCulinaryServicestab
5. ClickHistory

6. Closethepropertysheet
7. Closethedialogboxandreturntoyourprogrammingenvironment

TheOutlookBaronanMFCPropertySheet
Insteadofdisplayingtabsinthetopsectionofapropertysheet,youcancreateaverticalbar
ontheleftsideofthedialogboxandmakeitdisplayabuttonforeachtab.Thisispopularly
referred to as the Outlook or Outlook Bar look of an application. In this case, the property
sheetwouldbedividedintwosections:aframeontheleftandtherightareausedtodisplay
thepropertypages.
RememberthatthesyntaxoftheCMFCPropertySheet::SetLook()memberfunctionis:
voidSetLook(PropSheetLooklook,intnNavControlWidth=100)
The second argument specifies the width of the left frame. The default with is 100 pixels,
whichappliesifyoudon'tpassthesecondargument.Tospecifyyourdesiredwidth,passthe
secondargument.
If you are familiar with Microsoft Outlook bar, you may know that each button displays a
pictureontop.BeforeconsideringgettingtheOutlookbarlook,youshould(must)firstcreate
one ore more icons, an icon for each button that would lead to the corresponding property
page. You can create the list of icons as a long bitmap resource. After creating the physical
bitmap, declare a variable of type CImageList and call its Create() member function to
initializeit.Passthebitmapresourcetoit.
ToletyougettheOutlookbar,theCMFCPropertySheetisequippedwiththeSetIconsList()
memberfunctionthatisoverloadedwithtwovesions.Theirsyntaxesare:
voidSetIconsList(HIMAGELISThIcons)
BOOLSetIconsList(UINTuiImageListResID,

intcx,

COLORREFclrTransparent=RGB(255,0,255))
ThefirstversiontabkesahandletoaWin32'simagelistasargument.
The second version takes two required arguments and an optional argument. The first
argumentistheIDofanimagelistresource.Thesecondargumentspecifiesthewidthoreach
picture in the image list. The third argument optionally specifies the level or transparency of
htepictures.
To get the Outlook bar, call the SetLook() member function and apply the
PropSheetLook_OutlookBaroption.

PracticalLearning:UsingtheOutlookBar
1. IntheResourceView,rightclickLifePlanning>Add>Resource...
2. IntheAddResourcedialogbox,clickBitmapandclickNew
3. InthePropertieswindow,changethefollowingvalues:

Color:24bit
Height:32
Width:96
4. IntheResourceView,clickIDB_BITMAP1
5. InthePropertieswindow,clickID,typeIDB_OUTLOOKandpressEnter
6. Designthebitmapasfollows:

CareerPlanningandLifeAchievement

7. AccesstheLifePlanningSheet.hfileanddeclareaCImageListvariablenamedm_OutlookImages:
#pragmaonce
#include"ComputerScience.h"
#include"InformationTechnology.h"
#include"History.h"
#include"CulinaryServices.h"
#include"Careers.h"
//CLifePlanningSheet
classCLifePlanningSheet:publicCMFCPropertySheet
{
DECLARE_DYNAMIC(CLifePlanningSheet)
public:
CLifePlanningSheet()
virtual~CLifePlanningSheet()
private:
CComputerScience
pgeComputerScience
CInformationTechnology
pgeInformationTechnology
CHistory

pgeHistory
CCulinaryServices pgeCulinaryServices
CCareers

pgeCareers
CImageListm_OutlookImages
protected:
DECLARE_MESSAGE_MAP()
}
8. AccesstheLifePlanningSheet.cppfileandchangeitasfollows:
CLifePlanningSheet::CLifePlanningSheet()
{
//1.Classicpropertysheet
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
SetLook(CMFCPropertySheet::PropSheetLook_Tabs)*/

//2.MicrosoftOneNotetabs
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
AddPage(&pgeHistory)
AddPage(&pgeCulinaryServices)
SetLook(CMFCPropertySheet::PropSheetLook_OneNoteTabs)*/

//3.OutlookBar
AddPage(&pgeComputerScience)
AddPage(&pgeHistory)
AddPage(&pgeCulinaryServices)
m_OutlookImages.Create(IDB_OUTLOOK,32,1,RGB(128,128,128))
SetIconsList(m_OutlookImages)
SetLook(CMFCPropertySheet::PropSheetLook_OutlookBar)
}
9. Toexecute,pressF5
10. ClicktheCulinaryServicesicon
11. PositionthemouseonComputerScience

12. Closethepropertysheet
13. Closethedialogboxandreturntoyourprogrammingenvironment

UsingaListofLabels
Instead of using tabs or buttons, you can create strings that each would behave like a link. The user
can create a label to access a property page. To get this behavior, call the SetLook() member
functionandapplythePropSheetLook_Listoption.
As seen for the Outlook bar, if you use a list of strings, there would be a bar on the left side of the
propertysheetandthatbarwouldbeequippedwiththestrings.

PracticalLearning:UsingaList
1. ChangetheLifePlanningSheet.cppfileitasfollows:
CLifePlanningSheet::CLifePlanningSheet()
{
//1.Classicpropertysheet
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
SetLook(CMFCPropertySheet::PropSheetLook_Tabs)*/

//2.MicrosoftOneNotetabs
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
AddPage(&pgeHistory)
AddPage(&pgeCulinaryServices)
SetLook(CMFCPropertySheet::PropSheetLook_OneNoteTabs)*/

//3.OutlookBar
/*AddPage(&pgeComputerScience)
AddPage(&pgeHistory)
AddPage(&pgeCulinaryServices)
m_OutlookImages.Create(IDB_OUTLOOK,32,1,RGB(128,128,128))
SetIconsList(m_OutlookImages)
SetLook(CMFCPropertySheet::PropSheetLook_OutlookBar)*/

//4.List
AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
AddPage(&pgeCulinaryServices)
SetLook(CMFCPropertySheet::PropSheetLook_List,150)
}
2. Toexecute,pressF5

3. Closethepropertysheet
4. Closethedialogboxandreturntoyourprogrammingenvironment

UsingaTreeListofNodes
One of the characteristics of a list of labels is that each string is independent of the others. As
alternative,youcancreateatreeoflabelssothatitwouldshowthatsomelabelsbelongtoagroup,
andconsequentlysomepropertypagesworktogether.Thelabelsinthiscasearecallednodes.
Ifyouuseatreelist,thepropertysheetdisplaysabarontheleftside.Thelistonthatsidecanhave
strings like those of the previously seen list. To enhance it, you can create one or more nodes that
behaveasparentstoothernodes.Whenanodeisusedasaparent,iftheuserclicksit,itexpandsto
showitschildnodes.Iftheuserclicksthatparentnodeagain,itcollapsestohiditschildnodes.Inall
cases,iftheuserclicksanodeontheleftside,itspropertypagedisplaysontherightside.
To get a tree list, first call the SetLook() member function and apply the
CMFCPropertySheet::PropSheetLook_Tree.Ifyoustopthere,thepropertysheetwouldbehavelike
thatofthelistoflabels.Ifyouwantanactuallist,youmustcreate.Fortunately,itiseasyaslongas
youfollowtherightsteps.
Toletyoucreateatreelist,theCMFCPropertySheetclassisequippedwiththeAddTreeCategory()
memberfunction.Itssyntaxis:
CMFCPropertySheetCategoryInfo*AddTreeCategory(
LPCTSTRlpszLabel,
intnIconNum=1,
intnSelectedIconNum=1,
constCMFCPropertySheetCategoryInfo*pParentCategory=NULL
)
WhencallingthisfunctiongetareferencetotheCMFCPropertySheetCategoryInfoobjectitreturns.
This function takes four argument but only one is required. The first argument is the string of the
parent node. You can pass just that argument and the property sheet would work fine. If you want a
nodetodisplayanicon,passthezerobasedindexofthaticonasthesecondargument.Inthiscase,
youcanalsopassathirdargumentastheiconthatwoulddisplaywhentheparentnodeisselected.If
thenodeyouarecurrentlycreatingisthetopnode,passthethirdargumentasNULL.Ifthatnodehas
itsownparent,passitsreferenceasthefourthargument.
Aftercallingthismemberfunction,callthetheAddPageToTree()memberfunction.Itssyntaxis:
voidAddPageToTree(
CMFCPropertySheetCategoryInfo*pCategory,
CMFCPropertyPage*pPage,
intnIconNum=1,
intnSelIconNum=1
)
The first argument is a reference to a parent node you must have previously created. The second
argument is a reference to a property page, the exact same argument you would pass for a regular
propertypage in a Win32 property sheet. If the node should display an icon, pass the optional third
argument. Also, you can optionally pass the fourth argument to specify what icon the node should
displaywhenitisselected.

PracticalLearning:UsingaTreeList
1. ChangetheLifePlanningSheet.cppfileitasfollows:
CLifePlanningSheet::CLifePlanningSheet()
{
//1.Classicpropertysheet
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
SetLook(CMFCPropertySheet::PropSheetLook_Tabs)*/

//2.MicrosoftOneNotetabs
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
AddPage(&pgeHistory)
AddPage(&pgeCulinaryServices)
SetLook(CMFCPropertySheet::PropSheetLook_OneNoteTabs)*/

//3.OutlookBar
/*AddPage(&pgeComputerScience)
AddPage(&pgeHistory)
AddPage(&pgeCulinaryServices)
m_OutlookImages.Create(IDB_OUTLOOK,32,1,RGB(128,128,128))
SetIconsList(m_OutlookImages)
SetLook(CMFCPropertySheet::PropSheetLook_OutlookBar)*/

//4.List
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
AddPage(&pgeCulinaryServices)
SetLook(CMFCPropertySheet::PropSheetLook_List,150)*/

//5.TreeList
SetLook(CMFCPropertySheet::PropSheetLook_Tree,150)
CMFCPropertySheetCategoryInfo*pscComputers=AddTreeCategory(_T("Computers"))
AddPageToTree(pscComputers,&pgeComputerScience)
AddPageToTree(pscComputers,&pgeInformationTechnology)
AddPage(&pgeHistory)
AddPage(&pgeCulinaryServices)
}
2. Toexecute,pressF5

3. Closethepropertysheet
4. Closethedialogboxandreturntoyourprogrammingenvironment
5. IntheResourceView,rightclickLifePlanning>Add>Resource...
6. IntheAddResourcedialogbox,clickBitmapandclickNew
7. InthePropertieswindow,changethefollowingvalues:
Color:24bit
Height:16
Width:64
8. IntheResourceView,clickIDB_BITMAP2
9. InthePropertieswindow,clickID,typeIDB_TREELISTandpressEnter
10. Designthebitmapasfollows:

CareerPlanningandLifeAchievement

11. AccesstheLifePlanningSheet.hfileanddeclareaCImageListvariablenamedm_OutlookImages:
#pragmaonce
#include"ComputerScience.h"
#include"InformationTechnology.h"
#include"History.h"
#include"CulinaryServices.h"
#include"Careers.h"
//CLifePlanningSheet
classCLifePlanningSheet:publicCMFCPropertySheet
{
DECLARE_DYNAMIC(CLifePlanningSheet)
public:
CLifePlanningSheet()
virtual~CLifePlanningSheet()
private:
CComputerScience

CInformationTechnology
CHistory

CCulinaryServices
CCareers

CImageListm_OutlookImages

pgeComputerScience
pgeInformationTechnology
pgeHistory
pgeCulinaryServices
pgeCareers

CImageListm_TreeListImages

protected:
DECLARE_MESSAGE_MAP()
}
12. AccesstheLifePlanningSheet.cppfileandchangeitasfollows:
CLifePlanningSheet::CLifePlanningSheet()
{
//1.Classicpropertysheet
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
SetLook(CMFCPropertySheet::PropSheetLook_Tabs)*/

//2.MicrosoftOneNotetabs
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
AddPage(&pgeHistory)
AddPage(&pgeCulinaryServices)
SetLook(CMFCPropertySheet::PropSheetLook_OneNoteTabs)*/

//3.OutlookBar
/*AddPage(&pgeComputerScience)
AddPage(&pgeHistory)
AddPage(&pgeCulinaryServices)
m_OutlookImages.Create(IDB_OUTLOOK,32,1,RGB(128,128,128))
SetIconsList(m_OutlookImages)
SetLook(CMFCPropertySheet::PropSheetLook_OutlookBar)*/

//4.List
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
AddPage(&pgeCulinaryServices)
SetLook(CMFCPropertySheet::PropSheetLook_List,150)*/

//5.TreeList
//Addtheiconstotheimagelist
m_TreeListImages.Create(IDB_TREELIST,16,1,RGB(255,255,255))
//Indicatethatthetreelistwilluseicons
SetIconsList(m_TreeListImages)
//Indicatethatthepropertysheetwilluseatreelist
SetLook(CMFCPropertySheet::PropSheetLook_Tree,185)
//CreatethetopnodeandnameitCollegeMajors
CMFCPropertySheetCategoryInfo*pscCollgeMajors=

AddTreeCategory(_T("CollegeMajors"),0,1)
//UndertheCollegeMajorsnode,createacategorynamedComputersRelated
CMFCPropertySheetCategoryInfo*pscComputers=

AddTreeCategory(_T("ComputersRelated"),2,3,pscCollgeMajors)
//Addthepagestothecategory
AddPageToTree(pscComputers,&pgeComputerScience)
AddPageToTree(pscComputers,&pgeInformationTechnology)
//AddtwocategoriestotheCollegeMajorsnode
AddPageToTree(pscCollgeMajors,&pgeHistory)
AddPageToTree(pscCollgeMajors,&pgeCulinaryServices)
//Addanodethatdoesn'thaveaparent
AddPage(&pgeCareers)
}
13. Toexecute,pressF5

14. Closethepropertysheet
15. Closethedialogboxandreturntoyourprogrammingenvironment
16. Changethedesignofthebitmapasfollows:

CareerPlanningandLifeAchievement

17. AccesstheLifePlanningSheet.cppfileandchangeitasfollows:
CLifePlanningSheet::CLifePlanningSheet()
{
//1.Classicpropertysheet
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
SetLook(CMFCPropertySheet::PropSheetLook_Tabs)*/

//2.MicrosoftOneNotetabs
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
AddPage(&pgeHistory)
AddPage(&pgeCulinaryServices)
SetLook(CMFCPropertySheet::PropSheetLook_OneNoteTabs)*/

//3.OutlookBar
/*AddPage(&pgeComputerScience)
AddPage(&pgeHistory)
AddPage(&pgeCulinaryServices)
m_OutlookImages.Create(IDB_OUTLOOK,32,1,RGB(128,128,128))
SetIconsList(m_OutlookImages)
SetLook(CMFCPropertySheet::PropSheetLook_OutlookBar)*/

//4.List
/*AddPage(&pgeComputerScience)
AddPage(&pgeInformationTechnology)
AddPage(&pgeCulinaryServices)
SetLook(CMFCPropertySheet::PropSheetLook_List,150)*/

//5.TreeList
//Addtheiconstotheimagelist
m_TreeListImages.Create(IDB_TREELIST,16,1,RGB(255,255,255))
//Indicatethatthetreelistwilluseicons
SetIconsList(m_TreeListImages)
//Indicatethatthepropertysheetwilluseatreelist
SetLook(CMFCPropertySheet::PropSheetLook_Tree,185)
//CreatethetopnodeandnameitCollegeMajors

CMFCPropertySheetCategoryInfo*pscCollgeMajors=

AddTreeCategory(_T("CollegeMajors"),0,1)
//UndertheCollegeMajorsnode,createacategorynamedComputersRelated
CMFCPropertySheetCategoryInfo*pscComputers=

AddTreeCategory(_T("ComputersRelated"),0,1,pscCollgeMajors)
//Addthepagestothecategory
AddPageToTree(pscComputers,&pgeComputerScience)
AddPageToTree(pscComputers,&pgeInformationTechnology)
//AddtwocategoriestotheCollegeMajorsnode
AddPageToTree(pscCollgeMajors,&pgeHistory)
AddPageToTree(pscCollgeMajors,&pgeCulinaryServices)
//Addanodethatdoesn'thaveaparent
AddPage(&pgeCareers)
}
18. PressF5toexecute

19. Closethepropertysheet
20. Closethedialogboxandreturntoyourprogrammingenvironment

PHP

WEBSITE

IN

MINUTES

Create PHP code for any database. No programming.

Home

Copyright2010FunctionX,Inc.

WizardPages

Introdution

MFC
VisualC++
C++Example
...

A wizard is a series of dialog boxes that are accessed consecutively.A


wizardcanconsistoftwoormorepages.Whenitstarts,itpresentsthe
startingorfirstpageanditusuallydisplaystwoormorebuttons.Oneof
the buttons may be disabled and display a caption as Back. Here is an
examplefromMicrosoftAccess:

To exploit it, the user would click a Next or Back buttons. The Next button allows the user to
accessthepagethatsucceedsthecurrentone.TheBackbuttonimplementstheopposite,allowing
theusertoaccessthepreviouspage.
When on the first page, after making a selection, the user can click Next. This would enable the
Back button. The wizard should have another button labeled Next. After making a selection on a
page,theusercanclickNext.Mostofthetime,awizardalsohasabuttonlabeledFinish:

In this case, at any time, the user can click the Finish. In some cases, a wizard has only two
buttonswithcaptionsasBackandNext.Wheninthefirstpage,theleftbuttonisdisabled.When
theusergetstothelastbutton,therightbuttonchangesfromNexttoFinish.
Bydefault,awizardhasatleasttwobuttonslabeledBackandNext.Asmentionedalready,when
theusergetstothelastpage,theNextbuttonbecomesFinish.Insomecases,suchasdescribed
fortheabovewizardinMicrosoftAccess,theFinishbuttonisseparate.Whentheusergetstothe
lastpage,theNextbuttonbecomesdisabled:

A wizard can also be equipped with a Cancel button. If the wizard is equipped with a Cancel
button, the user can close and dismiss it at any time. This, by default allows you to ignore
anythingtheuserdidonthewizard.AnotherwizardmayhaveaHelpbutton.
All this descrption is left up to you to decide what buttons to display on your wizard, what to do
withthebuttons,why,andwhen.Alloptionsarepossibleandusuallyeasytoconfigure.

PracticalLearning:IntroducingWizards
1. Tocreateanewapplication,onthemainmenu,clickFile>NewProject...
2. Intheleftlist,clickVisualC++.Intherightlist,clickMFCApplication
3. ChangetheNametoAutoRepair1
4. ClickOK
5. Inthefirstpageofthewizard,clickNext
6. Inthesecondpageofthewizard,clickDialogBased

7. ClickNext
8. Inthethirdpage,clickAboutBoxtoremoveitscheckmarkandclickNext
9. Inthefourthpageofthewizard,clickNext
10. InthefifthpageofthewizardandintheGeneralClasseslist,clickCAutoRepairDlg
11. IntheClassName,changethenameoftheclasstoCCustomerInformationDlg
12. Changethe.hFiletoCustomerInformationDlg.h
13. Changethe.cppFiletoCustomerInformationDlg.cpp

14. ClickFinish
15. Onthedialogbox,clicktheTODOlineandpressDelete
16. WhiletheOKbuttonisselected,pressDelete
17. AlsodeletetheCancelbutton
18. IntheToolbox,clickButtonandclickthebodyofthedialogbox

CreatingaWizard
As seen with the property sheet, there are a few steps you must follow to create a wizard. The
stepsareprimarilythesameasthoseofapropertysheet.Startbycreatingadialogboxforeach
wizardpage. When designing a page, set the size you want. If your wizard will have more than
one page (it is possible but not practical to have a wizard with only one page), the width of the
largestdialogboxwillbeappliedtotheotherpage(s).Theheightofthetallestdialogboxwillbe
usedforallpages.
After designing a page, create a class for it. For the base class, select CPropertyPage. After
creatingthepagesandtheirclasses,deriveaclassfromCPropertySheet.Inaconstructorofthe
CPropertySheetbasedclass,addeachpage.

PracticalLearning:CreatingWizardPages
1. Inthemainwindow,clickthebodyofthedialogbox
2. InthePropertieswindow,changetheIDtoIDD_CUSTOMERINFO_DLG
3. IntheSolutionExplorer,expandtheprojectandtheHeaderFilesnode.Doubleclick
CustomerInformationDlg.h
4. Changethedocumentasfollows:
//CustomerInformationDlg.h:headerfile
//
#pragmaonce
//CCustomerInformationDlgdialog
classCCustomerInformationDlg:publicCPropertyPage
{
//Construction
public:

CCustomerInformationDlg(CWnd*pParent=NULL)//standardconstructor
//DialogData

enum{IDD=IDD_CUSTOMERINFO_DLG}

protected:
virtualvoidDoDataExchange(CDataExchange*pDX)//DDX/DDVsupport

//Implementation
protected:

HICONm_hIcon

//Generatedmessagemapfunctions
virtualBOOLOnInitDialog()
afx_msgvoidOnPaint()
afx_msgHCURSOROnQueryDragIcon()
DECLARE_MESSAGE_MAP()

5. AccesstheCustomerInformationDlg.cppfileandchangeitasfollows:
//CustomerInformationDlg.cpp:implementationfile
//
#include"stdafx.h"

#include"AutoRepair1.h"
#include"CustomerInformationDlg.h"
#include"afxdialogex.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#endif
//CCustomerInformationDlgdialog
CCustomerInformationDlg::CCustomerInformationDlg(CWnd*pParent/*=NULL*/)

:CPropertyPage(CCustomerInformationDlg::IDD)
{

m_hIcon=AfxGetApp()>LoadIcon(IDR_MAINFRAME)
}
voidCCustomerInformationDlg::DoDataExchange(CDataExchange*pDX)
{

CPropertyPage::DoDataExchange(pDX)
}
BEGIN_MESSAGE_MAP(CCustomerInformationDlg,CPropertyPage)

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()
//CCustomerInformationDlgmessagehandlers
BOOLCCustomerInformationDlg::OnInitDialog()
{

CPropertyPage::OnInitDialog()

//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon

//TODO:Addextrainitializationhere

returnTRUE//returnTRUEunlessyousetthefocustoacontrol

//Ifyouaddaminimizebuttontoyourdialog,youwillneedthecodebelow
//todrawtheicon.ForMFCapplicationsusingthedocument/viewmodel,
//thisisautomaticallydoneforyoubytheframework.
voidCCustomerInformationDlg::OnPaint()
{
if(IsIconic())
{

CPaintDCdc(this)//devicecontextforpainting

SendMessage(WM_ICONERASEBKGND,

reinterpret_cast<WPARAM>(dc.GetSafeHdc()),0)

//Centericoninclientrectangle
intcxIcon=GetSystemMetrics(SM_CXICON)
intcyIcon=GetSystemMetrics(SM_CYICON)
CRectrect
GetClientRect(&rect)
intx=(rect.Width()cxIcon+1)/2
inty=(rect.Height()cyIcon+1)/2

}
else
{

//Drawtheicon
dc.DrawIcon(x,y,m_hIcon)

CPropertyPage::OnPaint()

HCURSORCCustomerInformationDlg::OnQueryDragIcon()
{

returnstatic_cast<HCURSOR>(m_hIcon)
}
6. Displaythedialogboxoftheproject
7. ClicktheOKbuttonandpressDelete
8. ClicktheCancelbuttonandpressDelete
9. InthePropertieswindow,changethefollowingcharacteristicsofthedialogbox:
Border:Thin
Caption:CustomerInformation
Disabled:True
Style:Child
10. IftheResourceViewisnotvisible,onthemainmenu,clickView>OtherWindows>
ResourceView.
IntheResourceView,expandthenameoftheproject.ExpandAutoRepair1.rc.ExpandDialog.
RightclickDialogandclickInsertDialog
11. Onthenewdialogbox,clickOKandpressDelete
12. AstheCancelbuttonisselected,pressDelete
13. InthePropertieswindow,changethefollowingcharacteristicsofthedialogbox:
Border:Thin

Caption:JobPerformed/PartsUsed
Disabled:True
ID:IDD_JOBSANDPARTS_DLG
Style:Child
14. IntheToolbox,clickComboBoxandclickthebodyofthedialogbox
15. Tocreateaclassforthedialogbox,rightclickthebodyofthedialogboxandclickAdd
Class...
16. SettheClassNametoCJobsAndPartsDlg
17. SettheBaseClasstoCPropertyPage

PHP code
generator
Generate
PHP code for
any local or
remote
database.

18. ClickFinish
19. Tocreateanewpropertypage,intheResourceView,rightclickDialogandclickAdd
Resource...
20. IntheAddResourcedialogbox,expandDialogandclickIDD_PROPPAGE_LARGE
21. ClickNew
22. InthePropertieswindow,changethefollowingcharacteristics:
Caption:RepairSummary
ID:IDD_REPAIRSUMMARY_DLG
23. IntheToolbox,clickMonthCalendarControlandclickthebodyofthedialogbox
24. RightclickthebodyofthedialogboxandclickAddClass...
25. SettheClassNametoCRepairSummaryDlg
26. SettheBaseClasstoCPropertyPage
27. ClickFinish
28. Tocreateanewclass,onthemainmenu,clickProject>AddClass...
29. ClickMFCClassandclickAdd
30. SettheClassNametoCRepairOrderSheet
31. SettheBaseClasstoCPropertySheet

32. ClickFinish
33. ChangetheRepairOrderSheet.hdocumentasfollows:
#pragmaonce
#include"CustomerInformationDlg.h"
#include"JobsAndPartsDlg.h"
#include"RepairSummaryDlg.h"
//CRepairOrderSheet
classCRepairOrderSheet:publicCPropertySheet
{

DECLARE_DYNAMIC(CRepairOrderSheet)
public:

CRepairOrderSheet(UINTnIDCaption,

CWnd*pParentWnd=NULL,

UINTiSelectPage=0)
CRepairOrderSheet(LPCTSTRpszCaption,

CWnd*pParentWnd=NULL,

UINTiSelectPage=0)
virtual~CRepairOrderSheet()

private:

CCustomerInformationDlgdlgCustomerInformation

CJobsAndPartsDlgdlgJobsAndParts

CRepairSummaryDlgdlgRepairSummary
protected:

DECLARE_MESSAGE_MAP()
}
34. AccesstheRepairOrderSheet.dppfileandchangetheconstructorthattakesastringasitsfirst
argumentasfollows:
CRepairOrderSheet::CRepairOrderSheet(LPCTSTRpszCaption,

CWnd*pParentWnd,UINTiSelectPage)

:CPropertySheet(pszCaption,pParentWnd,iSelectPage)
{

this>AddPage(&dlgCustomerInformation)

this>AddPage(&dlgJobsAndParts)

this>AddPage(&dlgRepairSummary)
}

SettingtheWizardMode
Thebigdifferencebetweenapropertysheetandawizardisthat,beforeshowingthedialogbox,youmust
calltheSetWizardMode()memberfunctionoftheCPropertySheetclass.Itssyntaxis:
voidSetWizardMode()
Asyoucansee,thismemberfunctiontakesnoargument.Itsimplyinformsthecompilerthat,insteadofa
propertysheet,youwanttocreateawizard.Therealquestionis,wheredoyoucallthismemberfunction?
That's because you have various options. The secret is to call before displaying the pages that is, before
calling CDialog::DoModal(). You can call CPropertySheet::SetWizardMode() in the same constructore
whereyouaddthepages,oryoucancallitjustbeforecallingCDialog::DoModal().

PracticalLearning:CallingaWizard
1. IntheSolutionExplorer,doubleclickAutoRepair1.cppandchangeitasfollows:
//AutoRepair1.cpp:Definestheclassbehaviorsfortheapplication.
//
#include"stdafx.h"
#include"AutoRepair1.h"
#include"CustomerInformationDlg.h"
#include"RepairOrderSheet.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#endif
//CAutoRepair1App
BEGIN_MESSAGE_MAP(CAutoRepair1App,CWinApp)

ON_COMMAND(ID_HELP,&CWinApp::OnHelp)
END_MESSAGE_MAP()
//CAutoRepair1Appconstruction
CAutoRepair1App::CAutoRepair1App()
{

//supportRestartManager

m_dwRestartManagerSupportFlags=AFX_RESTART_MANAGER_SUPPORT_RESTART

//TODO:addconstructioncodehere,
//PlaceallsignificantinitializationinInitInstance

//TheoneandonlyCAutoRepair1Appobject
CAutoRepair1ApptheApp
//CAutoRepair1Appinitialization
BOOLCAutoRepair1App::InitInstance()
{

//InitCommonControlsEx()isrequiredonWindowsXPifanapplication

//manifestspecifiesuseofComCtl32.dllversion6orlatertoenable

//visualstyles.Otherwise,anywindowcreationwillfail.

INITCOMMONCONTROLSEXInitCtrls

InitCtrls.dwSize=sizeof(InitCtrls)

//Setthistoincludeallthecommoncontrolclassesyouwanttouse

//inyourapplication.

InitCtrls.dwICC=ICC_WIN95_CLASSES

InitCommonControlsEx(&InitCtrls)

CWinApp::InitInstance()

AfxEnableControlContainer()

//Createtheshellmanager,incasethedialogcontains
//anyshelltreevieworshelllistviewcontrols.
CShellManager*pShellManager=newCShellManager

//Standardinitialization
//Ifyouarenotusingthesefeaturesandwishtoreducethesize
//ofyourfinalexecutable,youshouldremovefromthefollowing
//thespecificinitializationroutinesyoudonotneed
//Changetheregistrykeyunderwhichoursettingsarestored
//TODO:Youshouldmodifythisstringtobesomethingappropriate
//suchasthenameofyourcompanyororganization
SetRegistryKey(_T("LocalAppWizardGeneratedApplications"))

//CCustomerInformationDlgdlg

CRepairOrderSheetdlg(L"CollegeParkAutoRepair")
m_pMainWnd=&dlg
dlg.SetWizardMode()

INT_PTRnResponse=dlg.DoModal()
if(nResponse==IDOK)
{

//TODO:Placecodeheretohandlewhenthedialogis

//dismissedwithOK
}
elseif(nResponse==IDCANCEL)
{

//TODO:Placecodeheretohandlewhenthedialogis

//dismissedwithCancel
}

//Deletetheshellmanagercreatedabove.
if(pShellManager!=NULL)
{

deletepShellManager
}

//Sincethedialoghasbeenclosed,returnFALSEsothatweexitthe
//application,ratherthanstarttheapplication'smessagepump.
returnFALSE

2. Toexecutetheproject,pressF5

3. NoticethattheBackbuttonisenabled.
ClickNext

4. ClickNextagain

5. NoticethatthereisnoFinishbuttonalthoughyouareonthelastpage.
Closethedialogboxandreturntoyourprogrammingenvironment

ConfiguringtheDefaultButtonsofaWizard

Bydefault,aftercreatingaregularwizard,itisequippedwiththreebuttons:Back,Next,andCancel.Ifyou
selecttheoptiontoaddhelpintheMFCApplication,thewizardwouldalsobeequippedwithaHelpbutton.
Youcanmanagethebuttonsandyouhavemanyoptions.
Aswithanythingelseintheworldorprogramming,youshouldmakeyourwizardintuitiveandfriendly.For
example, on the first page, since there is no reason for the user to access the previous page, you can
disable the Back button. On the other hand, when the user gets to the last page, since there is no
succeeding page, there is no need for a Next button. Consequently, you should replace it with a Finish
button.Fortunately,thedisplayofthesebuttonsisprobablytheeasiestthingtomanageonawizard.
In order to decide what button(s) should be available when a particular page is accessed, generate its
CPropertyPage::OnSetActive()event.Itssyntaxis:
virtualBOOLOnSetActive()
This event fires when a page of your choice is accessed, allowing you to do what you want on the wizard
page.Oneoftheactionsyoucantakewhenapagedisplaysistodecidewhatbutton(s)shouldbedisplayed
on the wizard. The buttons of a wizard are managed through the CPropertySheet::SetWizardButtons()
memberfunction.Itssyntaxis:
voidSetWizardButtons(DWORDdwFlags)
The dwFlags argument is a constant or a combination of values that defines the buttons to display. The
possiblevaluesare:
PSWIZB_BACKfortheBackbutton
PSWIZB_NEXTfortheNextbutton
PSWIZB_FINISHfortheFinishbutton
PSWIZB_DISABLEDFINISHtodisabletheFinishbutton
On the first page, to display the Next button while disabling the Back button, you can pass only the
PSWIZB_NEXT value. On the last page, you should display the Back and the Finish buttons. All pages
betweenthefirstandthelastshoulddisplaytheBackandtheNextbuttons,unlessyouhaveareasontodo
otherwise.

AddingtheDefaultButtonsofaWizard
Toaddyourownbuttontothewizard,youcanusethefeaturesoftheCWndclass.Hereisanexample:
CmyWizardSheet::OnInitDialog()
{
BOOLbResult=CPropertySheet::OnInitDialog()
CButton*btnWhatever=newCButton
btnWhatever>Create(L"Whatever",WS_CHILD|WS_VISIBLE,

CRect(10,362,126,385),this,0x122)
ReturnbResult
}
When the user clicks the Back button, the CPropertyPage::OnWizardBack() event fires, giving you the
opportunitytodowhatyoujudgenecessary.Itssyntaxis:
virtualLRESULTOnWizardBack()
YoushouldusethiseventonapagethathastheBackbutton and if this button is enabled. When the user
clickstheNextbutton,theCPropertyPage::OnWizardNext()eventfires,allowingyoutotakeappropriate
measures.Itssyntaxis:
virtualLRESULTOnWizardNext()
You should use this event on a page that has the Next button. When the user clicks the Finish button, the
CPropertyPage::OnWizardFinish()eventfires.Itssyntaxis:
virtualBOOLOnWizardFinish()
ThiseventshouldbeimplementwheneithertheuserisonthelastpagethathastheFinishbuttonoratany
timeifthewizardhasapermanentFinishbuttonavailableonallpages.

PracticalLearning:ImplementingWizardButtons
1. Onthemainmenu,clickProject>ClassWizard...
2. IntheClassNamecombobox,makesurethatCCustomerInformationDlgisselected(orselectit).
ClicktheVirtualFuntionstab
3. IntheVirtualFunctionslist,doubleclickOnSetActive

4. ClickEditCode
5. Changethefileasfollows:
//CustomerInformationDlg.cpp:implementationfile
//
#include"stdafx.h"
#include"AutoRepair1.h"
#include"CustomerInformationDlg.h"
#include"afxdialogex.h"
#include"RepairOrderSheet.h"
...NoChange
BOOLCCustomerInformationDlg::OnSetActive()
{
//TODO:Addyourspecializedcodehereand/orcallthebaseclass
CRepairOrderSheet*ros=reinterpret_cast<CRepairOrderSheet*>(GetParent())
ros>SetWizardButtons(PSWIZB_NEXT)
returnCPropertyPage::OnSetActive()
}
6. PressF5toexecute

7. NoticethattheBackbuttonisnowdisabled.
Closethedialogboxandreturntoyourprogrammingenvironment
8. Onthemainmenu,clickProject>ClassWizard...
9. IntheClassNamecombobox,selectCRepairSummaryDlg
10. ClicktheVirtualFuntionstab
11. IntheVirtualFunctionslist,doubleclickOnSetActive
12. IntheClassNamecombobox,selectCJobsAndPartsDlg
13. IntheVirtualFunctionslist,doubleclickOnSetActive
14. ClickEditCode

15. Changethefileasfollows:
//JobsAndPartsDlg.cpp:implementationfile
//
#include"stdafx.h"
#include"AutoRepair1.h"
#include"JobsAndPartsDlg.h"
#include"afxdialogex.h"
#include"RepairOrderSheet.h"
...NoChange
BOOLCJobsAndPartsDlg::OnSetActive()
{
//TODO:Addyourspecializedcodehereand/orcallthebaseclass
CRepairOrderSheet*ros=reinterpret_cast<CRepairOrderSheet*>(GetParent())
ros>SetWizardButtons(PSWIZB_BACK|PSWIZB_NEXT)
returnCPropertyPage::OnSetActive()
}
16. AccesstheRepairSummaryDlg.cppfile
17. Changethefileasfollows:
//RepairSummaryDlg.cpp:implementationfile
//
#include"stdafx.h"
#include"AutoRepair1.h"
#include"RepairSummaryDlg.h"
#include"afxdialogex.h"
#include"RepairOrderSheet.h"
...NoChange
BOOLCRepairSummaryDlg::OnSetActive()
{
//TODO:Addyourspecializedcodehereand/orcallthebaseclass
CRepairOrderSheet*ros=reinterpret_cast<CRepairOrderSheet*>(GetParent())
ros>SetWizardButtons(PSWIZB_BACK|PSWIZB_FINISH)
returnCPropertyPage::OnSetActive()
}
18. Totesttheapplication,pressF9

19. Closethedialogboxandreturntoyourprogrammingenvironment
20. AccesstheRepairSummaryDlg.cppfileanddelete|PSWIZB_FINISHfromthecodeyouwrote:
OOLCRepairSummaryDlg::OnSetActive()
{

//TODO:Addyourspecializedcodehereand/orcallthebaseclass

CRepairOrderSheet*ros=reinterpret_cast<CRepairOrderSheet*>(GetParent())

ros>SetWizardButtons(PSWIZB_BACK)

returnCPropertyPage::OnSetActive()

21. Onthemainmenu,clickProject>ClassWizard...
22. IntheClassNamecombobox,selectCRepairOderSheetandclicktheVirtualFunctionstab
23. IntheVirtualFunctionslist,doubleclickOnInitDialog
24. ClickEditCode
25. Changethefileasfollows:
BOOLCRepairOrderSheet::OnInitDialog()
{

BOOLbResult=CPropertySheet::OnInitDialog()

//TODO:Addyourspecializedcodehere
CButton*btnFinish

btnFinish=reinterpret_cast<CButton*>(GetDlgItem(IDCANCEL))

btnFinish>SetWindowText(L"Finish")

CButton*btnClose

btnClose=reinterpret_cast<CButton*>(GetDlgItem(IDHELP))
btnClose>SetWindowText(L"Close")

returnbResult

26. Onthemainmenu,clickProject>ClassWizard...
27. IntheClassNamecombobox,makesureCRepairOrderSheetisselectedandclicktheCommandstab.
IntheObjectIDslist,doubleclickIDCANCEL
28. ChangetheMemberFunctionNametoOnFinishRepairOrder
29. ClickOK
30. IntheObjectIDslist,doubleclickIDHELP
31. ChangetheMemberFunctionNametoOnCloseRepairOrder
32. ClickOK
33. ClickEditCode
34. Implementtheeventsasfollows:
voidCRepairOrderSheet::OnFinishRepairOrder()
{
//TODO:Addyourcommandhandlercodehere
AfxMessageBox(L"TheFinishbuttonofthewizardwasclicked.")
}
voidCRepairOrderSheet::OnCloseRepairOrder()
{
//TODO:Addyourcommandhandlercodehere
AfxMessageBox(L"Therepairorderwillbeclosed!")

PostQuitMessage(0)
}
35. Toexecute,pressF9

36. Closethedialogboxandreturntoyourprogrammingenvironment

Home

Copyright2010FunctionX,Inc.

MFCDocument/ViewArchitecture:
FormViews

IntroductiontoForms
A form is an object used to host, hold, or carry
other controls. By itself, a form means nothing.
Thecontrolspositionedonitgiveitusefulness.
In the Microsoft Foundation Classes library, a
formisatypeofdialogboxwithoutborders.The
restofthefunctionalityismostlythesameasa
dialog box. While a dialog box is usually closed
using either the system Close button or a user
created button positioned on it, such as OK or
Cancel, because a form is part of a bigger
application, it should use another means to be
closed.Infact,theapplicationtowhichtheform
belongs should define when and how the form
wouldbeclosed.

AFormFromAppWizard
Therearethreemaintechniquesusedtocreateaform.IfyouuseAppWizardtocreateanSDI
oranMDIapplication,youcanspecifythattheclasswouldbebasedontheCFormViewclass.
When you do this, the wizard would add a form to your application and make it the (main)
view.

PracticalLearning:CreatingaFormBasedApplicationFrom
AppWizard
1. StartMicrosoftVisualStudioorVisualC++anddisplaytheNewdialogboxtostartanewapplication
2. Fromthe(VisualC++)Projects(tab),selectMFCAppWizard(exe)orMFCApplication
3. Inthe(Project)Name,typeFourCornerCarryOut

4. ClickOK
5. SettheApplicationTypeasSingleDocument
6. Changethefilesasfollows:

ClassName

NewClass
Name

CFourCornerCarryOutView CExoView

HeaderFile

Implementation
File

BaseClass

ExoView.h

ExoView.cpp

CFormView

CFourCornerCarryOutApp CExoApp

NoChange NoChange

NoChange

CFourCornerCarryOutDoc CExoDoc

ExoDoc.h

NoChange

ExoDoc.cpp

7. ClickFinishandclickOK
8. Noticethatyouarepresentedwithaborderlessform
ClicktheTODOlineandpressDeletetoremovetheonlyexistingline
Optionallydesigntheformasfollows:

9. PressCtrl+F5totesttheform

ADatabaseForm
Another technique used to have a form is by creating a database application. This process
automatically creates a form without necessarily getting it ready for database objects. To use
thistechnique,startanapplicationfromAppWizardandspecifythatyouneeddatabasesupport.
Thewizardwouldconsequentlycreateaform.

ANewForm
The third alternative to getting a form is by creating one that you didn't get from AppWizard.
Once again this depends on the current state of your application. If you started an application
already,youmaysimplywanttoaddaform.Youcanalsodecidetochangethetypeofviewthat
your application is using. You can also work from scratch, with no view at all, and then decide
that your application would be based on a form as the main view. Either way, it is not
particularlydifficulttoaddorchangetheview.
As mentioned already, an MFC form is just a type of dialog box that doesn't have borders.
Therefore,toaddaformtoanapplication,displaytheAddResourcedialogboxandexpandthe
Dialognode.ThenclickIDD_FORMVIEWandclickOK.Afteraddingtheform,youmustassociate
a class with it. You can either use an existing class or create your own. The class should be
derivedfromCFormView.
If you add a form to an application, when the user starts the application, a message box ask
whattypeofdocumentshouldbedisplayed.TheusercanthenselectfromthelistandclickOK.

PracticalLearning:AddingaFormtoanApplication
1. DisplaytheNewdialogboxtostartanewapplication
2. CreateitusingMFCAppWizard(exe)orMFCApplication
3. SetthenameoftheprojecttoAssociates
4. CreateitasaSingleDocument
5. BasetheclassonCListView
6. ClickFinish.IfusingMSVC6,clickOKtwice
7. Toaddaformtotheapplication,onthemainmenu,clickInsert>NewForm...
8. SettheNameoftheclasstoCProductsandmakesureitisbasedonCFormView

PHP code
generator
Generate
PHP code for
any local or
remote
database.

9. ClickOK
10. Testtheapplicationandthencloseit
11. Todisplayafriendlierlist,accesstheStringTable
12. DoubleclickIDR_PRODUCTS_TMPLandchangeitsCaptionasfollows:

Products\n\nBusinessProducts\nProducFiles
(*.pro)\n.pro\nProducts.Document\nProducDocument
13. DoubleclickIDR_MAINFRAMEandchangeitsCaptionasfollows:

Associates\n\nCustomersContract\n\n\nAssociates.Document\nAssoci
Document
14. Testtheapplicationandselectoneofthedocuments

15. CloseitandreturntoMSVC

AMultiFormApplication
Sofar,wehavediscussedhowyoucaneithercreateaformbasedapplicationorhowyoucan
add a form to an application. In the above projects, we were dealing with only one form. In
somecases,youmayneedtocreateanapplicationthatusesvariousforms.Onceagain,you
havevariouschoices:
ThefirstsolutionthatcomesinmindofcoursewouldconsistofcreatinganMDI.One
situationyoumayencounter,whichisfineifthat'swhatyouwant,isthateachchild

windowwouldbebasedonthesamedesignbecauseeachwouldusethesameform
Anothersolutionistocreatedifferentdialogboxesanduseeachasaform.Inthiscase,
youwouldnotbereallyimplementingforms
Anothersolutionistocreatevarious"miniapplications"anddisplayeachwhenneeded.
Althoughthislastsolutionispossible,itcouldbeanightmare.
Anothersolutionistocreatevariousformsanddisplayeachasneeded.Thiscanbea
valuablealternativeasdifferentformscandisplayinthesameframe
You can use various forms in the same application and display each upon request. This
solution can bring tremendous results on a database because that type of application usually
dealwithdifferentgroupsorsetsofrecordsthatdon'tbelongtothesameobject.
To use various forms in an application, create each form and associate it with its own class.
Toprepareaconvenientwaytodisplay them, you can add items to a menu and let the user
decidewhentodisplayaparticularform.

PracticalLearning:CreatingaMultiFormBasedApplication
1. DisplaytheNew(Project)dialogboxtostartanewapplication
2. CreateitusingMFCAppWizard(exe)orMFCApplication
3. SetthenameoftheapplicationtoEmplSolutions
4. CreateitasaSingleDocumentandacceptthedefaultviewclassasCView
5. ClickFinish(andOK)
6. Tocreateaform,displaytheInsertResources(Insert>Resource...)ortheAddResources(Project>Add
Resource...)dialogbox
7. ExpandtheDialognodeandclickIDD_FORMVIEW

8. ClickNew
9. Ontheform,deletetheTODOlineandplacesomerandomcontrolsonit
10. ChangetheIDoftheformtoIDD_VIEW_EMPLAPP
11. Doubleclickanemptyareaontheform.WhentheAddingADialogBoxdialogcomesup,clickCreateANewClass
andclickOK
12. SettheNameoftheclasstoCEmplAppViewandsetitsBaseClasstoCFormView

13. ClickOKtwice
14. DisplaytheInsertResourcedialogboxagain
15. ExpandtheDialognodeanddoubleclickIDD_FORMVIEW
16. DeletetheTODOlineandplacesomerandomcontrolsonit
17. ChangetheIDoftheformtoIDD_VIEW_TIMESHEET
18. CreateANewClassforthenewform
19. NametheclassCTimeSheetViewandbaseitonCFormView
20. DisplaytheInsertResourcedialogboxagain
21. ExpandtheDialognodeanddoubleclickIDD_FORMVIEW
22. DeletetheTODOlineandplacesomerandomcontrolsonit
23. ChangetheIDoftheformtoIDD_VIEW_RFTIMEOFF
24. CreateANewClassforthenewform
25. NametheclassCTimeOffViewandbaseitonCFormView
26. DisplaytheEmplSolutions.cppsourcefileandchangethedefaultdocumentasfollows:

//EmplSolutions.cpp:Definestheclassbehaviorsfortheapplication.
//
#include"stdafx.h"
#include"EmplSolutions.h"
#include"MainFrm.h"
#include"EmplSolutionsDoc.h"
#include"EmplSolutionsView.h"
#include"EmplAppView.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__
#endif
/////////////////////////////////////////////////////////////////////////////
//CEmplSolutionsApp
BEGIN_MESSAGE_MAP(CEmplSolutionsApp,CWinApp)

//{{AFX_MSG_MAP(CEmplSolutionsApp)

ON_COMMAND(ID_APP_ABOUT,OnAppAbout)

//}}AFX_MSG_MAP

//Standardfilebaseddocumentcommands

ON_COMMAND(ID_FILE_NEW,CWinApp::OnFileNew)

ON_COMMAND(ID_FILE_OPEN,CWinApp::OnFileOpen)

//Standardprintsetupcommand

ON_COMMAND(ID_FILE_PRINT_SETUP,CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
//CEmplSolutionsAppconstruction
CEmplSolutionsApp::CEmplSolutionsApp()
{
}
/////////////////////////////////////////////////////////////////////////////
//TheoneandonlyCEmplSolutionsAppobject
CEmplSolutionsApptheApp
/////////////////////////////////////////////////////////////////////////////
//CEmplSolutionsAppinitialization
BOOLCEmplSolutionsApp::InitInstance()
{

AfxEnableControlContainer()

//Standardinitialization

#ifdef_AFXDLL

Enable3dControls()

#else

Enable3dControlsStatic()
#endif

//CallthiswhenusingMFCinasharedDLL

//CallthiswhenlinkingtoMFCstatically

//Changetheregistrykeyunderwhichoursettingsarestored.
SetRegistryKey(_T("LocalAppWizardGeneratedApplications"))

LoadStdProfileSettings()//LoadstandardINIfileoptions(includingMRU)

//Registerdocumenttemplates

CSingleDocTemplate*pDocTemplate
pDocTemplate=newCSingleDocTemplate(

IDR_MAINFRAME,

RUNTIME_CLASS(CEmplSolutionsDoc),

RUNTIME_CLASS(CMainFrame),//mainSDIframewindow

RUNTIME_CLASS(CEmplAppView))
AddDocTemplate(pDocTemplate)

//Parsecommandlineforstandardshellcommands,DDE,fileopen
CCommandLineInfocmdInfo
ParseCommandLine(cmdInfo)

//Dispatchcommandsspecifiedonthecommandline
if(!ProcessShellCommand(cmdInfo))

returnFALSE
m_pMainWnd>ShowWindow(SW_SHOW)
m_pMainWnd>UpdateWindow()

returnTRUE

...
27. TesttheapplicationandcloseittoreturntoMSVC
28. DisplaytheIDR_MAINFRAMEmenuandchangeitasfollows:

ID

Caption

Prompt

ID_VIEW_EMPLAPP

&Employment
application

Displaytheemployment
application\nEmploymentApplication

ID_VIEW_TIMESHEET

Ti&meSheet

DisplayTimeSheetForm\nTimeSheet

ID_VIEW_REQTIMEOFF &RequestForTimeOff

DisplayRequestForTimeOffform\nRequest
ForTimeOff

29. AccesstheheaderfileoftheframeanddeclareanunsignedintegeroftypeUINTandnamedm_CurrentView

classCMainFrame:publicCFrameWnd
{

protected://createfromserializationonly

CMainFrame()

DECLARE_DYNCREATE(CMainFrame)

//Attributes
public:

UINTm_CurrentView
//Operations
public:
...
30. Intheconstructoroftheframe,initializetheabovevariabletotheIDentifierofthefirstview:

CMainFrame::CMainFrame()
{

m_CurrentView=ID_VIEW_EMPLAPP
}
31. InClassView,rightclicktheCMainFramenodeandclickAddMemberFunction...
32. SetthepublicfunctiontypeasvoidanditsnameasSelectViewwithanargumentoftypeUINTnamedViewID

33. Implementthememberfunctionasfollows:

//MainFrm.cpp:implementationoftheCMainFrameclass
//
#include"stdafx.h"
#include"EmplSolutions.h"
#include"MainFrm.h"
#include"EmplAppView.h"
#include"TimeSheetView.h"
#include"TimeOffView.h"
...
voidCMainFrame::SelectView(UINTViewID)
{

//Iftheviewtheuserselectedisalreadydisplaying,donothing

if(ViewID==m_CurrentView)

return

//Getapointertothecurrentview
CView*pCurrentView=GetActiveView()

//Weareabouttochangetheview,soweneedapointertotheruntimeclass
CRuntimeClass*pNewView

//Wewillprocessaform
//First,let'schangetheidentifierofthecurrentviewtoourinteger
::SetWindowLong(pCurrentView>m_hWnd,GWL_ID,m_CurrentView)

//Nowwewillidentifywhatformtheuserselected
switch(ViewID)
{
caseID_VIEW_EMPLAPP:

pNewView=RUNTIME_CLASS(CEmplAppView)

break
caseID_VIEW_TIMESHEET:

pNewView=RUNTIME_CLASS(CTimeSheetView)

break

caseID_VIEW_REQTIMEOFF:

pNewView=RUNTIME_CLASS(CTimeOffView)

break
}

//Wewilldealwiththeframe
CCreateContextcrtContext

//Wehaveanewviewnow.Soweinitializethecontext
crtContext.m_pNewViewClass=pNewView
//Noneedtochangethedocument.Wekeepthecurrentdocument
crtContext.m_pCurrentDoc=GetActiveDocument()

CView*pNewViewer=STATIC_DOWNCAST(CView,CreateView(&crtContext))

//Nowwecancreateanewviewandgetridofthepreviousone
if(pNewViewer!=NULL)
{

pNewViewer>ShowWindow(SW_SHOW)

pNewViewer>OnInitialUpdate()

SetActiveView(pNewViewer)

RecalcLayout()

m_CurrentView=ViewID

pCurrentView>DestroyWindow()
}

34. InClassView,rightclicktheCMainFramenodeandclickAddMemberFunction...
35. SetthefunctiontypeasvoidanditsnameasOnUpdateSelectViewUIwithapointerargumentoftypeCCmdUI*
namedpCmdUI

36. ClickOK
37. Implementthememberfunctionasfollows:

voidCMainFrame::OnUpdateSelectViewUI(CCmdUI*pCmdUI)
{

pCmdUI>SetCheck(pCmdUI>m_nID==m_CurrentView)
}
38. Inthesamesourcefile,tousetheabovetwomemberfunctionsforthemenuitemsusedtochangetheview,create
theircommandrangesasfollows:

/////////////////////////////////////////////////////////////////////////////
//CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame,CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)

//{{AFX_MSG_MAP(CMainFrame)

ON_WM_CREATE()

//}}AFX_MSG_MAP

ON_COMMAND_RANGE(ID_VIEW_EMPLAPP,ID_VIEW_REQTIMEOFF,SelectView)

ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_EMPLAPP,ID_VIEW_REQTIMEOFF,OnUpdateSelectViewUI)
END_MESSAGE_MAP()
39. Testtheapplicationandchangedifferentviews

Copyright20042007FunctionX,Inc.

PrintingWiththeDocument/View
Architecture

ADocumentanditsPages
When it comes to printing, the object from your
application is called a document. Inside of a
document, it is made of one or more pages. A
pageiscreatedaspartofadocument:

Print Server Software


Windows Print Server Software.
Installs in Seconds, No Hardware.

A document is not a physical object. It is an electronic representation of the result of an


application. Because it is not physical, it doesnt have dimensions: it has neither a width nor a
length. On the other hand, a page that is part of a document has dimensions. When printing,
therearestandarddimensionsthattheprinterwillfollow.
A document has and must have at least one page. A document can also have more than one
page:

Inthesameway,adocumentcanhaveasmanypagesasnecessary:

PracticalLearning:IntroducingtheDocumentandPages
1. Tostartanewapplication,onthemainmenuofMicrosoftVisualC++,clickFile>New>
Project

2. IntheTemplatessectionoftheNewProjectdialogbox,clickMFCApplication
3. IntheNamebox,typeDepartmentStore2andclickOK
4. ClickApplicationTypeand,intherightframe,clickSingleDocument
5. Intheleftframe,clickDocumentTemplateStringsand,intheMainFrameCaption,
changethestringtoDepartmentStore
6. Intheleftframe,clickGeneratedClassesandmakethefollowingchanges:
ClassName

.hFile

.cppFile

BaseClass

CExerciseView ExerciseView.h ExerciseView.cpp CScrollView


CExerciseApp

CWinApp

CExerciseDoc

ExerciseDoc.h

ExerciseDoc.cpp

CDocument

7. ClickFinish
8. Copyeachofthesepictures

Cover1.bmp

Dress1.bmp

Dress2.bmp

Dress3.bmp

Dress4.bmp

Dress5.bmp

Dress6.bmp

9. Pastethemintheresfolderofthecurrentproject
10. Onthemainmenu,clickProject>AddResource
11. IntheAddResourcedialogbox,clickImport...
12. Locatetheressubfolderofthecurrentproject,clickCover1.bmp
13. PressandholdCtrl
14. ClickDress1.bmp,Dress2.bmp,Dress3.bmp,Dress4.bmp,Dress5.bmp,andDress6.bmp
15. ReleaseCtrlandclickOpen
16. IntheResourceView,expandtheBitmapfolder,doubleclickeachitemand,inthe
Propertieswindow,changeitsIDasfollows:

Filename

ID

res/Cover1.bmp IDB_COVER
res/Dress1.bmp IDB_DRESS1
res/Dress2.bmp IDB_DRESS2
res/Dress3.bmp IDB_DRESS3
res/Dress4.bmp IDB_DRESS4

res/Dress5.bmp IDB_DRESS5
res/Dress6.bmp IDB_DRESS6
17. IntheClassView,expandDepartmentStore2,expandCExerciseView,anddoubleclick
OnInitialUpdate
18. Changeitasfollows:

voidCExerciseView::OnInitialUpdate()
{

CScrollView::OnInitialUpdate()

CSizesizeTotal

//TODO:calculatethetotalsizeofthisview

sizeTotal.cx=500

sizeTotal.cy=1360

SetScrollSizes(MM_TEXT,sizeTotal)
}

19. IntheClassView,expandCmainFrameanddoubleclickOnCreate
20. Changetheeventasfollows:

BOOLCMainFrame::PreCreateWindow(CREATESTRUCT&cs)
{

if(!CFrameWnd::PreCreateWindow(cs))

returnFALSE

//TODO:ModifytheWindowclassorstylesherebymodifying

//theCREATESTRUCTcs

cs.cx=450

cs.cy=600

cs.style&=~FWS_ADDTOTITLE

returnTRUE

21. Saveall

IntroductiontoDocument/ViewPrinting
One of the primary ways Microsoft reduces its complexity of printing is through device
independence.Thismeansthatyoushouldworrylesswiththetypeofdeviceusedtoprint:you
dont have to care what type of printer or machine would be used to print a document of your
application. What you have left to do is the drawing side of the document. You have two main
approaches: using the MFC Application or manually implementing the document/view
architectureoftheMFClibrary.
As mentioned in the previous sections, if you use the MFC Application and decide to create a
CViewbased application, the wizard would suggest support for printing. If you accept it, it
would add a Print, a Print Preview, and a Print Setup options. As the wizard is writing the
primary code for your application, it would add code for three events: OnPreparePrinting,
OnBeginPrinting,andOnEndPrinting:
BOOLCExerciseView::OnPreparePrinting(CPrintInfo*pInfo)
{

//defaultpreparation

returnDoPreparePrinting(pInfo)
}
voidCExerciseView::OnBeginPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{

//TODO:addextrainitializationbeforeprinting
}
voidCExerciseView::OnEndPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{

//TODO:addcleanupafterprinting
}

PrintPreparation
As you may know by now, the user typically launches printing by opening the Printdialog box
that is equipped with various options and then clicking OK. To control how these options are
presentedtotheuser,theviewclassfirestheOnPreparePrintingevent.Itssyntaxis:
virtualBOOLOnPreparePrinting(CPrintInfo*pInfo)

If you are manually creating your application, make sure you add this event. As you can see
fromtheabovelines,theprimarycodewrittenbythewizardservesonlyasaplaceholder.
ThiseventtakesasargumentaCPrintInfoobject.Noticethatitispassedasapointer.Thisis
for two good reasons. If you access the argument, it can give you information about the print
job,informationthatmayhavebeenstoredintheCPrintInfoobject.Inthesameway,youcan
use the argument to make changes to the print job. After making such changes, call the
CView::DoPreparePrinting() method and pass it the modified CPrintInfoobject.Thesyntax
ofthismethodis:
BOOLDoPreparePrinting(CPrintInfo*pInfo)
The CView::OnPreparePrinting() event fires when the user initiates printing but before the
actualprintingoccurs.ThisisagoodplacetosetsomeoptionsonthePrintdialogbox.Thereare
two ways you can do this. You can directly use the pInfo object because the CPrintInfo
structure has a member variable named m_pPD that is of type CPrintDialog. Another
technique consists of creating your own CPrintDialog object, define it as you wish, and then
assigningittothem_pPDmemberofthepInfoargument.Hereisanexample:
BOOLCExerciseView::OnPreparePrinting(CPrintInfo*pInfo)
{

CPrintDialog*dlg=newCPrintDialog(FALSE,PD_PAGENUMS)

pInfo>m_pPD=dlg

pInfo>SetMinPage(1)

pInfo>SetMaxPage(14)

//defaultpreparation
returnDoPreparePrinting(pInfo)

PracticalLearning:PreparingtoPrint
1. IntheClassViewandundertheCExerciseViewnode,doubleclickOnPreparePrintingand
changeitasfollows:

BOOLCExerciseView::OnPreparePrinting(CPrintInfo*pInfo)
{

//defaultpreparation

pInfo>SetMaxPage(2)

returnDoPreparePrinting(pInfo)

2. Saveall

DocumentPrintingPreparation
OncethePrintdialogboxdisplays,theusercanreview,acceptormakechangesonit,andthen
clickOKtoprint.Ofcourse,theusercanclickCanceltogiveup.OncetheuserclicksOK,before
the job gets to the device, you must prepare the tools that would be used. To assist you with
makingthepreparationfortheactualprinting,theviewclassfiresanOnBeginPrintingevent:

ThesyntaxoftheOnBeginPrintingeventis:
virtualvoidOnBeginPrinting(CDC*pDC,CPrintInfo*pInfo)
ThepDC argument is the device context of the printer. ThepInfo is used to describe the print
job.Ifyouaremanuallycreatingyourviewbasedapplication,youshouldoverridethisevent.If
youusetheMFCApplication,thewizardcancreatetheskeletoncodeforyou.
BecausetheOnBeginPrintingeventisfiredbeforetheactualprintingstarts,youcanuseitto

initializetheGDItoolsthatwouldbeusedtodrawontheprintedsheet.Tomakesurethatthese
toolsareavailabletootherevents,youshouldhavedeclaredthemglobally.

PracticalLearning:BeginningtoPrint
1. IntheClassView,doubleclicktheCExerciseViewnodeanddeclaretwoprivateCFont
pointersasfollows:

private:

CFont*fntTitle1

CFont*fntTitle2
}
2. IntheClassView,underCExerciseView,doubleclickOnBeginPrintingandchangeitas
follows:

voidCExerciseView::OnBeginPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{

//TODO:addextrainitializationbeforeprinting

this>fntTitle1=newCFont

fntTitle1>CreateFont(60,40,0,0,

FW_BOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,

OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,

DEFAULT_QUALITY,DEFAULT_PITCH|FF_ROMAN,

_T("TimesNewRoman"))

this>fntTitle2=newCFont
fntTitle2>CreateFont(100,50,900,0,

FW_BOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,

OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,

DEFAULT_QUALITY,DEFAULT_PITCH|FF_ROMAN,

_T("TimesNewRoman"))

3. Saveall

DeviceContextPreparation
AfterallocatingGDIresourcesthatwouldbeusedtodraw,youcanpreparetheprintersdevice
context.Toassistyouwiththis,youcanusetheOnPrepareDCeventoftheview.Thesyntaxof
thiseventis:
virtualvoidOnPrepareDC(CDC*pDC,CPrintInfo*pInfo=NULL)
The pDC argument represents the device context of the printer. The pInfo object contains a
descriptionoftheprintjobsuchasthenumberofpages.
Whenpreparingtheprintersdevicecontext,youcanexaminethevaluesofthepInfoargument
here. During printing, the device will check the information in the pInfoobject.Forexample,if
pInfo doesnt specify the number of pages, the printer will consider that the document contains
only one page. In this case, if the document contains more than one, the first page would be
printed, the CPrintInfo::m_pContinuePrinting value would be set to FALSE, and the printing
wouldstop.
Whileaprintingjobisgoingon,thepagethatisbeingprintedataparticulartimeisreferredto
as the current page and it is represented by the CPrintInfo::m_nCurPage value. Using the
OnPrepareDC() event, you can continually check the value of the CPrintInfo::m_nCurPage
value.Whentheprintergetstothelastpage,thevalueofthismemberwouldbesetto1.Once
youfindthisout,youcansettheCPrintInfo::m_pContinuePrintingvaluetoFALSE.

Printing
TheactualprintingoccursintheCView::OnPrint()event.Itssyntaxis:
virtualvoidOnPrint(CDC*pDC,CPrintInfo*pInfo)
The pDC object is the device context of the printer, the CDC on which the contents of the
documentwouldbeprinted.ThepInfoobjectcontainsadescriptionoftheprintjob.
WhiletheOnPreparePrintingeventisfiredwhenadocumentissenttotheprinter,theOnPrint
eventisfiredforeachpagetobeprinted:

YoucanusetheOnPrinteventtoformatapagethewayyouwant.Forexample,youcancreate
atopsectionreferredtoastheheaderand/orabottomsectionreferredtoasthefooter.
Asstatedalready,theprintingofapageisperformedinresponsetotheCView::OnPrintevent.
At a particular time, if you want to find out whether a print job is currently occurring, you can
call the CDC::IsPrinting() method. If a printing job is going on, this method returns TRUE.
Otherwise,itreturnsFALSE.

PracticalLearning:Printing
1. IntheClassView,clickCExerciseViewand,intheOverridessectionoftheProperties
window,clickthearrowoftheOnPrintitemtoselect<Add>OnPrint
2. Implementtheeventasfollows:

voidCExerciseView::OnPrint(CDC*pDC,CPrintInfo*pInfo)
{

//TODO:Addyourspecializedcodehereand/orcallthebaseclass

pDC>SetMapMode(MM_ISOTROPIC)

pDC>SetWindowExt(500,500)

pDC>SetViewportExt(4500,6500)

if(pInfo>m_nCurPage==1)
{

CBitmapbmpCover

CDCmemDCCover

CBitmap*bmpOldCover

bmpCover.LoadBitmap(IDB_COVER)
memDCCover.CreateCompatibleDC(pDC)
bmpOldCover=memDCCover.SelectObject(&bmpCover)

pDC>SetBkMode(TRANSPARENT)

pDC>BitBlt(100,60,400,560,&memDCCover,0,0,SRCCOPY)
pDC>SelectObject(bmpOldCover)

CFont*fntOld=pDC>SelectObject(fntTitle1)

pDC>TextOut(10,10,"Collection",10)

fntOld=pDC>SelectObject(fntTitle2)

pDC>TextOut(5,400,"Spring",6)

pDC>SelectObject(fntOld)
}
elseif(pInfo>m_nCurPage==2)
{

CBitmapbmpDress1,bmpDress2,bmpDress3,

bmpDress4,bmpDress5,bmpDress6

CDCmemDCDress1,memDCDress2,memDCDress3,

memDCDress4,memDCDress5,memDCDress6

CBitmap*pOldDress

bmpDress1.LoadBitmap(IDB_DRESS1)
bmpDress2.LoadBitmap(IDB_DRESS2)
bmpDress3.LoadBitmap(IDB_DRESS3)
bmpDress4.LoadBitmap(IDB_DRESS4)
bmpDress5.LoadBitmap(IDB_DRESS5)
bmpDress6.LoadBitmap(IDB_DRESS6)

memDCDress1.CreateCompatibleDC(pDC)
memDCDress2.CreateCompatibleDC(pDC)
memDCDress3.CreateCompatibleDC(pDC)
memDCDress4.CreateCompatibleDC(pDC)

memDCDress5.CreateCompatibleDC(pDC)
memDCDress6.CreateCompatibleDC(pDC)

pOldDress=memDCDress1.SelectObject(&bmpDress1)
pDC>BitBlt(10,10,94,200,&memDCDress1,0,0,SRCCOPY)

pOldDress=memDCDress2.SelectObject(&bmpDress2)
pDC>BitBlt(360,10,113,200,&memDCDress2,0,0,SRCCOPY)

pOldDress=memDCDress3.SelectObject(&bmpDress3)
pDC>BitBlt(10,220,148,200,&memDCDress3,0,0,SRCCOPY)

pOldDress=memDCDress4.SelectObject(&bmpDress4)
pDC>BitBlt(380,220,78,200,&memDCDress4,0,0,SRCCOPY)

pOldDress=memDCDress5.SelectObject(&bmpDress5)
pDC>BitBlt(10,440,100,200,&memDCDress5,0,0,SRCCOPY)

pOldDress=memDCDress6.SelectObject(&bmpDress6)
pDC>BitBlt(360,440,143,200,&memDCDress6,0,0,SRCCOPY)

pDC>SelectObject(pOldDress)

CScrollView::OnPrint(pDC,pInfo)

3. IntheMethodscombobox,selectOnDrawandchangeitasfollows:

voidCExerciseView::OnDraw(CDC*pDC)
{

CExerciseDoc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

//TODO:adddrawcodefornativedatahere
if(!pDC>IsPrinting())
{

CBitmapbmpCover,

bmpDress1,bmpDress2,bmpDress3,

bmpDress4,bmpDress5,bmpDress6

CDCmemDCCover,

memDCDress1,memDCDress2,memDCDress3,

memDCDress4,memDCDress5,memDCDress6

bmpCover.LoadBitmap(IDB_COVER)
bmpDress1.LoadBitmap(IDB_DRESS1)
bmpDress2.LoadBitmap(IDB_DRESS2)
bmpDress3.LoadBitmap(IDB_DRESS3)
bmpDress4.LoadBitmap(IDB_DRESS4)
bmpDress5.LoadBitmap(IDB_DRESS5)
bmpDress6.LoadBitmap(IDB_DRESS6)

memDCCover.CreateCompatibleDC(pDC)
memDCDress1.CreateCompatibleDC(pDC)
memDCDress2.CreateCompatibleDC(pDC)
memDCDress3.CreateCompatibleDC(pDC)
memDCDress4.CreateCompatibleDC(pDC)
memDCDress5.CreateCompatibleDC(pDC)
memDCDress6.CreateCompatibleDC(pDC)

CBitmap*bmpOld=memDCCover.SelectObject(&bmpCover)

pDC>BitBlt(80,60,400,560,&memDCCover,0,0,SRCCOPY)

bmpOld=memDCDress1.SelectObject(&bmpDress1)
pDC>BitBlt(10,680,94,200,&memDCDress1,0,0,SRCCOPY)

bmpOld=memDCDress2.SelectObject(&bmpDress2)
pDC>BitBlt(360,680,113,200,&memDCDress2,0,0,SRCCOPY)

bmpOld=memDCDress3.SelectObject(&bmpDress3)
pDC>BitBlt(10,900,148,200,&memDCDress3,0,0,SRCCOPY)

bmpOld=memDCDress4.SelectObject(&bmpDress4)

pDC>BitBlt(380,900,78,200,&memDCDress4,0,0,SRCCOPY)

bmpOld=memDCDress5.SelectObject(&bmpDress5)
pDC>BitBlt(10,1150,100,200,&memDCDress5,0,0,SRCCOPY)

bmpOld=memDCDress6.SelectObject(&bmpDress6)
pDC>BitBlt(340,1150,143,200,&memDCDress6,0,0,SRCCOPY)

CFontfntVertical
CFontfntHorizontal
CFont*pFont

pDC>SetBkMode(TRANSPARENT)
fntHorizontal.CreateFont(60,40,0,0,

FW_BOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,

OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,

DEFAULT_QUALITY,DEFAULT_PITCH|FF_ROMAN,

_T("TimesNewRoman"))
pFont=pDC>SelectObject(&fntHorizontal)
pDC>TextOut(10,10,"Collection",10)

fntVertical.CreateFont(100,50,900,0,

FW_BOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,

OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,

DEFAULT_QUALITY,DEFAULT_PITCH|FF_ROMAN,

_T("TimesNewRoman"))
pFont=pDC>SelectObject(&fntVertical)

pDC>TextOut(5,400,"Spring",6)

pDC>SelectObject(fntVertical)
fntVertical.DeleteObject()
fntHorizontal.DeleteObject()

4. Saveall

DocumentPrintingFinalization
Eventually,afteraprintjobhasbeenperformed,theviewwouldfireanOnEndPrintingevent:

Itssyntaxis:
virtualvoidOnEndPrinting(CDC*pDC,CPrintInfo*pInfo)
This event takes the same arguments as its counterpart the OnBeginPrinting. This event is a
goodplacetofreetheGDIresourcesthatwereallocated.

PracticalLearning:FinalizingaPrintingJob
1. IntheClassView,undertheCExerciseViewnode,doubleclickOnEndPrintingandchangeit
asfollows:

voidCExerciseView::OnEndPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{

//TODO:addcleanupafterprinting

deletefntTitle1

deletefntTitle2
}
2. Executetheapplicationandprintitsdocument

3. Closetheapplication

MFCDocument/ViewArchitecture:
TheScrollingView

Introduction
As you may have found out from the Windows
controls we reviewed in previous lessons, the
contents of a window may hide some of its
parts. To show such parts, the control can be
equipped with a scroll bar. This characteristic
alsoappliestoaview.Hereisanexample:

CView, the parent of all MFC view classes, doesnt provide a default functionality that allows
theusertoscrollfromonesideofaviewtoanother.IfyouuseaCViewviewandwantthis
functionality, you can implement it yourself, using the appropriate methods of that class.
Because scrolling is very important and should be anticipated in many applications, the MFC
libraryprovidestheCScrollViewclass.

ScrollViewCreation
If you know for sure that the documents of an application you are creating will require
scrolling,eithervertically,horizontallyorboth,youshouldcreateitbasedontheCScrollView
class. This class provides all the default scrolling functionalities that a view would need. It is
equipped to scroll left and right or up and down. There are two main ways you can create a
CScrollViewbasedapplication.
If you are creating an application using the MFC Application wizard, you can select
CScrollView as the base class. If you are manually creating your application, derive your
viewclassonCScrollView.
CScrollViewisbasedontheCViewclasswhereitinheritsagoodpartofitsfunctionality.For
example, if you want to draw on a CScrollView object, you can call the use the
CView::OnDraw event. This event is automatically generated for you if you use the MFC
Application wizard to create your project. If you want to print the contents of a CScrollView
object,youcanusetheeventoftheCViewclassaswereviewedthemwhenstudyingprinting.
Here is an example of using the OnDraw event of a scroll view as if it were a regular CView
object:
voidCExerciseView::OnDraw(CDC*pDC)
{

CExerciseDoc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

//TODO:adddrawcodefornativedatahere
CBitmapbmpCar
CDCmdcCar

bmpCar.LoadBitmapW(IDB_CAR)
mdcCar.CreateCompatibleDC(pDC)
CBitmap*bmpOld=mdcCar.SelectObject(&bmpCar)

pDC>BitBlt(0,0,385,215,&mdcCar,0,0,SRCCOPY)
pDC>SelectObject(bmpOld)

PracticalLearning:CreatingaScrollViewBasedApplication
1. Tostartanewapplication,onthemainmenu,clickFile>NewProject
2. IntheTemplatessection,selectMFCApplication.
IntheNamebox,replacethestringwithCommonProfessionsandclickOK
3. SettheApplicationTypetoSingleDocument
4. IntheAdvencedFeatures,removethecheckboxofPrintingandPrintPreview
5. IntheGeneratedClasses,settheBaseClasstoCScrollView
6. ClickFinish
7. IntheResourceView,expandtheStringTablenodeandaccesstheStringTable
8. FortheIDR_MAINFRAMEstring,changethefirstsectiontoreadCommonProfessions
9. IntheClassView,clictheCmainFramenodeanddoubleclickPreCreateWindow
10. Makethefollowingchanges

intCMainFrame::OnCreate(LPCREATESTRUCTlpCreateStruct)
{

if(CFrameWnd::OnCreate(lpCreateStruct)==1)

return1

if(!m_wndToolBar.CreateEx(this,

TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP

|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|

CBRS_SIZE_DYNAMIC)||

!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{

TRACE0("Failedtocreatetoolbar\n")

return1//failtocreate
}

m_wndToolBar.SetWindowTextW(TEXT("StandardToolbar"))

if(!m_wndStatusBar.Create(this)||

!m_wndStatusBar.SetIndicators(indicators,

sizeof(indicators)/sizeof(UINT)))
{

TRACE0("Failedtocreatestatusbar\n")

return1//failtocreate
}

//TODO:Deletethesethreelinesifyoudon't
//wantthetoolbartobedockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY)
EnableDocking(CBRS_ALIGN_ANY)
DockControlBar(&m_wndToolBar)

CenterWindow()

return0

BOOLCMainFrame::PreCreateWindow(CREATESTRUCT&cs)
{

if(!CFrameWnd::PreCreateWindow(cs))

returnFALSE

//TODO:ModifytheWindowclassorstylesherebymodifying

//theCREATESTRUCTcs

cs.cx=512

cs.cy=712

cs.style&=~FWS_ADDTOTITLE

returnTRUE


11. CopyConsulting.bmpandpasteitintheresfolderofthecurrentproject
12. DothesameforHomeBased.bmp,Medical.bmp,andMusic.bmp
13. IntheResourceViewofMSVC,rightclickthenameoftheprojectandclickAddResource
14. ClickImport
15. Fromtheresfolderofthecurrentproject,selectthefourpicturesyouaddedandclick
Open
16. InthePropertieswindow,changetheirIDstoIDB_CONSULTING,IDB_HOMEBASED,
IDB_MEDICAL,andIDB_MUSICrespectively
17. StillintheResourceView,expandtheMenunodeanddoubleclickIDR_MAINFRAME
18. IntheViewcategory,createthefollowingmenuitems:

Caption

ID

&HomeBased ID_VIEW_HOME_BASED
&Consulting

ID_VIEW_CONSULTING

&Medical

ID_VIEW_MEDICAL

M&usic

ID_VIEW_MUSIC

19. IntheClassView,doubleclickCcommonProfessionsViewandchangeitasfollows:

//CommonProfessionsView.h:interfaceoftheCCommonProfessionsViewclass
//
#pragmaonce
//Thisenumeratorwillbeusedtomonitormenuitemselection
//andtheradiobuttonfunctionality
enumCOMMONPROFESSIONS
{

cpHomeBased,

cpConsulting,

cpMedical,

cpMusic
}
classCCommonProfessionsView:publicCScrollView
{
protected://createfromserializationonly

CCommonProfessionsView()

DECLARE_DYNCREATE(CCommonProfessionsView)
//Attributes
public:

CCommonProfessionsDoc*GetDocument()const
//Operations
public:

COMMONPROFESSIONSm_CommonProfessions
//Overrides
public:

...
#endif
20. IntheResourceView,accesstheIDR_MAINFRAMEmenu
21. RightclickConsultingandclickAddEventHandler
22. IntheMessageTypelist,makesureCOMMANDisselected.

IntheClassList,clicktheviewclass

23. ClickAddEndEdit
24. ReturntotheIDR_MAINFRAMEmenu.RightclickConsultingandclickAddEventHandler
25. IntheClassList,clicktheviewclass
26. IntheMessageTypelist,clickUPDATE_COMMAND_UI

27. ClickAddAndEdit
28. Performthesetwoactions(COMMANDandUPDATE_COMMAND_UIassociatedwiththeview
class)fortheotherthreemenuitems
29. Totakecareoftheradioeffectofthemenuitems,implementtheeventsasfollows:

//CommonProfessionsView.cpp:implementationofthe
//CCommonProfessionsViewclass
//
#include"stdafx.h"
#include"CommonProfessions.h"

#include"CommonProfessionsDoc.h"
#include"CommonProfessionsView.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#endif
//CCommonProfessionsView
IMPLEMENT_DYNCREATE(CCommonProfessionsView,CScrollView)
...
//CCommonProfessionsViewconstruction/destruction
CCommonProfessionsView::CCommonProfessionsView()
{

//TODO:addconstructioncodehere

this>m_CommonProfessions=cpHomeBased
}
...
//CCommonProfessionsViewmessagehandlers
voidCCommonProfessionsView::OnViewConsulting()
{

//TODO:Addyourcommandhandlercodehere

this>m_CommonProfessions=cpConsulting
}
voidCCommonProfessionsView::OnUpdateViewConsulting(CCmdUI*pCmdUI)
{

//TODO:AddyourcommandupdateUIhandlercodehere

pCmdUI>SetRadio(this>m_CommonProfessions==cpConsulting)

Invalidate()
}
voidCCommonProfessionsView::OnViewHomeBased()
{

//TODO:Addyourcommandhandlercodehere

this>m_CommonProfessions=cpHomeBased
}
voidCCommonProfessionsView::OnUpdateViewHomeBased(CCmdUI*pCmdUI)
{

//TODO:AddyourcommandupdateUIhandlercodehere

pCmdUI>SetRadio(this>m_CommonProfessions==cpHomeBased)

Invalidate()
}
voidCCommonProfessionsView::OnViewMedical()
{

//TODO:Addyourcommandhandlercodehere

this>m_CommonProfessions=cpMedical
}
voidCCommonProfessionsView::OnUpdateViewMedical(CCmdUI*pCmdUI)
{

//TODO:AddyourcommandupdateUIhandlercodehere

pCmdUI>SetRadio(this>m_CommonProfessions==cpMedical)

Invalidate()
}
voidCCommonProfessionsView::OnViewMusic()
{

//TODO:Addyourcommandhandlercodehere

this>m_CommonProfessions=cpMusic
}
voidCCommonProfessionsView::OnUpdateViewMusic(CCmdUI*pCmdUI)
{

//TODO:AddyourcommandupdateUIhandlercodehere

pCmdUI>SetRadio(this>m_CommonProfessions==cpMusic)

Invalidate()

}
30. Saveall

TheSizeoftheScrollingRegion
A scroll view is meant to show scroll bars only when necessary. To make this decision, the
viewshouldbeawareofthedimensionsofthedocument.
When you have just created a CScrollView application, the view doesnt know what
dimensions it would use in the scrolling region. This characteristic can be specified using the
CScrollView::SetScrollSizes()method.Itssyntaxis:
voidSetScrollSizes(intnMapMode,

SIZEsizeTotal,

constSIZE&sizePage=sizeDefault,

constSIZE&sizeLine=sizeDefault)
Ths nMapMode argument holds a mapping mode that can be MM_TEXT, MM_HIMETRIC,
MM_TWIPS,MM_HIENGLISH,MM_LOMETRIC,orMM_LOENGLISH.
The sizeTotal argument is the width and the height values that will be set as the maximum
dimensionsofthescrollingarea.
TheoptionalsizePage argument is the value by which the view would be scrolled for a page,
thatis,whentheuserclicksinsidethescrollingregionofthebar.
TheoptionalsizeLineargumentisthevaluebywhichtheviewwouldscrollwhentheuserclicks
onceinoneofthearrowbuttonsofthescrollbar.
Ifyouwanttospecifythedefaultdimensionsoftheviewforyourapplication,youcanusethe
CView::OnInitialUpdate event that the CScrollView class inherits. If you create a
CScrollViewbased project using the MFC Application, the wizard would generate an
OnInitialUpdate event for you and would write a default SetScrollSizes code that, in most
cases,youshouldmodify.UsingthesizeTotal,youcanspecifyonlythewidth,onlytheheight,
orboth.
As mentioned above, the view doesnt always show the scroll bars. For example, if the
application itself or the user increases the size of the frame so it would be greater than the
dimensions stored in the SIZE value of the SetScrollSizes() method, the scroll bars would
disappear.Hereisanexample:
BOOLCMainFrame::PreCreateWindow(CREATESTRUCT&cs)
{

if(!CFrameWnd::PreCreateWindow(cs))

returnFALSE

//TODO:ModifytheWindowclassorstylesherebymodifying

//theCREATESTRUCTcs

cs.cx=410
cs.cy=310
cs.style&=~FWS_ADDTOTITLE

returnTRUE

voidCExerciseView::OnInitialUpdate()
{

CScrollView::OnInitialUpdate()

CSizesizeTotal
//TODO:calculatethetotalsizeofthisview
sizeTotal.cx=385
sizeTotal.cy=215
SetScrollSizes(MM_TEXT,sizeTotal)

PHP code
generator
Generate
PHP code for
any local or
remote
database.

In the same way, when you pass constant values as the sizeTotal of the SetScrollSizes()
method, you should have a good idea of the dimensions of the contents of the view. An
alternativeistogetthedimensionsofthecontentsandstoretheminavalue.Forexample,if
you are using the view to display a picture, it may be a good idea to know the dimensions of
thatpicturesotheviewwouldfitit.
Toknowthecurrentsizeofthescrollingregionandeventhemappingmodeappliedtoit,you
cancalltheGetDeviceScrollSizes().Itssyntaxis:
voidGetDeviceScrollSizes(int&nMapMode,

SIZE&sizeTotal,

SIZE&sizePage,

SIZE&sizeLine

)const
At any time, to get the size of the scrolling region, you can call the GetTotalSize()method.
Itssyntaxis:
CSizeGetTotalSize()const
Thismethodreturnsthewidth,asaCSize::cxvalue,andtheheight,asaCSize::cyvalue,of
thescrollview.

PracticalLearning:SettingtheDimensionsoftheView
1. Tochangethesizeoftheview,changetheOnDraweventoftheviewclassasfollows:

voidCCommonProfessionsView::OnDraw(CDC*pDC)
{

CCommonProfessionsDoc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

//TODO:adddrawcodefornativedatahere
CBitmapbmpProfession
CDCmemDCProfession
CSizeszeBitmap

if(m_CommonProfessions==cpConsulting)
{

bmpProfession.LoadBitmap(IDB_CONSULTING)

szeBitmap.cx=1276

szeBitmap.cy=1024
}
elseif(m_CommonProfessions==cpHomeBased)
{

bmpProfession.LoadBitmap(IDB_HOMEBASED)

szeBitmap.cx=683

szeBitmap.cy=748
}
elseif(m_CommonProfessions==cpMedical)
{

bmpProfession.LoadBitmap(IDB_MEDICAL)

szeBitmap.cx=683

szeBitmap.cy=1024

}
elseif(m_CommonProfessions==cpMusic)
{

bmpProfession.LoadBitmap(IDB_MUSIC)

szeBitmap.cx=1280

szeBitmap.cy=853
}

memDCProfession.CreateCompatibleDC(pDC)
CBitmap*bmpPrevious=memDCProfession.SelectObject(&bmpProfession)

if(m_CommonProfessions==cpConsulting)
pDC>BitBlt(0,0,1276,1024,&memDCProfession,0,0,SRCCOPY)
elseif(m_CommonProfessions==cpHomeBased)
pDC>BitBlt(0,0,683,748,&memDCProfession,0,0,SRCCOPY)
elseif(m_CommonProfessions==cpMedical)
pDC>BitBlt(0,0,683,1024,&memDCProfession,0,0,SRCCOPY)
elseif(m_CommonProfessions==cpMusic)
pDC>BitBlt(0,0,1280,853,&memDCProfession,0,0,SRCCOPY)

pDC>SelectObject(bmpPrevious)

SetScrollSizes(MM_TEXT,szeBitmap)

2. Executetheapplicationtotestit

3. Closeit

CheckingtheExistenceofScrollBars
Rememberthat,dependingonthesizeofthecontentrelativetotheframeofthewindow,the
viewmayormaynotdisplaythescrollbar(s).Insomecases,beforeperforminganoperation
onthevieworitscontents,youmayneedtoknowwhethertheviewiscurrentlyequippedwith
oneorbothscrollbars.Togetthisinformation,youcancalltheCheckScrollBars()method.
Itssyntaxis:
voidCheckScrollBars(BOOL&bHasHorzBar,BOOL&bHasVertBar)const
Noticethateachargumentispassedbyreference.Thismeansthateachwouldreturnavalue.
After calling this method, if the frame is displaying a horizontal scroll bar, the first argument
would return with a TRUE value. If the frame is displaying a vertical scroll bar, the second
argumentwouldreturnwithaTRUEvalue.

CheckingthePositionsofScrollBoxes

If the frame is equipped with one or both scroll bars, the user can scroll. If this happens and
you want to know the position of the scroll boxes, you can call the
GetDeviceScrollPosition()method.Itssyntaxis:
CPointGetDeviceScrollPosition()const
Thismethodreturnstheposition,asaCPointcoordinate,ofthescrollboxes.

ScalingtheDocumenttoFittheView
Imagineyouhavespecifiedthecontentsofthedocument.Forexample,supposeyouareusing
theviewtodisplayapictureandallowtheusertoscrolltogettohiddensections.Iftheuser
resizes the window to a width longer than the contents, the horizontal scroll bar would
disappear.Considerthefollowingexample:

In the same way, if the user resizes the window to a height taller than the contents, the
verticalscrollbarwoulddisappear.Asmentionedalready,iftheuserresizesthewholewindow
widerandtallerthanthecontents,bothscrollbarswoulddisappear:

Ifyouwant,andifyourapplicationisappropriateforit,youcanuseastretchingeffectsothat
the contents of the document would extend to the resizing dimensions of the view when the
userchangesthesizeofthewindow.Considerthefollowingtwoscreenshots:

If you want the contents of the view to resize itself to fit the view when the user resizes the
window, instead of calling SetScrollSizes, call the CScrollView::SetScaleToFitsSize()
method.Itssyntaxis:
voidSetScaleToFitSize(SIZEsizeTotal)
Theargumentspecifiesthedimensionsoftheview.Aftercallingthismethod,theviewdoesnt
have scroll bars anymore and its contents would assume any size the view gets resized to.
Hereisanexampleofcallingthismethod:
voidCExerciseView::OnInitialUpdate()
{

CScrollView::OnInitialUpdate()

CSizesizeTotal
//TODO:calculatethetotalsizeofthisview
sizeTotal.cx=385
sizeTotal.cy=215
SetScaleToFitSize(sizeTotal)

Integrate Java and C++


Easy, professional solution for all your Java-C++ integration projects.

Home

Copyright20062007FunctionX,Inc.

MFCTopics:PrintingFundamentals

FundamentalsofPrinting

Introduction
To make it possible to print from a document,
that is, from a CDocument object, the MFC
provides printing at the CView level. Since
CView is the common ancestor to the view
based classes, the derived objects inherit this
functionality,
using
the
Document/View
architecture.

WYSIWYGNotExactly
When introducing the process of creating a new
project, we saw that you could use the MFC
Application wizard to generate a semiready
made application equipped with a view. When
studying GDI, we saw that you could use the
OnDraw()eventoftheviewtodrawsomething
on the monitor (of course, if you manually
create your application and apply the
document/view architecture, you can still
implementthiseventonyourown).
IfyouusetheMFCApplicationtocreateaviewbasedapplication,thewizardwouldgiveyouto
optiontosupportprinting:

If you accept this default to provide printing in your application, the wizard would create a
readymademenu:

Noticethatthetoolbarisalsoequippedwithabuttonthatdisplaysaprinter.Thisindicatesthat
youshouldbeabletoprintsomethingyouwouldhavedrawnusingtheOnDraw()event.
For example, you can draw a picture or bitmap to display to the user. Consider the following
image:

Hereisawayofdisplayingthispictureinaview:
voidCDecorationView::OnDraw(CDC*pDC)
{

CDecorationDoc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

CBitmapbmpFlower
CDCmemDCFlower

bmpFlower.LoadBitmap(IDB_FLOWER1)
memDCFlower.CreateCompatibleDC(pDC)
CBitmap*bmpPrevious=memDCFlower.SelectObject(&bmpFlower)

pDC>BitBlt(10,10,450,563,&memDCFlower,0,0,SRCCOPY)

pDC>SelectObject(bmpPrevious)
//TODO:adddrawcodefornativedatahere
Thiswouldproduce:

PHP code
generator
Generate
PHP code for
any local or
remote
database.

Toprintthis,onthemainmenu,youwouldclickFile>Printandyouwouldnoticethatonly
asmallpictureprints

This indicates that, when it comes to default printing, What You See on the monitor is not
exactlyWhatYouGetonthePrinter.

PrintingWiththeDocument/View
Architecture

ADocumentanditsPages
When it comes to printing, the object from your
application is called a document. Inside of a
document, it is made of one or more pages. A
pageiscreatedaspartofadocument:

Print Server Software


Windows Print Server Software.
Installs in Seconds, No Hardware.

A document is not a physical object. It is an electronic representation of the result of an


application. Because it is not physical, it doesnt have dimensions: it has neither a width nor a
length. On the other hand, a page that is part of a document has dimensions. When printing,
therearestandarddimensionsthattheprinterwillfollow.
A document has and must have at least one page. A document can also have more than one
page:

Inthesameway,adocumentcanhaveasmanypagesasnecessary:

PracticalLearning:IntroducingtheDocumentandPages
1. Tostartanewapplication,onthemainmenuofMicrosoftVisualC++,clickFile>New>
Project

2. IntheTemplatessectionoftheNewProjectdialogbox,clickMFCApplication
3. IntheNamebox,typeDepartmentStore2andclickOK
4. ClickApplicationTypeand,intherightframe,clickSingleDocument
5. Intheleftframe,clickDocumentTemplateStringsand,intheMainFrameCaption,
changethestringtoDepartmentStore
6. Intheleftframe,clickGeneratedClassesandmakethefollowingchanges:
ClassName

.hFile

.cppFile

BaseClass

CExerciseView ExerciseView.h ExerciseView.cpp CScrollView


CExerciseApp

CWinApp

CExerciseDoc

ExerciseDoc.h

ExerciseDoc.cpp

CDocument

7. ClickFinish
8. Copyeachofthesepictures

Cover1.bmp

Dress1.bmp

Dress2.bmp

Dress3.bmp

Dress4.bmp

Dress5.bmp

Dress6.bmp

9. Pastethemintheresfolderofthecurrentproject
10. Onthemainmenu,clickProject>AddResource
11. IntheAddResourcedialogbox,clickImport...
12. Locatetheressubfolderofthecurrentproject,clickCover1.bmp
13. PressandholdCtrl
14. ClickDress1.bmp,Dress2.bmp,Dress3.bmp,Dress4.bmp,Dress5.bmp,andDress6.bmp
15. ReleaseCtrlandclickOpen
16. IntheResourceView,expandtheBitmapfolder,doubleclickeachitemand,inthe
Propertieswindow,changeitsIDasfollows:

Filename

ID

res/Cover1.bmp IDB_COVER
res/Dress1.bmp IDB_DRESS1
res/Dress2.bmp IDB_DRESS2
res/Dress3.bmp IDB_DRESS3
res/Dress4.bmp IDB_DRESS4

res/Dress5.bmp IDB_DRESS5
res/Dress6.bmp IDB_DRESS6
17. IntheClassView,expandDepartmentStore2,expandCExerciseView,anddoubleclick
OnInitialUpdate
18. Changeitasfollows:

voidCExerciseView::OnInitialUpdate()
{

CScrollView::OnInitialUpdate()

CSizesizeTotal

//TODO:calculatethetotalsizeofthisview

sizeTotal.cx=500

sizeTotal.cy=1360

SetScrollSizes(MM_TEXT,sizeTotal)
}

19. IntheClassView,expandCmainFrameanddoubleclickOnCreate
20. Changetheeventasfollows:

BOOLCMainFrame::PreCreateWindow(CREATESTRUCT&cs)
{

if(!CFrameWnd::PreCreateWindow(cs))

returnFALSE

//TODO:ModifytheWindowclassorstylesherebymodifying

//theCREATESTRUCTcs

cs.cx=450

cs.cy=600

cs.style&=~FWS_ADDTOTITLE

returnTRUE

21. Saveall

IntroductiontoDocument/ViewPrinting
One of the primary ways Microsoft reduces its complexity of printing is through device
independence.Thismeansthatyoushouldworrylesswiththetypeofdeviceusedtoprint:you
dont have to care what type of printer or machine would be used to print a document of your
application. What you have left to do is the drawing side of the document. You have two main
approaches: using the MFC Application or manually implementing the document/view
architectureoftheMFClibrary.
As mentioned in the previous sections, if you use the MFC Application and decide to create a
CViewbased application, the wizard would suggest support for printing. If you accept it, it
would add a Print, a Print Preview, and a Print Setup options. As the wizard is writing the
primary code for your application, it would add code for three events: OnPreparePrinting,
OnBeginPrinting,andOnEndPrinting:
BOOLCExerciseView::OnPreparePrinting(CPrintInfo*pInfo)
{

//defaultpreparation

returnDoPreparePrinting(pInfo)
}
voidCExerciseView::OnBeginPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{

//TODO:addextrainitializationbeforeprinting
}
voidCExerciseView::OnEndPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{

//TODO:addcleanupafterprinting
}

PrintPreparation
As you may know by now, the user typically launches printing by opening the Print dialog box
that is equipped with various options and then clicking OK. To control how these options are
presentedtotheuser,theviewclassfirestheOnPreparePrintingevent.Itssyntaxis:
virtualBOOLOnPreparePrinting(CPrintInfo*pInfo)

If you are manually creating your application, make sure you add this event. As you can see
fromtheabovelines,theprimarycodewrittenbythewizardservesonlyasaplaceholder.
ThiseventtakesasargumentaCPrintInfoobject.Noticethatitispassedasapointer.Thisis
for two good reasons. If you access the argument, it can give you information about the print
job,informationthatmayhavebeenstoredintheCPrintInfoobject.Inthesameway,youcan
use the argument to make changes to the print job. After making such changes, call the
CView::DoPreparePrinting() method and pass it the modified CPrintInfoobject.Thesyntax
ofthismethodis:
BOOLDoPreparePrinting(CPrintInfo*pInfo)
The CView::OnPreparePrinting() event fires when the user initiates printing but before the
actualprintingoccurs.ThisisagoodplacetosetsomeoptionsonthePrintdialogbox.Thereare
two ways you can do this. You can directly use the pInfo object because the CPrintInfo
structure has a member variable named m_pPD that is of type CPrintDialog. Another
technique consists of creating your own CPrintDialog object, define it as you wish, and then
assigningittothem_pPDmemberofthepInfoargument.Hereisanexample:
BOOLCExerciseView::OnPreparePrinting(CPrintInfo*pInfo)
{

CPrintDialog*dlg=newCPrintDialog(FALSE,PD_PAGENUMS)

pInfo>m_pPD=dlg

pInfo>SetMinPage(1)

pInfo>SetMaxPage(14)

//defaultpreparation
returnDoPreparePrinting(pInfo)

PracticalLearning:PreparingtoPrint
1. IntheClassViewandundertheCExerciseViewnode,doubleclickOnPreparePrintingand
changeitasfollows:

BOOLCExerciseView::OnPreparePrinting(CPrintInfo*pInfo)
{

//defaultpreparation

pInfo>SetMaxPage(2)

returnDoPreparePrinting(pInfo)

2. Saveall

DocumentPrintingPreparation
OncethePrintdialogboxdisplays,theusercanreview,acceptormakechangesonit,andthen
clickOKtoprint.Ofcourse,theusercanclickCanceltogiveup.OncetheuserclicksOK,before
the job gets to the device, you must prepare the tools that would be used. To assist you with
makingthepreparationfortheactualprinting,theviewclassfiresanOnBeginPrintingevent:

ThesyntaxoftheOnBeginPrintingeventis:
virtualvoidOnBeginPrinting(CDC*pDC,CPrintInfo*pInfo)
ThepDC argument is the device context of the printer. ThepInfo is used to describe the print
job.Ifyouaremanuallycreatingyourviewbasedapplication,youshouldoverridethisevent.If
youusetheMFCApplication,thewizardcancreatetheskeletoncodeforyou.
BecausetheOnBeginPrintingeventisfiredbeforetheactualprintingstarts,youcanuseitto

initializetheGDItoolsthatwouldbeusedtodrawontheprintedsheet.Tomakesurethatthese
toolsareavailabletootherevents,youshouldhavedeclaredthemglobally.

PracticalLearning:BeginningtoPrint
1. IntheClassView,doubleclicktheCExerciseViewnodeanddeclaretwoprivateCFont
pointersasfollows:

private:

CFont*fntTitle1

CFont*fntTitle2
}
2. IntheClassView,underCExerciseView,doubleclickOnBeginPrintingandchangeitas
follows:

voidCExerciseView::OnBeginPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{

//TODO:addextrainitializationbeforeprinting

this>fntTitle1=newCFont

fntTitle1>CreateFont(60,40,0,0,

FW_BOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,

OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,

DEFAULT_QUALITY,DEFAULT_PITCH|FF_ROMAN,

_T("TimesNewRoman"))

this>fntTitle2=newCFont
fntTitle2>CreateFont(100,50,900,0,

FW_BOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,

OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,

DEFAULT_QUALITY,DEFAULT_PITCH|FF_ROMAN,

_T("TimesNewRoman"))

3. Saveall

DeviceContextPreparation
AfterallocatingGDIresourcesthatwouldbeusedtodraw,youcanpreparetheprintersdevice
context.Toassistyouwiththis,youcanusetheOnPrepareDCeventoftheview.Thesyntaxof
thiseventis:
virtualvoidOnPrepareDC(CDC*pDC,CPrintInfo*pInfo=NULL)
The pDC argument represents the device context of the printer. The pInfo object contains a
descriptionoftheprintjobsuchasthenumberofpages.
Whenpreparingtheprintersdevicecontext,youcanexaminethevaluesofthepInfoargument
here. During printing, the device will check the information in the pInfoobject.Forexample,if
pInfo doesnt specify the number of pages, the printer will consider that the document contains
only one page. In this case, if the document contains more than one, the first page would be
printed, the CPrintInfo::m_pContinuePrinting value would be set to FALSE, and the printing
wouldstop.
Whileaprintingjobisgoingon,thepagethatisbeingprintedataparticulartimeisreferredto
as the current page and it is represented by the CPrintInfo::m_nCurPage value. Using the
OnPrepareDC() event, you can continually check the value of the CPrintInfo::m_nCurPage
value.Whentheprintergetstothelastpage,thevalueofthismemberwouldbesetto1.Once
youfindthisout,youcansettheCPrintInfo::m_pContinuePrintingvaluetoFALSE.

Printing
TheactualprintingoccursintheCView::OnPrint()event.Itssyntaxis:
virtualvoidOnPrint(CDC*pDC,CPrintInfo*pInfo)
The pDC object is the device context of the printer, the CDC on which the contents of the
documentwouldbeprinted.ThepInfoobjectcontainsadescriptionoftheprintjob.
WhiletheOnPreparePrintingeventisfiredwhenadocumentissenttotheprinter,theOnPrint
eventisfiredforeachpagetobeprinted:

YoucanusetheOnPrinteventtoformatapagethewayyouwant.Forexample,youcancreate
atopsectionreferredtoastheheaderand/orabottomsectionreferredtoasthefooter.
Asstatedalready,theprintingofapageisperformedinresponsetotheCView::OnPrintevent.
At a particular time, if you want to find out whether a print job is currently occurring, you can
call the CDC::IsPrinting() method. If a printing job is going on, this method returns TRUE.
Otherwise,itreturnsFALSE.

PracticalLearning:Printing
1. IntheClassView,clickCExerciseViewand,intheOverridessectionoftheProperties
window,clickthearrowoftheOnPrintitemtoselect<Add>OnPrint
2. Implementtheeventasfollows:

voidCExerciseView::OnPrint(CDC*pDC,CPrintInfo*pInfo)
{

//TODO:Addyourspecializedcodehereand/orcallthebaseclass

pDC>SetMapMode(MM_ISOTROPIC)

pDC>SetWindowExt(500,500)

pDC>SetViewportExt(4500,6500)

if(pInfo>m_nCurPage==1)
{

CBitmapbmpCover

CDCmemDCCover

CBitmap*bmpOldCover

bmpCover.LoadBitmap(IDB_COVER)
memDCCover.CreateCompatibleDC(pDC)
bmpOldCover=memDCCover.SelectObject(&bmpCover)

pDC>SetBkMode(TRANSPARENT)

pDC>BitBlt(100,60,400,560,&memDCCover,0,0,SRCCOPY)
pDC>SelectObject(bmpOldCover)

CFont*fntOld=pDC>SelectObject(fntTitle1)

pDC>TextOut(10,10,"Collection",10)

fntOld=pDC>SelectObject(fntTitle2)

pDC>TextOut(5,400,"Spring",6)

pDC>SelectObject(fntOld)
}
elseif(pInfo>m_nCurPage==2)
{

CBitmapbmpDress1,bmpDress2,bmpDress3,

bmpDress4,bmpDress5,bmpDress6

CDCmemDCDress1,memDCDress2,memDCDress3,

memDCDress4,memDCDress5,memDCDress6

CBitmap*pOldDress

bmpDress1.LoadBitmap(IDB_DRESS1)
bmpDress2.LoadBitmap(IDB_DRESS2)
bmpDress3.LoadBitmap(IDB_DRESS3)
bmpDress4.LoadBitmap(IDB_DRESS4)
bmpDress5.LoadBitmap(IDB_DRESS5)
bmpDress6.LoadBitmap(IDB_DRESS6)

memDCDress1.CreateCompatibleDC(pDC)
memDCDress2.CreateCompatibleDC(pDC)
memDCDress3.CreateCompatibleDC(pDC)
memDCDress4.CreateCompatibleDC(pDC)

memDCDress5.CreateCompatibleDC(pDC)
memDCDress6.CreateCompatibleDC(pDC)

pOldDress=memDCDress1.SelectObject(&bmpDress1)
pDC>BitBlt(10,10,94,200,&memDCDress1,0,0,SRCCOPY)

pOldDress=memDCDress2.SelectObject(&bmpDress2)
pDC>BitBlt(360,10,113,200,&memDCDress2,0,0,SRCCOPY)

pOldDress=memDCDress3.SelectObject(&bmpDress3)
pDC>BitBlt(10,220,148,200,&memDCDress3,0,0,SRCCOPY)

pOldDress=memDCDress4.SelectObject(&bmpDress4)
pDC>BitBlt(380,220,78,200,&memDCDress4,0,0,SRCCOPY)

pOldDress=memDCDress5.SelectObject(&bmpDress5)
pDC>BitBlt(10,440,100,200,&memDCDress5,0,0,SRCCOPY)

pOldDress=memDCDress6.SelectObject(&bmpDress6)
pDC>BitBlt(360,440,143,200,&memDCDress6,0,0,SRCCOPY)

pDC>SelectObject(pOldDress)

CScrollView::OnPrint(pDC,pInfo)

3. IntheMethodscombobox,selectOnDrawandchangeitasfollows:

voidCExerciseView::OnDraw(CDC*pDC)
{

CExerciseDoc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

//TODO:adddrawcodefornativedatahere
if(!pDC>IsPrinting())
{

CBitmapbmpCover,

bmpDress1,bmpDress2,bmpDress3,

bmpDress4,bmpDress5,bmpDress6

CDCmemDCCover,

memDCDress1,memDCDress2,memDCDress3,

memDCDress4,memDCDress5,memDCDress6

bmpCover.LoadBitmap(IDB_COVER)
bmpDress1.LoadBitmap(IDB_DRESS1)
bmpDress2.LoadBitmap(IDB_DRESS2)
bmpDress3.LoadBitmap(IDB_DRESS3)
bmpDress4.LoadBitmap(IDB_DRESS4)
bmpDress5.LoadBitmap(IDB_DRESS5)
bmpDress6.LoadBitmap(IDB_DRESS6)

memDCCover.CreateCompatibleDC(pDC)
memDCDress1.CreateCompatibleDC(pDC)
memDCDress2.CreateCompatibleDC(pDC)
memDCDress3.CreateCompatibleDC(pDC)
memDCDress4.CreateCompatibleDC(pDC)
memDCDress5.CreateCompatibleDC(pDC)
memDCDress6.CreateCompatibleDC(pDC)

CBitmap*bmpOld=memDCCover.SelectObject(&bmpCover)

pDC>BitBlt(80,60,400,560,&memDCCover,0,0,SRCCOPY)

bmpOld=memDCDress1.SelectObject(&bmpDress1)
pDC>BitBlt(10,680,94,200,&memDCDress1,0,0,SRCCOPY)

bmpOld=memDCDress2.SelectObject(&bmpDress2)
pDC>BitBlt(360,680,113,200,&memDCDress2,0,0,SRCCOPY)

bmpOld=memDCDress3.SelectObject(&bmpDress3)
pDC>BitBlt(10,900,148,200,&memDCDress3,0,0,SRCCOPY)

bmpOld=memDCDress4.SelectObject(&bmpDress4)

pDC>BitBlt(380,900,78,200,&memDCDress4,0,0,SRCCOPY)

bmpOld=memDCDress5.SelectObject(&bmpDress5)
pDC>BitBlt(10,1150,100,200,&memDCDress5,0,0,SRCCOPY)

bmpOld=memDCDress6.SelectObject(&bmpDress6)
pDC>BitBlt(340,1150,143,200,&memDCDress6,0,0,SRCCOPY)

CFontfntVertical
CFontfntHorizontal
CFont*pFont

pDC>SetBkMode(TRANSPARENT)
fntHorizontal.CreateFont(60,40,0,0,

FW_BOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,

OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,

DEFAULT_QUALITY,DEFAULT_PITCH|FF_ROMAN,

_T("TimesNewRoman"))
pFont=pDC>SelectObject(&fntHorizontal)
pDC>TextOut(10,10,"Collection",10)

fntVertical.CreateFont(100,50,900,0,

FW_BOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,

OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,

DEFAULT_QUALITY,DEFAULT_PITCH|FF_ROMAN,

_T("TimesNewRoman"))
pFont=pDC>SelectObject(&fntVertical)

pDC>TextOut(5,400,"Spring",6)

pDC>SelectObject(fntVertical)
fntVertical.DeleteObject()
fntHorizontal.DeleteObject()

4. Saveall

DocumentPrintingFinalization
Eventually,afteraprintjobhasbeenperformed,theviewwouldfireanOnEndPrintingevent:

Itssyntaxis:
virtualvoidOnEndPrinting(CDC*pDC,CPrintInfo*pInfo)
This event takes the same arguments as its counterpart the OnBeginPrinting. This event is a
goodplacetofreetheGDIresourcesthatwereallocated.

PracticalLearning:FinalizingaPrintingJob
1. IntheClassView,undertheCExerciseViewnode,doubleclickOnEndPrintingandchangeit
asfollows:

voidCExerciseView::OnEndPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{

//TODO:addcleanupafterprinting

deletefntTitle1

deletefntTitle2
}
2. Executetheapplicationandprintitsdocument

3. Closetheapplication

MFCTopics:CDCPrintingFundamentals

Introduction
Sofar,wehaveintroducedandusedCDCasthe
classusedtodrawtextorgraphicsinaview.As
we saw in the previous section, the CDC class
alsohighlyinterveneswhenitcomestoprinting.
Microsoft Windows considers different types of
drawing,dependingonthedevicethatisshowing
the result. The screen of a monitor is usually
referred to as a display. Because the printer is
anexternaldevice,ithasitsowncategory.

Online File Sharing


Business-class Secure File
Sharing 4 Stars by PC
Magazine. Free Trial

Because it distinguishes the display and the


printer,theCViewclassprovidestwomessages
and events to deal with drawing. Since you can
andwillusuallyimplementbothevents,youmay
want to know which one gets fired and when.
Considerthefollowingtwoevents:
voidCDecorationView::OnDraw(CDC*pDC)
{

CDecorationDoc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

AfxMessageBox("CallingOnDraw())")

//TODO:adddrawcodefornativedatahere

voidCDecorationView::OnPaint()
{

CPaintDCdc(this)//devicecontextforpainting

//TODO:Addyourmessagehandlercodehere

//DonotcallCView::OnPaint()forpaintingmessages

AfxMessageBox("CallingOnPaint())")
If you execute the application, when it appears, a message box indicates that the OnPaint
eventisfired.If,onthemainmenu,youclickFile>Printand,inthePrintdialogbox,you
clickOK,youwouldnoticethattheOnDraweventfires.ThisindicatesthattheOnPaintevent
isusedtodrawonthemonitorandtheOnDraweventisusedtodrawonthepieceofpaperon
theprinter.
Considerthefollowingcode:

voidCDecorationView::OnDraw(CDC*pDC)
{

CDecorationDoc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

AfxMessageBox("CallingOnDraw())")

//TODO:adddrawcodefornativedatahere

bmpFlower.LoadBitmap(IDB_FLOWER1)
memDCFlower.CreateCompatibleDC(pDC)

CBitmapbmpFlower
CDCmemDCFlower

CBitmap*bmpPrevious=memDCFlower.SelectObject(&bmpFlower)

pDC>BitBlt(10,10,450,563,&memDCFlower,0,0,SRCCOPY)

pDC>SelectObject(bmpPrevious)

voidCDecorationView::OnPaint()
{

CPaintDCdc(this)//devicecontextforpainting

//TODO:Addyourmessagehandlercodehere

//DonotcallCView::OnPaint()forpaintingmessages

AfxMessageBox("CallingOnPaint())")
Thistime,ifyouexecutetheapplication,theOnPainteventwouldfirebutnothingdisplayson
thescreen.If,onthemainmenu,youclickFile>Printandif,onthePrintdialogbox,you
clickOK,theOnDraweventwouldfireandasmallpicturewouldbeprintedonthepaper.
Considerthefollowingevents:

voidCDecorationView::OnDraw(CDC*pDC)
{

CDecorationDoc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

//TODO:adddrawcodefornativedatahere
CBitmapbmpFlower
CDCmemDCFlower

bmpFlower.LoadBitmap(IDB_FLOWER1)
memDCFlower.CreateCompatibleDC(pDC)
CBitmap*bmpPrevious=memDCFlower.SelectObject(&bmpFlower)

pDC>BitBlt(10,10,450,563,&memDCFlower,0,0,SRCCOPY)

pDC>SelectObject(bmpPrevious)

voidCDecorationView::OnPaint()
{

CPaintDCdc(this)//devicecontextforpainting

//TODO:Addyourmessagehandlercodehere

//DonotcallCView::OnPaint()forpaintingmessages

CBitmapbmpFlower

CDCmemDCFlower

bmpFlower.LoadBitmap(IDB_FLOWER1)
memDCFlower.CreateCompatibleDC(&dc)
CBitmap*bmpPrevious=memDCFlower.SelectObject(&bmpFlower)

dc.BitBlt(10,10,450,563,&memDCFlower,0,0,SRCCOPY)

dc.SelectObject(bmpPrevious)
Notice that both events received the exact same code. If you execute the application, the
OnPaint event would fire and a large picture would be drawn on the screen. If you print, the
OnDraw event would fire and a small picture would be printed on the paper although both
events received the same code. This illustrates that the display and the printer interpret
drawingdifferently

TransformingthePrinter
We have just established that the display and the printer interpret GDI code differently. This
means that we should also draw on them differently. Because they are rendering the same
contents when they receive the same code, since the result on the printer simply appears
small,wecansimplyzoomittoareasonablesizetomakeitappearasthesamecontentsof
the display. In our study of the GDI library, we saw that, to increase the display size of a
drawing, we could call the CDC::SetViewportExt() method after calling the
CDC::SetWindowExt() method and the CDC::SetMapMode() method with a value of
MM_ISOTROPIC.
Hereisanexample:

PHP code
generator
Generate PHP code for
any database.
AJAX,charts,dynamic
forms and more

voidCDecorationView::OnDraw(CDC*pDC)
{

CDecorationDoc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

//TODO:adddrawcodefornativedatahere
CBitmapbmpFlower
CDCmemDCFlower

bmpFlower.LoadBitmap(IDB_FLOWER1)
memDCFlower.CreateCompatibleDC(pDC)
CBitmap*bmpPrevious=memDCFlower.SelectObject(&bmpFlower)

pDC>SetMapMode(MM_ISOTROPIC)
pDC>SetWindowExt(500,500)
pDC>SetViewportExt(4500,5630)

pDC>BitBlt(10,10,450,563,&memDCFlower,0,0,SRCCOPY)

pDC>SelectObject(bmpPrevious)

voidCDecorationView::OnPaint()
{

CPaintDCdc(this)//devicecontextforpainting

//TODO:Addyourmessagehandlercodehere

//DonotcallCView::OnPaint()forpaintingmessages

CBitmapbmpFlower

CDCmemDCFlower

bmpFlower.LoadBitmap(IDB_FLOWER1)
memDCFlower.CreateCompatibleDC(&dc)
CBitmap*bmpPrevious=memDCFlower.SelectObject(&bmpFlower)

dc.BitBlt(10,10,450,563,&memDCFlower,0,0,SRCCOPY)

dc.SelectObject(bmpPrevious)
Thistime,theprintedsheetwouldresemblethepictureontheview:

MFCTopics:MenuFundamentals

IntroductiontotheMainMenu
Amenuisalistofactionstheusercanperformon
anapplication.Theactionsarepresentedinoneor
more groups. There are broad categories of
menus:themainmenuandthecontextmenu.
A main menu, also called a toplevel menu,
displays categories of menu items using a range
ofitemscalledamenubar:

Whentheuserclicksanitemofthemenubar,theitemclickedopensitslist:

After a list has been displayed, the user can then use an item from the list. Each item of the
list is primarily a word or a group of words on a line. Different menu items are used for
differentreasons.Forexample,somemenuitemssimplydisplayawordoragroupofwords.
Someotheritemsdisplayacheckmark.Thisindicatesthattheitemtogglestheavailabilityor
disappearanceofanobject.
When a menu item is only meant to lead to a submenu, such a menu item is called a popup

menu.Therearetwotypesofpopupmenus.Ifthemenudisplaysontopofawindow,whichis
thetypeofmenuunderthetitlebar,thewordontop,whichrepresentsacategoryofmenu,is
apopupmenu.Ifamenuitemisequippedwithanarrowinitsright,whichmeansthemenu
itemhasasubmenu,suchamenu item is also a popup menu. Popup menus are used only to
represent a submenu. No inherent action is produced by clicking them, except that, when
placedontop,suchmenuitemsallowopeningthesubmenu.
Tocreatemenusthatbelongtoagroup,menuitemsareseparatedbyahorizontallinecalleda
separator.SeparatorsarecreateddifferentlyinMSVC6andMSVC7.

PracticalLearning:IntroducingMenus
1. StartMicrosoftVisualStudioorVisualC++andcreateaWin32Projectnamed
DepartmentStore1
2. ClickOK
3. CreateitasanEmptyProjectandclickFinish
4. Onthemainmenu,clickProject>DepartmentStore1Properties
5. ClickConfigurationProperties
6. IntheUseofMFCcomboboxoftherightsection,selectUseMFCinaSharedDLLandclick
OK
7. Tocreateaheaderfile,onthemainmenu,clickProject>AddNewItem
8. IntheTemplatessectionofthedialogbox,clickHeaderFile(.h)
9. SettheNametostdafx
10. ClickAdd
11. Intheemptydocument,type#include<afxwin.h>
12. Tocreateasourcefile,onthemainmenu,clickProject>AddNewItem
13. IntheTemplatessectionofthedialogbox,clickC++File(.cpp)
14. SettheNametostdafxandclickAdd
15. Intheemptyfile,type#includestdafx.handpressEnter
16. AddanewheaderfilenamedMainFrmand,init,type:

#include"stdafx.h"
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()

virtual~CMainFrame()
}
17. AddanewsourcefilenamedMainFrmandtypethefollowinginit:

#include"MainFrm.h"
CMainFrame::CMainFrame()
{

Create(NULL,

TEXT("DepartmentStore"),

WS_OVERLAPPEDWINDOW,

CRect(200,120,640,400))
}
CMainFrame::~CMainFrame()
{
}
18. AddanewheaderfilenamedExerciseand,init,type:

#include"stdafx.h"
classCExerciseApp:publicCWinApp
{
public:

BOOLInitInstance()
}
19. AddanewsourcefilenamedExerciseandtypethefollowinginit:

#include"Exercise.h"
#include"MainFrm.h"
BOOLCExerciseApp::InitInstance()
{

m_pMainWnd=newCMainFrame

m_pMainWnd>ShowWindow(SW_SHOW)

m_pMainWnd>UpdateWindow()

returnTRUE

CExerciseApptheApp
20. Executetheapplicationtotestit

MenuCreation
There are two main ways you can create a main menu: Using a resource file or
programmatically creating the menu items. You can create a resource file that has the .rc
extension. The menu is created as text. If you create the file manually, you must also
remembertocreateoredittheresource.hfileinordertospecifyanidentifierforeachmenu.
The alternative, which we will use, is to "visually" create the menu in Visual Studio. When
doingthis,thestudioitselfwouldupdatetheresource.hfileasitemsareaddedorremoved.
To visually create a menu, first add a resource of type Menu using the Add Resource dialog
box.The MFC library implements a Windows menu, from the Win32s HMENU class, through
theCMenuclass.Basedonthis,ifyouwanttoprogrammaticallycreateamenu,youcanstart
bydeclaringaCMenuvariable.Hereisanexample:
#include<afxwin.h>
classCExerciseApp:publicCWinApp
{
public:

virtualBOOLInitInstance()
}
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()
private:

CMenum_wndMainMenu
}
CMainFrame::CMainFrame()
{

Create(NULL,"MenusFundamentals")
}
BOOLCExerciseApp::InitInstance()
{

m_pMainWnd=newCMainFrame

m_pMainWnd>ShowWindow(SW_NORMAL)

returnTRUE

CExerciseApptheApp
After declaring the variable, to indicate that you intend to create a menu, you must first call
theCMenu::CreateMenu()method.Itssyntaxis:
BOOLCreateMenu()
Hereisanexample:
CMainFrame::CMainFrame()
{

Create(NULL,"MenusFundamentals")

this>m_wndMainMenu.CreateMenu()
Justincasesomethingmightgowrong,theMFCprovidestheVERIFYmacrothatyoucanuse

tomakesurethatthemenuwasrightlyinitialized.Itcanbeusedasfollows:
CMainFrame::CMainFrame()
{

Create(NULL,"MenusFundamentals")

VERIFY(this>m_wndMainMenu.CreateMenu())
AfterdeclaringthevariableandcallingCreateMenu(),youcanstartdefiningthecharacteristics
ofthemenu.Wewillreviewthevariouscharacteristicsinthenextsections.

PracticalLearning:CreatingaMainMenuVisually
1. Onthemainmenu,clickView>ResourceViewandagain,onthemainmenu,clickProject
>AddResource...
2. OntheAddResourcedialogbox,doubleclickMenu
3. IntheResourceView,clickIDR_MENU1toselectit
4. InthePropertieswindow,clickID,typeIDR_FIRSTandpressEnter

UsingaMenu
After creating a menu, before using it, you should associate it with a window frame that will
carry it and present it to the user. To associate a menu with a window, you have various
options. If you are using the CFrameWnd::Create() method to create the window, you can
specifythenameofthemenuusingthelpszMenuNameargument:
virtualBOOLCreate(

LPCTSTRlpszClassName,

LPCTSTRlpszWindowName,

DWORDdwStyle=WS_OVERLAPPEDWINDOW,

constRECT&rect=rectDefault,

CWnd*pParentWnd=NULL,

LPCTSTRlpszMenuName=NULL,

DWORDdwExStyle=0,

CCreateContext*pContext=NULL
)
Hereisanexample:
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()

Create(NULL,"ResourcesFundamentals",

WS_OVERLAPPEDWINDOW,CRect(200,120,640,400),

NULL,

MAKEINTRESOURCE(IDR_MAINFRAME))

}
}
IfyouareprogrammaticallycreatingthemenuusingaCMenuobject,toassignittoaframe,
youcancalltheCWnd::SetMenu()method.Itssyntaxis:
BOOLSetMenu(CMenu*pMenu)
Hereisanexample:
CMainFrame::CMainFrame()
{

Create(NULL,"MenusFundamentals")

VERIFY(this>m_wndMainMenu.CreateMenu())

//Dowhateverhere

this>SetMenu(&m_wndMainMenu)
Ifawindowalreadyhasamenuandyouwanttogetareferencetothatmenu,youcancallits
CWnd::GetMenu()method.Itssyntaxis:

CMenu*GetMenu()const
When using this method, if the window that calls it doesnt have a menu, this method returns
NULL.Otherwise,thismethodreturnsapointertotheCMenuobjectofthewindowthatcalled

it.
Asstatedalready,TheCMenuclassistheMFCsimplementationoftheHMENUhandle.Togeta
handle to an existing CMenu object of an application, you can access the value of the
CMenu::m_hMenuproperty,whichisoftypeHMENU.

PracticalLearning:AssociatingaMainMenuWithaWindow
Frame
1. AccesstheMainFrm.hfileanddeclareaprivatepointertoCMenuasfollows:

#include"stdafx.h"
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()

virtual~CMainFrame()
private:

CMenu*pCurrentMenu
}
2. Toassociatethenewmenuwiththeframe,accesstheMainFrm.cppfileandchangeitas
follows:

#include"MainFrm.h"
CMainFrame::CMainFrame()
{

Create(NULL,

TEXT("DepartmentStore"),

WS_OVERLAPPEDWINDOW,

CRect(200,120,640,400))

//Dynamicallycreateamenu...
pCurrentMenu=newCMenu
//...usingthemenuresourcewewillcreate
pCurrentMenu>LoadMenuW(MAKEINTRESOURCE(IDR_FIRST))
//Assignthemenumenutotheframeofthecurrentapplication
SetMenu(pCurrentMenu)
//Drawthemenuontheframe(thisisnotrequired
//ifthisistheonlytimewewillcreateamenu)
DrawMenuBar()

CMainFrame::~CMainFrame()
{
}
3. Savethefile

MenuMessageProcessing
As introduced earlier, a menu is primarily a list of actions that can be performed on an
application. The actions are generated when the user positions the mouse on a menu item or
whenoneoftheseitemsisclicked.IftheuserclicksanitemsuchasFileonthemainmenu,
the menu item generates a WM_INITMENUPOPUP message. To get the program ready to
process these messages, in the previous lesson, we saw that you should create a message
map.Hereisanexample:
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()

Create(NULL,"MenusFundamentals")

DECLARE_MESSAGE_MAP()

BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
END_MESSAGE_MAP()

BOOLCExoApp::InitInstance()
{

...
}
IftheMFCdoesntprovideadefaultfunctionthatprocessesyourtypeofmessage,youshould
firstimplementtheeventthatwillprocessthemessage.Hereisanexample:
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()

Create(NULL,"MenusFundamentals")

afx_msgvoidEndThisApplication()
DECLARE_MESSAGE_MAP()

...
voidCMainFrame::EndThisApplication()
{

PostQuitMessage(0)
}
Onceyouhavedefinedthemethodthatwillprocessthemessage,youcanmapittoaresource
symbol in your message map section using the ON_COMMAND macro. Once this has been
done,theapplicationcanprocessthemessage.

PracticalLearning:ProcessingaMenuMessage
1. AccesstheMainFrm.hheaderfile.Tocreateaneventthatwouldprocessamessage,
changethefileasfollows:

#include"stdafx.h"
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()

virtual~CMainFrame()

DECLARE_MESSAGE_MAP()

private:

CMenu*pCurrentMenu
}
2. AccesstheMainFrm.cppsourcefileandchangeitasfollows:

#include"MainFrm.h"
CMainFrame::CMainFrame()
{

...
}
CMainFrame::~CMainFrame()
{
}
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
END_MESSAGE_MAP()
3. Saveall

MFCTopics:CharacteristicsofMenu
Items

Introduction
Many applications rely on menus to assist the
userwiththeirinteractionwiththecomputer.To
fully support this interaction, Microsoft Windows
provides the menus with various characteristics
meant to serve different purposes. Based on
this, menus have such behaviors and properties
as alignment, radio buttons, check boxes,
grouping,etc.

APopupMenu
A main menu is made of categories of items. A
category displays as a list when the user clicks
itstopitem:

Aniteminthetoplevelofamenuisreferredtoaspopup.Tovisuallycreateapopupmenu,you
canclicktheMenunodefromtheAddResourcedialogboxclickTypeHereandtypeastringfor
themenucategory.
Toprogrammaticallycreateapopupmenu,calltheCMenu::AppendMenu()method.Itscomesin
twoversionswhosesyntaxesare:
BOOLAppendMenu(UINTnFlags,UINT_PTRnIDNewItem=0,

LPCTSTRlpszNewItem=NULL)
BOOLAppendMenu(UINTnFlags,UINT_PTRnIDNewItem,constCBitmap*pBmp)
If you are creating a simple menu item that will display by itself, you can (must) set the first
argument as MF_STRING. The second argument can be a ResourceID name as we reviewed
themearlier.Ifyouarecreatingasimplemenuitem,youcanpassthisargumentas0orNULL.
The third argument can be a string if you want to display a simple menu item. Here is an
example:
#include<afxwin.h>
classCExerciseApp:publicCWinApp
{
public:

virtualBOOLInitInstance()
}
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()
private:

MFCTopics:MaintenanceofMenuItems

MenuEnabledorDisabled
If you have just created a menu and has not yet
mapped it to a method that would process its 5x Faster C/C++ Build
message,themenuisdisabledandappearsgray.If
incredibuild.com/C++-Build-Speed
you map a menu item to a method, it becomes
enabled, indicating that the user can use it. In the Speed up Visual Studio Free Download - Start
following window, the New and the Open menu Today!
items are disabled while the Exit menu item is
enabled:

C++ Static Analysis Tools


Classe B Mercedes-Benz
Download Excel Dashboard

You also can enable or disable a menu item any time you judge this necessary. To visually
enable a menu item when designing it, in the Properties window, set its Enabled property to
False.Tovisuallyenableamenuitem,inthePropertieswindow,setitsEnabledpropertytoTrue.
Toprogrammaticallyenableordisableamenu,calltheCMenu::EnableMenuItem()method.

MenuDeletion
If you visually create a menu,, when the application exists, it would delete it and remove its
resources from the memory. If you dynamically create a menu, to delete it after using it, you
cancalltheCMenu::DestroyMenu()method.Itssyntaxis:
BOOLDestroyMenu()
Asyoucansee,themethoddoesnttakeanyargument.

PracticalLearning:DeletingaMenu
1. AccesstheMainFrm.cppfileandimplementthedestructorasfollows:
CMainFrame::~CMainFrame()
{

//IfthepointertoCMenuexists,destroyit

if(pCurrentMenu)

pCurrentMenu>DestroyMenu()
}
2. Saveall

UsingDifferentMenus
Becauseanapplicationcandealwithmorethanonetypeofdocument,usingthesamemenufor
different documents is not useful and can be confusing. To address such an issue, you can
perform various continuous operations of adding, deleting, enabling, and disabling some menu
items. If the documents are significantly different, a better alternative could consist of using
differentmenusinthesameapplication.Atonetime,youcandisplayonemenu.Atanothertime
you can, at least temporarily, replace one menu with another. This is made possible by using a
combinationoftheCMenumethodswehavereviewedsofar.

PracticalLearning:UsingDifferentMenus

1. Toaddanothermenu,intheResourceView,rightclickIDR_FIRSTandclickInsertMenu
2. IntheResourceView,clickthenewmenuand,inthePropertieswindow,changeitsIDto
IDR_SECOND
3. Inthemenudesigner,clickTypeHereandtypeFile
4. PressthedownarrowkeyandtypeExit
5. InthePropertieswindow,clickIDandtypeIDM_FILE_EXIT
6. OntherightsideofFile,clickTypeHereandtypeView
7. ClickthedownarrowkeyandtypeCustomersOrders
8. PressthedownarrowkeyandtypeEmployeesIssues
9. OntherightsideofView,clickTypeHereandtypeProcesses
10. PressthedownarrowkeyandtypeTimeSheets
11. PressthedownarrowkeyandtypeRequestforTimeOff
12. PressthedownarrowkeyandtypeLeave/Absence
13. PressthedownarrowkeyandtypeBenefits
14. RightclickViewandclickCopy
15. IntheResourceView,doubleclickIDR_FIRST
16. ClickHelpandpressIns(orInsert)
17. PressCtrl+Vtopastethemenu
18. AccesstheMainFrm.hheaderfileandchangeitasfollows:

#include"stdafx.h"
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()

virtual~CMainFrame()

afx_msgvoidClose()
afx_msgvoidShowFirstMenu()
afx_msgvoidShowSecondMenu()

DECLARE_MESSAGE_MAP()

private:

CMenu*pCurrentMenu
}
19. AccesstheMainFrm.cppsourcefileandchangeitasfollows:

#include"MainFrm.h"
CMainFrame::CMainFrame()
{

...
}
CMainFrame::~CMainFrame()
{
}
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)

ON_COMMAND(IDM_FILE_EXIT,Close)

ON_COMMAND(ID_VIEW_CUSTOMERSORDERS,ShowFirstMenu)

ON_COMMAND(ID_VIEW_EMPLOYEESISSUES,ShowSecondMenu)
END_MESSAGE_MAP()
voidCMainFrame::ShowFirstMenu()
{

this>SetMenu(NULL)

this>pCurrentMenu>DestroyMenu()

this>pCurrentMenu>LoadMenuW(IDR_FIRST)

this>SetMenu(this>pCurrentMenu)

this>DrawMenuBar()
}
voidCMainFrame::ShowSecondMenu()

this>SetMenu(NULL)
this>pCurrentMenu>DestroyMenu()
this>pCurrentMenu>LoadMenuW(IDR_SECOND)
this>SetMenu(this>pCurrentMenu)
this>DrawMenuBar()

voidCMainFrame::Close()
{

PostQuitMessage(WM_QUIT)
}
20. Executetheapplication
21. ClosetheapplicationandreturntoMSVC

IntroductiontoContextSensitiveMenu
Sofar,wehavetreatedthemenuinageneralconceptmostlyappliedtothemainmenu.Another
typeofmenu,probablylesspopularbutnotuncommonisonethatappearswhentheuserclicks
anitemsomewhereinawindow.Thistypeofmenuisreferredtoascontextsensitivebecauseit
depends on the item that would display it. Just like the main menu, before using a context
sensitive menu, you must first create it and you and you must decide when and where it would
beapplied.Becauseanapplicationcanbemadeofvariousobjects,itisuptoyoutodecidewhat
objectwouldusecontextsensitivemenuandhow.
Althoughacontextsensitivemenucandisplaywhentheuserclicksthedefineditem,toallowthe
usertoperformregularmouseclickactions,acontextsensitivemenuisusuallymadeavailable
whentheuserrightclicksthedesignateditem.

ImplementationofaContextSensitiveMenu
Whileamainmenuusuallyappearsasmorethanonegroupofitems,acontextsensitivemenu
usuallydisplaysonecolumn.Themenuitselfisprimarilycreatedlikeanyothermenu:youfirst
defineapopupitemandthenaddtheothersubitems.

FastReport VCL
for Delphi/CB 5-XE6 Fast. Compact. Feature-rich.

Previous

Copyright20062007FunctionX,Inc.

CMenum_wndMainMenu

CMainFrame::CMainFrame()
{

Create(NULL,"MenusFundamentals")

VERIFY(this>m_wndMainMenu.CreateMenu())
this>m_wndMainMenu.AppendMenu(MF_STRING,NULL,"Smell")
this>SetMenu(&m_wndMainMenu)

BOOLCExerciseApp::InitInstance()
{

m_pMainWnd=newCMainFrame

m_pMainWnd>ShowWindow(SW_NORMAL)

returnTRUE

CExerciseApptheApp
Thiswouldproduce:

If you want to create a real popup menu that display on a toplevel and holds its own list of
menuitems,youcanfirstcreateaCMenuobjectthatwillholdsthemenuitemsunderthepopup.
Suchapopupmenustartslikethemenuitemwecreatedabove.Hereisanexample:
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()
private:

CMenum_wndMainMenu

CMenum_wndFileMenu
}
CMainFrame::CMainFrame()
{

Create(NULL,"MenusFundamentals")

VERIFY(this>m_wndMainMenu.CreateMenu())
VERIFY(this>m_wndFileMenu.CreateMenu())

this>m_wndMainMenu.AppendMenu(MF_STRING,NULL,"File")
this>SetMenu(&m_wndMainMenu)
Afterinitializingthepopupmenu,youcancalltheCMenu::AppendMenu()foreachmenuitemthat
you want to display under the popup. In this case, you should pass the first argument as
MF_STRING, the second argument with a constant number that can be the name of a resource
symbol we introduced earlier, and the last argument can be the string that would display in the
menuitem.Herearethreeexamples:

CMainFrame::CMainFrame()
{

Create(NULL,"MenusFundamentals")

VERIFY(this>m_wndMainMenu.CreateMenu())
VERIFY(this>m_wndFileMenu.CreateMenu())

this>m_wndFileMenu.AppendMenu(MF_STRING,22001,"New")
this>m_wndFileMenu.AppendMenu(MF_STRING,22002,"Open")
this>m_wndFileMenu.AppendMenu(MF_STRING,22003,"Save")

this>SetMenu(&m_wndMainMenu)
After defining the menu items that would display under the toplevel menu, you can add assign
the group to the popup menu. To do this, you can call the CMenu::AppendMenu() method. This
time, the first argument would be passed as MF_POPUP, the second argument must be a
reference to the CMenu object that holds the popup menu, and the last argument should be the
stringthatwillrepresentthepopupmenu.Thiswouldbedoneasfollows:

#include<afxwin.h>
classCExerciseApp:publicCWinApp
{
public:

virtualBOOLInitInstance()
}
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()
private:

CMenum_wndMainMenu

CMenum_wndFileMenu
}
CMainFrame::CMainFrame()
{

Create(NULL,"MenusFundamentals")

VERIFY(this>m_wndMainMenu.CreateMenu())
VERIFY(this>m_wndFileMenu.CreateMenu())

this>m_wndFileMenu.AppendMenu(MF_STRING,22001,"New")
this>m_wndFileMenu.AppendMenu(MF_STRING,22002,"Open")
this>m_wndFileMenu.AppendMenu(MF_STRING,22003,"Save")
this>m_wndMainMenu.AppendMenu(MF_POPUP,

reinterpret_cast<UINT_PTR>(this>m_wndFileMenu.m_hMenu),

"File")
this>SetMenu(&m_wndMainMenu)

BOOLCExerciseApp::InitInstance()
{

m_pMainWnd=newCMainFrame

m_pMainWnd>ShowWindow(SW_NORMAL)

returnTRUE

CExerciseApptheApp
Thiswouldproduce:

Justaswecreatedthisonepopupmenu,youcancreateasmanymenuitemsasnecessary.Here

areexamples:
#include<afxwin.h>
classCExerciseApp:publicCWinApp
{
public:

virtualBOOLInitInstance()
}
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()
private:

CMenum_wndMainMenu

CMenum_wndFileMenu

CMenum_wndEditMenu

CMenum_wndHelpMenu
}
CMainFrame::CMainFrame()
{

Create(NULL,"MenusFundamentals")

VERIFY(this>m_wndMainMenu.CreateMenu())
VERIFY(this>m_wndFileMenu.CreateMenu())
VERIFY(this>m_wndEditMenu.CreateMenu())
VERIFY(this>m_wndHelpMenu.CreateMenu())

this>m_wndFileMenu.AppendMenu(MF_STRING,22001,"New")
this>m_wndFileMenu.AppendMenu(MF_STRING,22002,"Open")
this>m_wndFileMenu.AppendMenu(MF_STRING,22003,"Save")
this>m_wndMainMenu.AppendMenu(MF_POPUP,

reinterpret_cast<UINT_PTR>(this>m_wndFileMenu.m_hMenu),

"File")

this>m_wndEditMenu.AppendMenu(MF_STRING,22004,"Cut")
this>m_wndEditMenu.AppendMenu(MF_STRING,22005,"Copy")
this>m_wndMainMenu.AppendMenu(MF_POPUP,

reinterpret_cast<UINT_PTR>(this>m_wndEditMenu.m_hMenu),

"Edit")

this>m_wndHelpMenu.AppendMenu(MF_STRING,22005,

"AboutthisApplication")
this>m_wndMainMenu.AppendMenu(MF_POPUP,

reinterpret_cast<UINT_PTR>(this>m_wndHelpMenu.m_hMenu),

"Help")

this>SetMenu(&m_wndMainMenu)

BOOLCExerciseApp::InitInstance()
{

m_pMainWnd=newCMainFrame

m_pMainWnd>ShowWindow(SW_NORMAL)

returnTRUE

CExerciseApptheApp
Thiswouldproduce:

PracticalLearning:CreatingaMainMenu
1. IntheResourceView,doubleclickIDR_MAINFRAMEtogetbacktothemenu.
Inthemainwindow,clickthetopbox,typeFileandpressEnter
2. ClicktheitemunderFile.TypeNewOrder
3. InthePropertieswindow,clickIDandsetitsvaluetoIDM_FILE_NEW
4. PressEnter
5. IntheTypeHereboxundertheNewstring,typeOpenOrder
6. InthePropertieswindow,clickIDandsetitsvaluetoIDM_FILE_OPEN
7. PressEnter
8. IntheTypeHereboxundertheNewstring,typeExit
9. InthePropertieswindow,clickIDandsetitsvaluetoIDM_FILE_EXIT
10. PressEnter
11. Accessthestdafx.hheaderfileand,undertheexisting#includeline,type

#includeresource.h
12. AccesstheMainFrm.hfileanddeclarethefollowingmethod:

#include"stdafx.h"
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()

virtual~CMainFrame()

afx_msgvoidClose()

DECLARE_MESSAGE_MAP()

private:

CMenu*pCurrentMenu
}
13. AccesstheMainFrm.cppfileandchangeitasfollows:

#include"MainFrm.h"
CMainFrame::CMainFrame()
{

...
}
CMainFrame::~CMainFrame()
{
}
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)

ON_COMMAND(IDM_FILE_EXIT,Close)
END_MESSAGE_MAP()
voidCMainFrame::Close()
{

PostQuitMessage(WM_QUIT)

PHP code
generator
Generate
PHP code for
any local or
remote
database.

}
14. Executetheapplicationtotestit

MovingaMenu
While or after creating your menu, you may find out that a menu category is in the wrong
sequenceoramenuitemisinthewrongposition.Youcanvisuallymoveeitheramenucategory
oramenuitem.
Tomenuamenucategory,clickanholdthemouseonit.Drageitherleftorrightinthedirection
of your choice. As you are moving it, a short vertical line with double arrows will follow and
guideyou.Oncetheverticallineispositionedwhereyouwantthemenucategorytobe,release
themouse.
Tomoveamenuitem,clickandholdyourmouseonit.Drageitherupordownwhereyouwant
topositionit.Whileyouaredragging,ahorizontallinewillguideyou.Oncethelineispositioned
whereyouwantthemenuitemotbe,releasethemouse.

MenuSeparators
Amenuseparatorisalinethatseparatestwogroupsofmenuitems.Itcanbeusedintwomain
ways.Itcansimplybeusedtosetapartdifferentgroups,or,aswewillseelateron,itcanassist
withimplementingthebehaviorofradiobuttonsinamenu.
Ifyouarevisuallycreatingamenu,tocreateaseparator,setthestringofamenuitemasand
press Enter. If you are programmatically creating a menu, to specify a separator, call the
CMenu::AppendMenu()method.PassthefirstargumentasMF_SEPARATOR,thesecondasNULL,
andthelastargumentas.Hereisanexample:
CMainFrame::CMainFrame()
{

Create(NULL,"MenusFundamentals")

VERIFY(this>m_wndMainMenu.CreateMenu())
VERIFY(this>m_wndFileMenu.CreateMenu())

this>m_wndFileMenu.AppendMenu(MF_STRING,22001,"New")
this>m_wndFileMenu.AppendMenu(MF_SEPARATOR,NULL,"")
this>m_wndFileMenu.AppendMenu(MF_STRING|MF_DISABLED,22004,"Exit")
this>m_wndMainMenu.AppendMenu(MF_POPUP,

reinterpret_cast<UINT_PTR>(this>m_wndFileMenu.m_hMenu),

"File")

this>SetMenu(&m_wndMainMenu)
Thiswouldproduce:

PracticalLearning:CreatingaMenuSeparator
1. IntheResourceView,doubleclickIDR_FIRST.Inthemenu,clickExit
2. PressIns(orInsertdependingonyourkeyboard
3. TypeandpressEnter
4. NoticethataseparatorwasaddedbetweenOpenandExit.
Saveall

MenuAlignment
Bydefault,whenyoucreateapopupmenuitem,itisalignedtotheleft.Ifitisthefirstgroup,it
would be positioned to the left of the menu bar. If you add another popup menu, it would be
positioned immediately to the right of the previous group. This alignment continues every time
you add a new popup menu. This alignment is to the left of the menu bar. Microsoft Windows

allows you to align one or more menu groups or menu items to the right. Based on this, if you
create a first popup menu, instead of aligning it to the left, you may prefer to position it to the
rightofthemenubar.Hereiswhatitwouldappearlike:

To specify the alignment of a menu item, if you are visually creating the menu, set the Help
property to True in the Properties window. If you are programmatically creating the menu,
bitwiseORtheMF_HELPflagtothefirstargument.Basedonthis,theabovemenuwascreated
asfollows:
CMainFrame::CMainFrame()
{

Create(NULL,"MenusFundamentals")

VERIFY(this>m_wndMainMenu.CreateMenu())
VERIFY(this>m_wndFileMenu.CreateMenu())
VERIFY(this>m_wndEditMenu.CreateMenu())
VERIFY(this>m_wndHelpMenu.CreateMenu())

this>m_wndFileMenu.AppendMenu(MF_STRING,22001,"New")
this>m_wndFileMenu.AppendMenu(MF_STRING,22002,"Open")
this>m_wndFileMenu.AppendMenu(MF_STRING,22003,"Save")
this>m_wndMainMenu.AppendMenu(MF_POPUP|MF_HELP,

reinterpret_cast<UINT_PTR>(this>m_wndFileMenu.m_hMenu),

"File")
this>SetMenu(&m_wndMainMenu)
Youcanalsopositiononeormorepopupmenustotheleftandoneormorepopupmenuitemsto
therightofthemenubar.Todothis,ifyouarevisuallycreatingthemenu,setthedesiredmenu
items Help property to True. That popup menu item and all toplevel menus positioned to the
rightofthatmenuwouldbepositionedtotheright.Ifyouareprogrammaticallycreatingamenu,
you can bitwiseOR one popup menu. That popup menu and all toplevel menu items created
afteritwouldbepositionedtotheright.Hereisanexample:

#include<afxwin.h>
classCExerciseApp:publicCWinApp
{
public:

virtualBOOLInitInstance()
}
classCMainFrame:publicCFrameWnd
{
public:

CMainFrame()
private:

CMenum_wndMainMenu

CMenum_wndFileMenu

CMenum_wndViewMenu

CMenum_wndEditMenu

CMenum_wndHelpMenu
}
CMainFrame::CMainFrame()
{

Create(NULL,"MenusFundamentals")

VERIFY(this>m_wndMainMenu.CreateMenu())
VERIFY(this>m_wndFileMenu.CreateMenu())
VERIFY(this>m_wndViewMenu.CreateMenu())
VERIFY(this>m_wndEditMenu.CreateMenu())

VERIFY(this>m_wndHelpMenu.CreateMenu())

this>m_wndFileMenu.AppendMenu(MF_STRING,22001,"New")
this>m_wndFileMenu.AppendMenu(MF_STRING,22002,"Open")
this>m_wndFileMenu.AppendMenu(MF_STRING,22003,"Save")
this>m_wndMainMenu.AppendMenu(MF_POPUP,

reinterpret_cast<UINT_PTR>(this>m_wndFileMenu.m_hMenu),

"File")

this>m_wndViewMenu.AppendMenu(MF_STRING,22002,"Toolbar")
this>m_wndViewMenu.AppendMenu(MF_STRING,22003,"StatusBar")
this>m_wndMainMenu.AppendMenu(MF_POPUP,

reinterpret_cast<UINT_PTR>(this>m_wndViewMenu.m_hMenu),

"View")

this>m_wndEditMenu.AppendMenu(MF_STRING,22004,"Cut")
this>m_wndEditMenu.AppendMenu(MF_STRING,22005,"Copy")
this>m_wndMainMenu.AppendMenu(MF_POPUP|MF_HELP,

reinterpret_cast<UINT_PTR>(this>m_wndEditMenu.m_hMenu),

"Edit")

this>m_wndHelpMenu.AppendMenu(MF_STRING,22005,

"AboutthisApplication")
this>m_wndMainMenu.AppendMenu(MF_POPUP,

reinterpret_cast<UINT_PTR>(this>m_wndHelpMenu.m_hMenu),

"Help")

this>SetMenu(&m_wndMainMenu)

BOOLCExerciseApp::InitInstance()
{

m_pMainWnd=newCMainFrame

m_pMainWnd>ShowWindow(SW_NORMAL)

returnTRUE

CExerciseApptheApp
Thiswouldproduce:

PracticalLearning:AligningaMenu
1. Onthemenu,clickFileandclicktheboxlabeledTypeHereontherightsideofFile
2. TypeHelpand,inthePropertieswindow,setitsHelpvaluetoTrue
3. ClicktheTypeHereboxunderHelpandtypeAbout
4. Saveall

ThePositionofaMenuItem
Whenwestudymenumaintenance,wewillseethatmanyroutineoperationsrequirethatyoube
abletolocateamenuitembeforetakingaction.Locatinganitemispossibleifyouconsiderthat
themenusitemarestoredina0basedlist.

Mnemonics
Ifyoulookatthemenuofmostapplications,oneletteroneverymenuisunderlinedallowingthe
userstoaccessthemenuwithoutusingthemouse.Thatmenushouldfirstreceivefocus,thisis
done by pressing Alt or F10, then eventually, the underlined letter of the menu that the user

wants to access. For example, if you press Alt, then F now, the File menu will open. Get in the
same good habit of accommodating your users. The mnemonics can be used anywhere in your
application,includingdialogboxes,comboboxes,checkboxes,radiobuttons,etc.So,getinthe
habitofusingthem.Theonesonthemenuwillbeusedifthemenuhasfocus(AltorF10).The
othersareavailableanytime.
Amnemoniciscreatedbyusingtheampersand&beforetheletteryoujudgeappropriate.Onthe
categories of a main menu, you should use a unique letter for each category Consider the main
menu of Microsoft Visual Studio. Only one F letter is underlined on the whole main menu, only
oneE,onlyoneV,etc.Programmerstendtoconsiderthefirstletterofeachtopmenu.Ifyouget
in a situation where two words start with the same letter, consider using the 2nd letter. For
example,ifyouhaveonecategorywithFileandanothercategorywithFormat,youcanapplythe
firstmnemonicontheFofFileandusetheoletteronFormat.
Sometimesyouwillgetinasituationwhereeitheryougetconfusedbecauseofsomuchmenuto
create,ortoomanyitemsthatneedmnemonics.InanycaseyoucanaskMicrosoftVisualStudio
to help you identify double mnemonics. To do this, rightclick a menu and select Check
Mnemonics.

Shortcuts
Ashortcutisanaction,similartothatofamenuitem,thatcanbeperformedbypressingoneor
acombinationofkeys.Forexample,toopentheStartmenuofMicrosoftWindows,youcanpress
Ctrl+Esc,toopentheSystemmenuofanyapplication,pressAlt+Space,tosaveadocument
onmost(ifnotall)Microsoftapplications,pressCtrl+S.,etc.Foratypicalprogram,youshould
provide a shortcut to your users for most menu actions performed on your application. As a
suggestion, observe other applications, such as a word processor. Many actions on such an
application have shortcuts even when the shortcut is not listed. It allows people who like
shortcuts to do their job faster, it also anticipates the situations when the mouse is behaving
badly.
PeoplewhouseMicrosoftWindowsandMicrosoftsoftwareproductsareusuallyfamiliarwithalot
of"universal"shortcutssuchasCtrl+C,Ctrl+V,Delete,etc.Youcanseesomeoftheseifyou
clickFileorEditonthemainmenu.Thoseareshortcutsthatareexplicitlyandreadilyavailable.
Othershortcuts,thoughcompletelyefficient,canalsobemadeavailable.
The easiest way to let users know about the shortcuts is by displaying them on the menu. For
exampleCtrl+N,Ctrl+C,etcarealreadydisplayedonthemenu.Toprovideashortcut,append\t
andtheshortcutcombinationintheCaptionofamenuitem.

MenuPrompts
The status bar can be used to display a message to the user about a menu item, like a small
detail.Hereisanexample,onthemainmenuofMicrosoftVisualStudio,clickProjectsfollowed
by a menu item and look at the Status Bar. While the menu is still opened, move the mouse to
another menu item and look at the Status Bar. When you have finished, press Esc twice to
dismissthemenu.
To specify the message that would be displayed on the status bar, when designing the menu,
clickamenuitemand,inthePropertieswindow,typeastringinthePromptfield.

C++ Static Analysis Tools


10th December 2014 - Free Webinar. Return on Investment for SA Tools.

Previous

Copyright20062007FunctionX,Inc.

Next

Agile Methodology Tool


Improve Agile Project Visibility & Predictability. Try Our Agile Tool!

DLLExplicitLoading

Introduction

Sofar,inordertousealibrary,whetherstaticorDLL,wemadesurewenewwherethelibrary
was located. In fact, we kept copying it in the directory where we created it and pasted in the
directory of the application that needed it. Suppose someone else or a certaincompanycreated
thelibraryanddistributedit,eitherwithMicrosoftWindowsortheDLLwasinstalledwithanother
application.Touse such a library, of course you can find it, copy it, and paste it in theproject
whereyouwanttouseit.IfmanyotherprogramsareaccessingsuchaDLL,therewouldbeno
needtocopyandpasteitlikethat.ThesetypesofDLLareinstalledintheWindowsdirectoryso
anyprogramthatneedsthemcanaccessthemfromthere.
As you can see, Microsoft Windows installed many DLLs in the Windows or Windows\System32
directory.Youtoo,whencreatingtheexecutable of your program, you can install the DLL there
soyouwouldknowwithcertaintywheretheDLLislocated.

PracticalLearning:CreatinganMFCStaticLibrary
1. Tostartanewapplication,opentheNewdialogbox(File>New...)and,intheProjects
propertypage,clickWin32DynamicLinkLibraries.IntheProjectNamebox,type
ExplicitDLL1andpressEnter
2. IntheWin32DynamicLinkLibraryStep1of1,makesuretheAnEmptyDLLProjectradio
buttonisselected.
ClickFinishthenclickOK
3. Toaddaheaderfile,onthemainmenu,clickFile>New
4. IntheNewdialogboxandintheFilespropertypage,clickC/C++HeaderFile
5. IntheNameeditbox,typestdafxandpressEnter
6. Intheemptyfile,typethefollowing:

#ifndefSTDAFX_H_
#defineSTDAFX_H_
#defineWIN32_LEAN_AND_MEAN//ExcluderarelyusedstufffromWindowsheaders
#include<windows.h>
#endif//STDAFX_H_
7. Toaddtheaccompanyingsourcefile,displaytheNewdialogboxandselectC++SourceFile
8. IntheNameeditbox,typestdafxandpressEnter
9. Intheemptyfile,typethefollowing:

#include"stdafx.h"
10. Toaddanewsourcefile,onthemainmenu,clickFile>New...
11. IntheNameeditbox,typeexo1andpressEnter
12. Intheemptyfile,typethefollowing:

#include"stdafx.h"
BOOLAPIENTRYDllMain(HANDLEhModule,
DWORDul_reason_for_call,
LPVOIDlpReserved)
{
returnTRUE
}
13. Toaddaheaderfile,onthemainmenu,clickFile>New
14. IntheNewdialogboxandintheFilespropertypage,clickC/C++HeaderFile

15. IntheNameeditbox,typeheadandpressEnter
16. Intheemptyfile,typethefollowing:

#pragmaonce
doubleGetNumber(doublen)
17. Toaddtheaccompanyingsourcefile,displaytheNewdialogboxandselectC++SourceFile
18. IntheNameeditbox,typeheadandpressEnter
19. Intheemptyfile,typethefollowing:

#include"stdafx.h"
#include"head.h"
doubleGetNumber(doubleNbr)
{

returnNbr*4.12
}
20. Toaddadefinitionfile,displaytheNewdialogboxagain
21. IntheFilespropertypage,clickTextFile
22. IntheNameeditbox,type"exo1.def"andpressEnter
23. Intheemptyfile,typethefollowing:

LIBRARYExplicitDLL1
EXPORTS

GetNumber
24. TocreatetheDLL,onthemainmenu,clickBuild>BuildExplicitDLL1.dll
25. OpenWindowsExplorerorMyComputerandlocatethefolderthatcontainstheabove
ExplicitDLL1projectthenopenitsDebugfolder
26. SelectandcopyboththeExplicitDLL1.dllandtheExplicitDLL1.libfiles
27. PastetheminyourWindows\System32folder

ExplicitLoadingaDLL
The technique of calling a DLL as we have proceeded so far is referred to as implicit loading
becauseweknewhowwecreatedtheDLLandweaddedittothedirectoryoftheapplicationwe
werecreating.ThisallowedustoaddtheDLLanditslibraryfiletotheprojectandfreedusfrom
remembering to call the DLL by its name. Another technique consists of calling the DLL by its
name.ThisisreferredtoasexplicitcallbecauseyouspecifythenameoftheDLLyouneedand
youdon'thavetocopyandpasteitinyourdirectoryandyoudon'thavetoaddittotheproject.
TocallaDLLexplicitly,
YoufirstcalltheLoadLibrary()function.Since/ifcreatinganMFCapplication,Microsoft
recommendsthatyouusetheAfxLoadLibrary()function
TousethefunctionyouneedfromtheDLL,calltheGetProcAddress()function
WhenyouhavefinishedusingtheDLL,youcancalltheFreeLibrary()function.Thistimetoo,
MicrosoftrecommendsusingtheAfxFreeLibrary()functioninstead.

PracticalLearning:LoadingaDLLExplicitly
1. Tostartanewapplication,displaytheNewdialogboxandclicktheProjectspropertypage
2. SelectMFCAppWizard(exe)
3. IntheNameeditbox,typeExplicitDLLTest1andpressEnter
4. IntheMFCAppWizardStep1,clickDialogBasedandclickFinishthenclickOK
5. DeletetheTODOlineonthedialogbox
6. AddanEditBoxcontroltothedialogboxandchangeitsIDtoIDC_NUMBER
7. Addanewbutton.ChangeitsIDtoIDC_GET_NUMBER_BTNandchangeitsCaptiontoGetNumber
8. AddanewEditBoxcontrolandchangeitsIDtoIDC_GETNUMBER

9. PressCtrl+WtoopenClassWizardandclicktheMemberVariablespropertypage
10. AddaCStringMemberVariablefortheIDC_GETNUMBERcontrolandnameitm_GetNumber
11. AddaCStringMemberVariablefortheIDC_NUMBERcontrolandnameitm_Number
12. ClicktheMessageMapstaband,intheClassNamecombobox,selectCExplicitDLLTest1Dlg.Inthe
ObjectIDslist,clickIDC_GET_NUMBER_BTN
13. IntheMessageslist,doubleclickBN_CLICKED.AcceptthesuggestednameofthefunctionandclickOK
14. ClickEditCodeandchangethefileasfollows:

//ExplicitDLLTest1Dlg.cpp:implementationfile
//
#include"stdafx.h"
#include"ExplicitDLLTest1.h"
#include"ExplicitDLLTest1Dlg.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__
#endif
typedefdouble(*LPGETNUMBER)(doubleNbr)
HINSTANCEhDLL=NULL
LPGETNUMBERlpGetNumber
...
/////////////////////////////////////////////////////////////////////////////
//CExplicitDLLTest1Dlgdialog
CExplicitDLLTest1Dlg::CExplicitDLLTest1Dlg(CWnd*pParent/*=NULL*/)

:CDialog(CExplicitDLLTest1Dlg::IDD,pParent)
{

//{{AFX_DATA_INIT(CExplicitDLLTest1Dlg)

m_GetNumber=_T("0")

m_Number=_T("1")

//}}AFX_DATA_INIT

//NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32

m_hIcon=AfxGetApp()>LoadIcon(IDR_MAINFRAME)
}
voidCExplicitDLLTest1Dlg::DoDataExchange(CDataExchange*pDX)
{

CDialog::DoDataExchange(pDX)

//{{AFX_DATA_MAP(CExplicitDLLTest1Dlg)

DDX_Text(pDX,IDC_GETNUMBER,m_GetNumber)

DDX_Text(pDX,IDC_NUMBER,m_Number)

//}}AFX_DATA_MAP

BEGIN_MESSAGE_MAP(CExplicitDLLTest1Dlg,CDialog)

//{{AFX_MSG_MAP(CExplicitDLLTest1Dlg)

ON_WM_SYSCOMMAND()

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()

ON_BN_CLICKED(IDC_GET_NUMBER_BTN,OnGetNumberBtn)

//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CExplicitDLLTest1Dlgmessagehandlers
BOOLCExplicitDLLTest1Dlg::OnInitDialog()
{

CDialog::OnInitDialog()

//Add"About..."menuitemtosystemmenu.

//IDM_ABOUTBOXmustbeinthesystemcommandrange.
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX)
ASSERT(IDM_ABOUTBOX<0xF000)

CMenu*pSysMenu=GetSystemMenu(FALSE)
if(pSysMenu!=NULL)
{

CStringstrAboutMenu

strAboutMenu.LoadString(IDS_ABOUTBOX)

if(!strAboutMenu.IsEmpty())

pSysMenu>AppendMenu(MF_SEPARATOR)

pSysMenu>AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu)

}
}

//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon

if(hDLL==NULL)

AfxMessageBox("CouldnotloadtheDLL")
else
{
lpGetNumber=(LPGETNUMBER)GetProcAddress(hDLL,"GetNumber")
}

returnTRUE//returnTRUEunlessyousetthefocustoacontrol

//TODO:Addextrainitializationhere
hDLL=AfxLoadLibrary("ExplicitDLL1")

...

voidCExplicitDLLTest1Dlg::OnGetNumberBtn()
{

//TODO:Addyourcontrolnotificationhandlercodehere

doubleNumber,GetNbr

UpdateData()

if(hDLL==NULL)
{

AfxMessageBox("CouldnotfindtheDLL")

return
}

Number=atof(m_Number)
GetNbr=lpGetNumber(Number)
m_GetNumber.Format("%.2f",GetNbr)

UpdateData(FALSE)

15. Testtheapplication:

16. Closethedialogbox

Previous

Copyright20042006FunctionX,Inc.

GDITopics:UsingaTrajectory

Introduction
A trajectory is a path along which an object
travels.Inoneexample,anobjectcouldgofrom
one point to another without coming back. In
another example, an object could go back and
forth from one object to another. The study or
implementation of trajectories is common in
graphics applications, in games, or other
simulationtypes.

PracticalLearning:
IntroducingTrajectories

1. Tostartthisexercise,createanMFCApplicationnamedTrajectory1
2. CreateitasaSingleDocumenttype
3. Tofillthewindow'scontentwithablackbackground,accessthesourcefileoftheviewand
changeitsOnDraweventasfollows:

voidCTrajectory1View::OnDraw(CDC*pDC)
{

CTrajectory1Doc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

//TODO:adddrawcodefornativedatahere
CBrushbrsBlack
CRectrctClient

brsBlack.CreateSolidBrush(RGB(0,0,0))

GetWindowRect(&rctClient)

CBrush*pOldBrush=pDC>SelectObject(&brsBlack)
pDC>Rectangle(0,0,rctClient.Width(),rctClient.Height())

pDC>SelectObject(pOldBrush)

4. Executetheapplicationtoseetheresult

MovingaShape
Theprimaryimplementationofusingatrajectoryconsistofmovinganobjectorashapealong
apath.Todothis,youcandrawtheshapeinresponsetoatimer.

PracticalLearning:MovingaShape
1. UsingtheResourceSymbolsdialogbox,createanIDnamedIDT_MOVE
2. GeneratetheOnInitialUpdateeventfortheviewclassanduseittoinitializethetimeras
follows:

voidCTrajectory1View::OnInitialUpdate()
{

CView::OnInitialUpdate()

SetTimer(IDT_MOVE,10,NULL)

//TODO:Addyourspecializedcodehereand/orcallthebaseclass

3. Intheviewheaderfile,declarethefollowingvariables:

//Trajectory1View.h:interfaceoftheCTrajectory1Viewclass
//
#pragmaonce
classCTrajectory1View:publicCView
{
protected://createfromserializationonly

CTrajectory1View()

DECLARE_DYNCREATE(CTrajectory1View)
//Attributes
public:

CTrajectory1Doc*GetDocument()const
//Operations
public:

staticconstintShapeWidth=45

staticconstintShapeHeight=15

intx

inty

boolMovingRight
//Overrides
public:

virtualvoidOnDraw(CDC*pDC)//overriddentodrawthisview

virtualBOOLPreCreateWindow(CREATESTRUCT&cs)
protected:

virtualBOOLOnPreparePrinting(CPrintInfo*pInfo)

virtualvoidOnBeginPrinting(CDC*pDC,CPrintInfo*pInfo)

virtualvoidOnEndPrinting(CDC*pDC,CPrintInfo*pInfo)
//Implementation
public:

virtual~CTrajectory1View()
#ifdef_DEBUG

virtualvoidAssertValid()const

virtualvoidDump(CDumpContext&dc)const
#endif
protected:
//Generatedmessagemapfunctions
protected:

DECLARE_MESSAGE_MAP()
}
#ifndef_DEBUG//debugversioninTrajectory1View.cpp
inlineCTrajectory1Doc*CTrajectory1View::GetDocument()const
{returnreinterpret_cast<CTrajectory1Doc*>(m_pDocument)}
#endif
4. Intheconstructoroftheviewclass,initializethevariablesasfollows:

CTrajectory1View::CTrajectory1View()
{

//TODO:addconstructioncodehere

x=0

y=200

MovingRight=false
}
5. ChangetheOnDraweventasfollows:

voidCTrajectory1View::OnDraw(CDC*pDC)
{

CTrajectory1Doc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

//TODO:adddrawcodefornativedatahere
CPenpenYellow
CBrushbrsBlack,brsFuchsia
CRectrctClient

brsBlack.CreateSolidBrush(RGB(0,0,0))
brsFuchsia.CreateSolidBrush(RGB(255,0,255))
penYellow.CreatePen(PS_SOLID,1,RGB(255,255,0))

GetWindowRect(&rctClient)

CBrush*pOldBrush=pDC>SelectObject(&brsBlack)
pDC>Rectangle(0,0,rctClient.Width(),rctClient.Height())

pOldBrush=pDC>SelectObject(&brsFuchsia)
CPen*pOldPen=pDC>SelectObject(&penYellow)
pDC>RoundRect(this>x,this>y,this>x+ShapeWidth,

this>y+ShapeHeight,5,5)

pDC>SelectObject(pOldPen)
pDC>SelectObject(pOldBrush)

6. GeneratetheeventoftheWM_TIMERmessagefortheviewclassandimplementitas
follows:

voidCTrajectory1View::OnTimer(UINT_PTRnIDEvent)
{

//TODO:Addyourmessagehandlercodehereand/orcalldefault

CRectrctClient

GetWindowRect(&rctClient)

if(this>x<0)
{

this>x=0

this>MovingRight=true
}

if(this>x>rctClient.Width()ShapeWidth)
{

this>x=rctClient.Width()ShapeWidth

this>MovingRight=FALSE
}

if(x<0)
{

x=0

MovingRight=TRUE
}

if(x>rctClient.Width()ShapeWidth)
{

x=rctClient.Width()ShapeWidth

MovingRight=FALSE
}

Invalidate()

if(MovingRight==TRUE)

x++
else

CView::OnTimer(nIDEvent)

7. GeneratetheeventoftheWM_ERASEBKGNDmessageoftheviewclassandchangeits
returnvalueasfollows:

BOOLCTrajectory1View::OnEraseBkgnd(CDC*pDC)
{

//TODO:Addyourmessagehandlercodehereand/orcalldefault

returnTRUE//CView::OnEraseBkgnd(pDC)

8. Executetheapplicationtoseetheresult:

PHP code
generator
9. CloseitandreturntoMSVC

CreatingaShapeClass
Objectorientedprogrammingconsistsofcreatingobjectsthateachcanperformaspecifictask
and take of assignments related to it. In trajectoryrelated programming, you can create a
class for each object or shape. This can make it easy to recognize and use the object. If you
happentousedifferentobjects,youcanthencustomizethebehaviorofeach.

PracticalLearning:CreatingaShapeClass
1. Tocreateanewclass,onthemainmenu,clickProject>AddClass...
2. IntheTemplateslist,clickC++ClassandclickAdd
3. SettheClassNametoCShapeandpressEnter
4. Changetheheaderfileasfollows:

#pragmaonce
classCShape
{
public:

CShape(void)
public:

~CShape(void)

staticconstintWidth=45
staticconstintHeight=15
intx
inty
boolMovingRight

voidDraw(CDC*pDC)
voidMove(CRectrctClient)

5. Changethesourcefileasfollows:

#include"StdAfx.h"
#include"Shape.h"
CShape::CShape(void)

:x(0),

y(150),

Generate
PHP code
for any local
or remote
database.


{
}

MovingRight(false)

CShape::~CShape(void)
{
}
voidCShape::Draw(CDC*pDC)
{

CPenpenYellow

CBrushbrsFuchsia

brsFuchsia.CreateSolidBrush(RGB(255,0,255))
penYellow.CreatePen(PS_SOLID,1,RGB(255,255,0))

CBrush*pOldBrush=pDC>SelectObject(&brsFuchsia)
CPen*pOldPen=pDC>SelectObject(&penYellow)
pDC>RoundRect(this>x,

this>y,

this>x+CShape::Width,

this>y+CShape::Height,

5,

5)

pDC>SelectObject(pOldBrush)

voidCShape::Move(CRectrctClient)
{

if(this>x<0)

this>x=0

this>MovingRight=true

if(this>x>rctClient.Width()CShape::Width)
{

this>x=rctClient.Width()CShape::Width

this>MovingRight=FALSE
}

6. Accesstheheaderfileoftheviewclassandchangeitasfollows:

//Trajectory2View.h:interfaceoftheCTrajectory1Viewclass
//
#pragmaonce
#include"Shape.h"
classCTrajectory1View:publicCView
{
protected://createfromserializationonly

CTrajectory1View()

DECLARE_DYNCREATE(CTrajectory1View)
//Attributes
public:

CTrajectory1Doc*GetDocument()const
//Operations
public:

CShape*shape
//Overrides
public:

...
}
#ifndef_DEBUG//debugversioninTrajectory2View.cpp
inlineCTrajectory1Doc*CTrajectory1View::GetDocument()const
{returnreinterpret_cast<CTrajectory1Doc*>(m_pDocument)}
#endif
7. Accessthesourcefileoftheviewclassandchangeitasfollows:


//Trajectory2View.cpp:implementationoftheCTrajectory1Viewclass
//
#include"stdafx.h"
#include"Trajectory2.h"
#include"Trajectory2Doc.h"
#include"Trajectory2View.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#endif
//CTrajectory1View
IMPLEMENT_DYNCREATE(CTrajectory1View,CView)
BEGIN_MESSAGE_MAP(CTrajectory1View,CView)

//Standardprintingcommands

ON_COMMAND(ID_FILE_PRINT,&CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_DIRECT,&CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_PREVIEW,&CView::OnFilePrintPreview)

ON_WM_TIMER()

ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
//CTrajectory1Viewconstruction/destruction
CTrajectory1View::CTrajectory1View()
{

//TODO:addconstructioncodehere

shape=newCShape
}
CTrajectory1View::~CTrajectory1View()
{

deleteshape
}
BOOLCTrajectory1View::PreCreateWindow(CREATESTRUCT&cs)
{

//TODO:ModifytheWindowclassorstylesherebymodifying

//theCREATESTRUCTcs

returnCView::PreCreateWindow(cs)

//CTrajectory1Viewdrawing
voidCTrajectory1View::OnDraw(CDC*pDC)
{

CTrajectory1Doc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

//TODO:adddrawcodefornativedatahere
CPenpenYellow
CBrushbrsBlack,brsFuchsia
CRectrctClient

brsBlack.CreateSolidBrush(RGB(0,0,0))
brsFuchsia.CreateSolidBrush(RGB(255,0,255))
penYellow.CreatePen(PS_SOLID,1,RGB(255,255,0))

GetWindowRect(&rctClient)

CBrush*pOldBrush=pDC>SelectObject(&brsBlack)
pDC>Rectangle(0,0,rctClient.Width(),rctClient.Height())

shape>Draw(pDC)

pDC>SelectObject(pOldBrush)

...
//CTrajectory1Viewmessagehandlers
voidCTrajectory1View::OnTimer(UINT_PTRnIDEvent)
{

//TODO:Addyourmessagehandlercodehereand/orcalldefault

CRectrctClient

GetWindowRect(&rctClient)
shape>Move(rctClient)

Invalidate()

if(shape>MovingRight==TRUE)

shape>x++
else

shape>x

CView::OnTimer(nIDEvent)

voidCTrajectory1View::OnInitialUpdate()
{

CView::OnInitialUpdate()

SetTimer(IDT_MOVE,10,NULL)
//TODO:Addyourspecializedcodehereand/orcallthebaseclass

BOOLCTrajectory1View::OnEraseBkgnd(CDC*pDC)
{

//TODO:Addyourmessagehandlercodehereand/orcalldefault

returnTRUE//CView::OnEraseBkgnd(pDC)

8. Executetheapplicationandnoticethatitproducesthesameresult

FastReport VCL
for Delphi/CB 5-XE6 Fast. Compact. Feature-rich.

Home

Copyright2006FunctionX,Inc.

Next

GDITopics:UsingaTrajectory

ChangingTrajectories
In some programming assignments, you may
need to show the trajectory of an item, such as
aperson,ananimal,acar,anairplane,atrain,
etc.Thereisnostrictaboutwheretostart.Still,
you would need to recognize and identify how
the trajectory would be traced. We will
implementasimpleexampleofacarmovingon
aroad.Forsimplicity,ononlywillweassumea
straight road, but also we will not deal with
conflicts(suchascollision(detection)).

PracticalLearning:
IntroducingTrajectories

1. Tostartthisexercise,createanMFCApplicationnamedTrajectory2
2. CreateitasaSingleDocumenttype
3. OpenMicrosoftPaint.Createapicturethathastheshapeoftrajectoryyouwillneed

4. SaveitasMapintheresfolderoftheTrajectory1projectyoucreated

5. Importthispictureinyourproject(Project>AddResource...,Import...)
6. SetitsIDtoIDB_MAP
7. Saveall

TracingaTrajectory
To trace the trajectory of an object, you should determine where it would start and where it
wouldstop.Forourexample,wewillhaveacarthatstartontheleftsectionofaview.When
itgetstotherightextreme,wewillsimplychangeitsdirectionandmoveitopposite.

PracticalLearning:TracingaTrajectory
1. UsingtheResourceSymbolsdialogbox,createanIDnamedIDT_MOVE
2. Intheviewheaderfile,declarethefollowingvariables:

//Trajectory2View.h:interfaceoftheCTrajectory1Viewclass
//
#pragmaonce
classCTrajectory2View:publicCView
{
protected://createfromserializationonly

CTrajectory2View()

DECLARE_DYNCREATE(CTrajectory2View)
//Attributes
public:

CTrajectory2Doc*GetDocument()const
//Operations
public:
//Overrides
public:

virtualvoidOnDraw(CDC*pDC)//overriddentodrawthisview

virtualBOOLPreCreateWindow(CREATESTRUCT&cs)
protected:

virtualBOOLOnPreparePrinting(CPrintInfo*pInfo)

virtualvoidOnBeginPrinting(CDC*pDC,CPrintInfo*pInfo)

virtualvoidOnEndPrinting(CDC*pDC,CPrintInfo*pInfo)
//Implementation
public:

virtual~CTrajectory1View()
#ifdef_DEBUG

virtualvoidAssertValid()const

virtualvoidDump(CDumpContext&dc)const
#endif
protected:
//Generatedmessagemapfunctions
protected:

DECLARE_MESSAGE_MAP()
private:

staticconstintBusWidth=45

staticconstintBusHeight=15

intxBus
intyBus
intwBus
inthBus
BOOLBusMovingRight

#ifndef_DEBUG//debugversioninTrajectory1View.cpp
inlineCTrajectory2Doc*CTrajectory2View::GetDocument()const
{returnreinterpret_cast<CTrajectory1Doc*>(m_pDocument)}
#endif

3. Intheconstructoroftheviewclass,initializethevariablesasfollows:

CTrajectory2View::CTrajectory1View()
{

//TODO:addconstructioncodehere

xBus=60

yBus=180

wBus=xBus+BusWidth

hBus=yBus+BusHeight

BusMovingRight=TRUE
}
4. GeneratetheOnInitialUpdateeventfortheviewclassanduseittoinitializethetimeras
follows:

voidCTrajectory2View::OnInitialUpdate()
{

CView::OnInitialUpdate()

//TODO:Addyourspecializedcodehereand/orcallthebaseclass
SetTimer(IDT_MOVE,10,NULL)

5. ChangetheOnDraweventasfollows:

voidCTrajectory2View::OnDraw(CDC*pDC)
{

CTrajectory2Doc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

//TODO:adddrawcodefornativedatahere
CBitmapbmpMap
CDCmdcMap
CBrushbrsOrange,*brsOld

bmpMap.LoadBitmap(IDB_MAP)
mdcMap.CreateCompatibleDC(pDC)
CBitmap*bmpOld=mdcMap.SelectObject(&bmpMap)

pDC>BitBlt(0,0,692,586,&mdcMap,0,0,SRCCOPY)

brsOrange.CreateSolidBrush(RGB(240,155,50))
brsOld=pDC>SelectObject(&brsOrange)
pDC>RoundRect(xBus,yBus,xBus+BusWidth,yBus+BusHeight,5,5)
pDC>SelectObject(bmpOld)

6. GeneratetheeventoftheWM_TIMERmessagefortheviewclassandimplementitas
follows:

voidCTrajectory2View::OnTimer(UINT_PTRnIDEvent)
{

//TODO:Addyourmessagehandlercodehereand/orcalldefault

if(xBus<0)

xBus=0

yBus=180

BusMovingRight=TRUE

if(xBus>645)

xBus=645

yBus=150

BusMovingRight=FALSE

Invalidate()

if(BusMovingRight==TRUE)

xBus++
else

xBus

CView::OnTimer(nIDEvent)

7. GeneratetheeventoftheWM_ERASEBKGNDmessageoftheviewclassandchangeits
returnvalueasfollows:

BOOLCTrajectory2View::OnEraseBkgnd(CDC*pDC)
{

//TODO:Addyourmessagehandlercodehereand/orcalldefault

returnTRUE//CView::OnEraseBkgnd(pDC)

8. ChangetheOnCreateandthePreCreateWindoweventsoftheframeclassasfollows:

intCMainFrame::OnCreate(LPCREATESTRUCTlpCreateStruct)
{

if(CFrameWnd::OnCreate(lpCreateStruct)==1)

return1

if(!m_wndToolBar.CreateEx(this,

TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP

|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|

CBRS_SIZE_DYNAMIC)||

!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

TRACE0("Failedtocreatetoolbar\n")

return1//failtocreate

if(!m_wndStatusBar.Create(this)||

!m_wndStatusBar.SetIndicators(indicators,

sizeof(indicators)/sizeof(UINT)))
{

TRACE0("Failedtocreatestatusbar\n")

return1//failtocreate
}

//TODO:Deletethesethreelinesifyoudon't
//wantthetoolbartobedockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY)
EnableDocking(CBRS_ALIGN_ANY)
DockControlBar(&m_wndToolBar)

CenterWindow()
SetWindowText(TEXT("TrajectoryRecognition"))

return0

BOOLCMainFrame::PreCreateWindow(CREATESTRUCT&cs)
{

if(!CFrameWnd::PreCreateWindow(cs))

returnFALSE

//TODO:ModifytheWindowclassorstylesherebymodifying

//theCREATESTRUCTcs

cs.cx=700

cs.cy=590

cs.style&=~FWS_ADDTOTITLE

returnTRUE

9. Executetheapplicationagaintoseetheresult

10. Closetheapplication

UsingMoreThanoneTrajectory
Most simulations and trajectory assignments use more than one object. This also means that
you would deal with more than one object and probably more than one trajectory. Here is a
simpleexampleofhowyoumayaddressthisproblem.

PracticalLearning:UsingTwoTrajectories
1. Changetheheaderfileoftheviewclassasfollows:

//Trajectory2View.h:interfaceoftheCTrajectory1Viewclass
//
#pragmaonce
classCTrajectory2View:publicCView
{
protected://createfromserializationonly

CTrajectory2View()

DECLARE_DYNCREATE(CTrajectory2View)
//Attributes
public:

CTrajectory1Doc*GetDocument()const
//Operations
public:
//Overrides
public:

virtualvoidOnDraw(CDC*pDC)//overriddentodrawthisview

virtualBOOLPreCreateWindow(CREATESTRUCT&cs)
protected:

virtualBOOLOnPreparePrinting(CPrintInfo*pInfo)

virtualvoidOnBeginPrinting(CDC*pDC,CPrintInfo*pInfo)

virtualvoidOnEndPrinting(CDC*pDC,CPrintInfo*pInfo)
//Implementation
public:

virtual~CTrajectory1View()
#ifdef_DEBUG

virtualvoidAssertValid()const

virtualvoidDump(CDumpContext&dc)const

#endif
protected:
//Generatedmessagemapfunctions
protected:

DECLARE_MESSAGE_MAP()
private:

staticconstintBusWidth=45

staticconstintBusHeight=15

staticconstintCarWidth=15

staticconstintCarHeight=30

intxBus
intyBus
intwBus
inthBus
BOOLBusMovingRight

virtualvoidOnInitialUpdate()
afx_msgvoidOnTimer(UINT_PTRnIDEvent)
afx_msgBOOLOnEraseBkgnd(CDC*pDC)

intxCar
intyCar
intwCar
inthCar
BOOLCarMovingDown

#ifndef_DEBUG//debugversioninTrajectory1View.cpp
inlineCTrajectory1Doc*CTrajectory2View::GetDocument()const
{returnreinterpret_cast<CTrajectory2Doc*>(m_pDocument)}
#endif
2. Changethesourcefileoftheviewasfollows:

//Trajectory2View.cpp:implementationoftheCTrajectory1Viewclass
//
#include"stdafx.h"
#include"Trajectory2.h"
#include"Trajectory2Doc.h"
#include"Trajectory2View.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#endif
//CTrajectory1View
IMPLEMENT_DYNCREATE(CTrajectory2View,CView)
BEGIN_MESSAGE_MAP(CTrajectory1View,CView)

//Standardprintingcommands

ON_COMMAND(ID_FILE_PRINT,&CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_DIRECT,&CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_PREVIEW,&CView::OnFilePrintPreview)

ON_WM_TIMER()

ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
//CTrajectory2Viewconstruction/destruction
CTrajectory2View::CTrajectory2View()
{

//TODO:addconstructioncodehere

xBus=60

yBus=180

wBus=xBus+BusWidth

hBus=yBus+BusHeight

BusMovingRight=TRUE

xCar=330

PHP code
generator
Generate PHP code for
any database.
AJAX,charts,dynamic
forms and more

yCar=100
wCar=CarWidth
hCar=yCar+CarHeight
CarMovingDown=TRUE

CTrajectory2View::~CTrajectory2View()
{
}
BOOLCTrajectory2View::PreCreateWindow(CREATESTRUCT&cs)
{

//TODO:ModifytheWindowclassorstylesherebymodifying

//theCREATESTRUCTcs

returnCView::PreCreateWindow(cs)

//CTrajectory2Viewdrawing
voidCTrajectory2View::OnDraw(CDC*pDC)
{

CTrajectory2Doc*pDoc=GetDocument()

ASSERT_VALID(pDoc)

if(!pDoc)

return

//TODO:adddrawcodefornativedatahere
CBitmapbmpMap
CDCmdcMap
CBrushbrsOrange,brsBlue,*brsOld

bmpMap.LoadBitmap(IDB_MAP)
mdcMap.CreateCompatibleDC(pDC)
CBitmap*bmpOld=mdcMap.SelectObject(&bmpMap)

pDC>BitBlt(0,0,692,586,&mdcMap,0,0,SRCCOPY)

brsOrange.CreateSolidBrush(RGB(240,155,50))
brsOld=pDC>SelectObject(&brsOrange)
pDC>RoundRect(xBus,yBus,xBus+BusWidth,yBus+BusHeight,5,5)
brsBlue.CreateSolidBrush(RGB(0,150,250))
brsOld=pDC>SelectObject(&brsBlue)
pDC>RoundRect(xCar,yCar,xCar+CarWidth,yCar+CarHeight,5,5)
pDC>SelectObject(bmpOld)

...
voidCTrajectory2View::OnInitialUpdate()
{

CView::OnInitialUpdate()

//TODO:Addyourspecializedcodehereand/orcallthebaseclass
SetTimer(IDT_MOVE,10,NULL)

voidCTrajectory2View::OnTimer(UINT_PTRnIDEvent)
{

//TODO:Addyourmessagehandlercodehereand/orcalldefault

if(xBus<0)

xBus=0

yBus=180

BusMovingRight=TRUE

if(xBus>645)

xBus=645

yBus=150

BusMovingRight=FALSE

if(yCar<0)

xCar=330

yCar=0

CarMovingDown=TRUE
}
if(yCar>500)
{

xCar=370

yCar=500

CarMovingDown=FALSE
}

Invalidate()

if(BusMovingRight==TRUE)

xBus++
else

xBus

if(CarMovingDown==TRUE)

yCar++
else

yCar

CView::OnTimer(nIDEvent)

BOOLCTrajectory2View::OnEraseBkgnd(CDC*pDC)
{

//TODO:Addyourmessagehandlercodehereand/orcalldefault

returnTRUE//CView::OnEraseBkgnd(pDC)

3. Executetheapplicationagaintoseetheresult

4. Runtheapplicationlongenoughtohavebothcarscollide

5. Closetheapplication

SQLServerDataEntry

CreatingaTable
In order to use this lesson, you should
be familiar with Microsoft SQL Server
as we have covered it already. We
will use SQL to create our table for
dataentry.

1. StartMicrosoftSQLServerandopentheSQLQueryAnalyzer.
2. Intheemptyquerywindow,typeandexecutethefollowingcommand(youexecutethecommandbypressingF5):

CREATEDATABASELiquorStore
3. Afterdatabasehasbeencreatedandyoureceiveconfirmation,deletethepreviousline
4. typeandexecutethefollowinginstructionsthatcreateatableandentersfourrecords:

USELiquorStore
CREATETABLEEmployees
(
EmployeeIDINTIDENTITY(1,1)NOTNULL,
EmployeeNoCHAR(6)NULL,
DateHiredVARCHAR(40)NULL,
FirstNameVARCHAR(20)NULL,
MICHAR(1)NULL,
LastNameVARCHAR(20)NULL,
AddressVARCHAR(40)NULL,
CityVARCHAR(32)NULL,
StateCHAR(2)NULL,
ZIPCodeVARCHAR(12)NULL,
CountryVARCHAR(30)NULL,
Salary
MONEYNULL,
HomePhone VARCHAR(16)NULL,
EmailAddressVARCHAR(40)NULL,
MaritalStatusBITNULL,
Notes
TextNULL
)
/*DataEntry*/
FirstRecord
INSERTINTOEmployees(EmployeeNo,DateHired,FirstName,MI,LastName,Address,City,

State,ZIPCode,Country,Salary,HomePhone,EmailAddress,MaritalStatus)
VALUES('GT882','10/05/1995','Geraldine','F','Thomas','802EpsilonAve',
'SilverSpring','MD','20904','USA',12.55,'(301)5247822','gthomas@hotmail.com',1)
SecondRecord
INSERTEmployees(EmployeeNo,DateHired,FirstName,MI,LastName,Address,City,

State,ZIPCode,Country,Salary,HomePhone,EmailAddress,MaritalStatus)
VALUES('EB405','8221996','Ernest','','Bilong','1060CalistoRd#D12',
'Alexandria','VA','222311244','USA',8.72,'(703)2768676','ebilong@yahoo.com',0)
ThirdRecord
INSERTEmployees(EmployeeNo,DateHired,FirstName,MI,LastName,Address,City,

State,ZIPCode,Country,Salary,HomePhone,EmailAddress,MaritalStatus)
VALUES('DJ614',8/22/1996,'James','D','Datts','','','DC','','USA',10.18,
'','dattsj@netscape.com',1)
FourthRecord
INSERTEmployees(EmployeeNo,DateHired,FirstName,MI,LastName,Address,City,

State,ZIPCode,Country,Salary,HomePhone,EmailAddress,MaritalStatus)
VALUES('BC200',4/15/1998,'Catherine','','Bollack','12442LockwoodDrive',
'Rockville','MD','','USA',10.44,'','bollackc1288@csumd.edu',1)
5. CloseSQLQueryAnalyzer.
6. Whenaskedwhetheryouwanttosavethetext,clickYes.
7. ChangethenameofthefiletoLiquorStoreandmakesurethatadesiredfolder,suchasMyDocuments,is
selectedintheSaveIncombobox.ClickSave.

CreatinganODBCDataSource
Herearethestepstocreatetheneededdatasource:
1. StartoropenControlPaneland,inControlPanel,doubleclickAdministrativeTools.
2. IntheAdministrativeToolswindow,doubleclickDataSources(ODBC).Alternatively,
fromtheTaskbar,youcouldhaveclickedStart>Programs>AdministrativeTools>
DataSources(ODBC).
3. IntheODBCDataSourceAdministratorpropertysheet,clicktheAddbutton:

4. IntheCreateNewDataSourcewizard,scrolldowninthelistboxandclickSQL
Server:

5. ClickFinish
6. IntheNameeditboxoftheCreateANewDataSourceToSQLServerwizard,type
LiqStoreandpressTab
7. IntheDescriptioneditbox,typeTheLiquorStoreApplication
8. ClickthearrowoftheServercomboboxandselecttheserverwheretheabove
(LiquorStore)databaseresides:

9. ClickNext
10. Selectthedesiredauthentication.Forthisexample,IaccepttheWindowsNT
Authentication.IalsoaccepttoconnecttoSQLServerwithDefaultSettingsbyleaving
thecheckboxuntouched:

11. ClickNext
12. InthenewpageoftheCreateANewDataSourceToSQLServerwizard,clicktheChange
TheDefaultDatabaseTocheckbox.
13. Oncethecomboboxisenabled,clickitsarrowandselectLiquorStore:

14. Forthisexample,leavetheAttachDatabaseFileNamecheckboxuncheckedandaccept
theotherdefaults.ClickNext
15. Unlessyouhaveanyotherreason,acceptthedefault(language,encryption,etc)settings
ofthenewpage:

16. ClickFinish
17. OntheODBCMicrosoftSQLServerSetupdialogbox,clicktheTestDataSourcebutton:

18. WhentheSQLServerODBCDataSourceTestdialogboxconfirmsthattheTESTS
COMPLETEDSUCCESSFULLY!,clickOK:

19. OntheODBCMicrosoftSQLServerSetupdialogbox,clickOK.
20. IntheUserDSNpropertypageoftheODBCDataSourceAdministratordialogbox,make
surethattheLiqStoredatastoreislistedintheUserDataSourceslistbox:

21. ClickOK

CreatingtheApplication
1. StartMicrosoftVisualC++
2. Onthemainmenu,clickFile>New
3. IntheNewdialogbox,clickProjectsandclickMFCAppWizard(exe)
4. IntheLocationeditbox,selectortypethedesiredfolderfortheapplication.IntheProject
Nameeditbox,typeLiqStoreDBandclickOK
5. IntheMFCAppWizardStep1dialogbox,clicktheSingleDocumentradiobuttonand
clickNext
6. IntheMFCAppWizardStep2of6,clicktheDatabaseViewWithoutFileSupport
(becausewewillnotneedandwillnotusefilesupportforthisexercise).
7. ClicktheDataSourcebutton.
8. IntheDatabaseOptionsdialogbox,intheDatasourcesection,makesuretheODBC
radiobuttonisselectedandclickthearrowofitscombobox.SelectLiqStore
9. IntheRecordsetTypesection,clicktheDynasetradiobutton

10. ClickOK

11. IntheSelectDatabaseTables,clickdbo.EmployeesandclickOK
12. IntheMFCAppWizardStep2of6,clickNext
13. IntheMFCAppWizardStep3of6,acceptalldefaultsandclickNext
14. IntheMFCAppWizardStep4of6,uncheckthePrintingAndPrintPreviewcheckbox
15. ClicktheAdvancedbuttonandclicktheWindowStylespropertypage.Uncheckthe
MaximizeBoxcheckboxandclickClose
16. ClickNext
17. IntheMFCAppWizardStep5of6,acceptalldefaultsandclickNext
18. IntheMFCAppWizardStep6of6,acceptalldefaultsandclickFinish.
19. IntheNewProjectInformationdialogbox,clickOK.
20. IntheWorkspace,clicktheResourceViewtab,expandtheStringTable,anddoubleclick
StringTable.DoubleclickIDR_MAINFRAMEandreplaceitsentireCaptionwithFour
CornerLiquorStoreEmployeesRecordsandclosethefloatingwindow.Alsoclose
theStringTablewindow.
21. UsingtheControlswindow,designformasfollows:

22. SettheIDsoftheeditcontrolsasfollows:IDC_EMPLOYEEID(ReadOnly),
IDC_EMPLOYEENBR,IDC_DATEHIRED,IDC_FIRSTNAME,IDC_MI,IDC_LASTNAME,
IDC_ADDRESS,IDC_CITY,IDC_STATE,IDC_ZIPCODE,IDC_COUNTRY,
IDC_SALARY,IDC_EMAILADDRESS,IDC_HOMEPHONE,andIDC_NOTES(Multiline,
VerticalScroll,WantReturn).ChangetheIDofthecheckboxtoIDC_MARITALSTATUS,
23. Saveeverything.
24. IntheWorkspace,clickClassViewtab.ExpandtheLiqStoreDBclassesnodeanddouble
clickCLiqStoreDBSet.NoticethattheCRecordsetclassalreadyhasvariablesdeclaredfor
eachcontrolofourform.
25. Toassociateeachcontrolwiththeappropriatevariable,onthemainmenu,clickView>
ClassWizard...
26. IntheMFCClassWizarddialogbox,clicktheMemberVariablespropertysheet.Inthe
ClassNamecombobox,selectCLiqStoreDBView.
27. Inthelistbox,doubleclickIDC_ADDRESS
28. IntheAddMemberVariabledialogbox,clickthearrowoftheMemberVariableName
comboboxandselectm_pSet>m_Address:

29. MakesurethattheVariableTypeissettoCStringandclickOK
30. Dothesamefortheothercontrols:

31. OntheMFCClassWizard,clickOK
32. Testtheapplication

33. Closetheapplication
Asyoucansee,thisdatabasewascreatedwithoutasinglelineofcode.

AddingaRecord
1. IntheWorkspace,clicktheResourceViewtab.ExpandtheLiqStoreDBResourcetreeandexpandthe
Menunode.
2. DoubleclickIDR_MAINFRAMEandaddanAddmenuitem:

3. AddabuttononthetoolbarandassociatetoitthesameidentifierastheAddmenuitem:

4. PressCtrl+WtoaccesstheClassWizard.
5. IntheClassNamecombobox,selectCLiqStoreDBViewand,intheObjectIDslistbox,select
ID_RECORD_ADD
6. IntheMessageslistbox,doubleclickCOMMAND
7. AcceptthesuggestednameofthefunctionandclickEditCode
8. Implementthefunctionasfollows:

voidCLiqStoreDBView::OnRecordAdd()
{

SetDlgItemText(IDC_EMPLOYEEID,"")

SetDlgItemText(IDC_EMPLOYEENBR,"")

SetDlgItemText(IDC_DATEHIRED,"")

SetDlgItemText(IDC_FIRSTNAME,"")

SetDlgItemText(IDC_MI,"")

SetDlgItemText(IDC_LASTNAME,"")

SetDlgItemText(IDC_ADDRESS,"")

SetDlgItemText(IDC_CITY,"")
SetDlgItemText(IDC_STATE,"")
SetDlgItemText(IDC_ZIPCODE,"")
SetDlgItemText(IDC_COUNTRY,"")
SetDlgItemText(IDC_SALARY,"")
SetDlgItemText(IDC_EMAILADDRESS,"")
SetDlgItemText(IDC_HOMEPHONE,"")
SetDlgItemText(IDC_NOTES,"")

reinterpret_cast<CButton*>(GetDlgItem(IDC_MARITALSTATUS))>SetCheck(FALSE)
m_pSet>AddNew()
m_pSet>Update()
m_pSet>Requery()

9. TesttheapplicationandreturntoMSVC

DeletingaRecord
1. AddaDeletemenuitem:

2. Onthetoolbar,addabuttonthathasthesameidentifierastheDeletemenuitem:

3. ImplementitsCOMMANDfunctionasfollows:


voidCLiqStoreDBView::OnRecordDelete()
{

m_pSet>Delete()

m_pSet>MoveNext()

if(m_pSet>IsEOF())

m_pSet>MoveLast()
}
4. Testtheapplication

Copyright20032005FunctionX,Inc.

WindowsControls:TheAnimation
Control

IntroductiontotheAnimationControl

Overview

AnimationVideo
AnimationClass
AnimationFlash

Ananimationisaseriesofpicturesputtogethertoproduceavideo
clip.Itcanbeusedtodisplaytheevolutionofanongoingtasktothe
user. This makes such tasks less boring. For example, making a
copyofaCDisusuallyalongprocessthatcantakeminutes.Tolet
theuserknowwhensuchataskisbeingperformed,youcandisplay
ananimation.

MicrosoftWindowsprovidesafewsmallanimationsyoucan use for your applications. If you


needananimationotherthanthosesupplied,youmayhavetocreateit.MicrosoftVisualC++
isnottheplacetocreateananimation.Youmayneedagraphicssoftwaretodothis.
To use a regular animation, the video must be a standard Microsoft Windows audio/video
format:AudioVideoInterleavedorAVI.Therefore,itmustbeafilewiththeaviextension.If
thefilehasbothaudioandvideo,onlythevideopartwouldbeconsidered.

PracticalLearning:IntroducingAnimations
1. Tocreateanewapplication,pressCtrl+N
2. SelectMFCApplication
3. SettheNametoVideo1
4. ClickOK
5. Inthefirstpageofthewizard,clickNext
6. Inthesecondpageofthewizard,clickDialogBasedandclickNext
7. Inthethirdpageofthewizard,clicksettheTitletoVideoAnimation
8. ClickFinish
9. ClickTODOandpressDelete
10. ClicktheOKbuttonandpressDelete
11. ChangethecaptionoftheCancelbuttonto&Close

GettinganAnimationControl
An animation first originates from an avi file created by an external application. Therefore,
youmustalreadyhavethevideoyouwanttoplayinyourapplication.Toprovideananimation
for your application, at design time, from the Toolbox, click the Animation Control
clickthedesiredareaonthehost.

and

The animator control is based on the CAnimatorCtrl class. Therefore, if you want to
programmaticallycreateananimation,youmustfirstdeclareavariableoftype,orapointer
to,CAnimationCtrl.Youcandothisinthesourcecodeofthedialogclass.Afterdeclaringthe
variable or pointer, to initialize the object, call its Create() member function. Here is an
example:
classCControlsDlg:publicCDialog
{
//Construction
public:
CControlsDlg(CWnd*pParent=NULL)//standardconstructor
~CControlsDlg()
...
private:
CAnimateCtrl*Player
}
CControlsDlg::CControlsDlg(CWnd*pParent/*=NULL*/)

:CDialog(CControlsDlg::IDD,pParent)
{
//{{AFX_DATA_INIT(CControlsDlg)
//NOTE:theClassWizardwilladdmemberinitializationhere
//}}AFX_DATA_INIT
Player=newCAnimateCtrl
}

CControlsDlg::~CControlsDlg()
{
deletePlayer
}
...
BOOLCControlsDlg::OnInitDialog()
{
CDialog::OnInitDialog()
//TODO:Addextrainitializationhere
RECTRecto={5,5,360,360}
Player>Create(WS_CHILD|WS_VISIBLE,

Recto,this,0x1884)
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
//EXCEPTION:OCXPropertyPagesshouldreturnFALSE
}

CharacteristicsoftheAnimationControl

OpeninganAnimation
Aftercreatingthecontrol,youmustprovideavideoto play. This is done by opening a video
fileusingtheCAnimateCtrl::Open()memberfunction.Itisoverloadedwithtwoversionsas
follows:
BOOLOpen(LPCTSTRlpszFileName)
BOOLOpen(UINTnID)
Thefirstversionexpectsthepathofthevideofile.Alternatively,youcanfirstaddthefileasa
resourcetoyourprojectand use its identifier as argument to the second version. Here is an
example:
BOOLCControlsDlg::OnInitDialog()
{
CDialog::OnInitDialog()
//TODO:Addextrainitializationhere
RECTRecto={5,5,360,360}
Player>Create(WS_CHILD|WS_VISIBLE|ACS_TRANSPARENT,

Recto,this,0x1884)

Player>Open("res\\clock.AVI")
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
//EXCEPTION:OCXPropertyPagesshouldreturnFALSE
}

TheTransparencyofanAnimation
In this case, the center of the video would match the center of your rectangle, even though
theanimationmaystillnotexactlymatchthedimensionsofyourrectangle.
Whenplayingthevideo,youhavetheoptionofdisplayingtheoriginalbackgroundcolorofthe
videoorseeingthrough.Whencreatingavideo,itsauthorcandoitwithtransparencytoallow
seeing the color of the host. In this case, to display the color of the host while the video is
playing, set the Transparent property to True. If you are creating the control
programmatically,addtheACS_TRANSPARENTstyle:

PHP code
generator
Generate
PHP code
for any local
or remote
database.

BOOLCControlsDlg::OnInitDialog()
{
CDialog::OnInitDialog()
//TODO:Addextrainitializationhere
RECTRecto={5,5,360,360}
Player>Create(WS_CHILD|WS_VISIBLE|

ACS_TRANSPARENT|ACS_AUTOPLAY,

Recto,this,0x1884)
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
//EXCEPTION:OCXPropertyPagesshouldreturnFALSE
}

PracticalLearning:ShowanAnimation
1. FromtheToolbox,clickAnimationControl
2. Drawarectanglefromtheupperleftsectionofthedialogboxtotherightmiddle
3. InthePropertieswindow,changethefollowingcharacteristics:
AutoPlay:True
Center:True
ClientEdge:False
ID:IDC_ANIMATOR
Transparent:True

4. Onthedialogbox,rightclicktheanimatorcontrolandclickAddVariable
5. IntheCategorycombobox,makesureControlisselected.
IntheVariableName,typem_Animator

6. ClickFinish

PlayinganAnimation
Ifyouwantthevideotostartdisplayingimmediatelyonceitshost(thedialogboxorform)
comesup,setitsAutoPlaypropertytoTrue.Ifyouaredynamicallycreatingthecontroland
youwantitsvideotoplayassoonasitsparentcomesup,addtheACS_AUTOPLAYstyle:
BOOLCControlsDlg::OnInitDialog()
{
CDialog::OnInitDialog()
//TODO:Addextrainitializationhere
RECTRecto={5,5,360,360}
Player>Create(WS_CHILD|WS_VISIBLE|

ACS_TRANSPARENT|ACS_AUTOPLAY,

Recto,this,0x1884)
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
//EXCEPTION:OCXPropertyPagesshouldreturnFALSE
}
As mentioned already, an animation is made of various pictures. Each picture is called a
frame.Thenumberofframesthatmakeupananimationcaninfluenceitslength.Avideoto
playasanimationisafile that puts these pictures together. Once you have the video, you
canplayitinananimation.Ifyouwanttheanimationtostartplayingassoonasitsparent
windowcomesup,youcancreateitwiththeACS_AUTOPLAYstyle.Otherwise,toplaythe
animation,youcancalltheCAnimateCtrl::Play()memberfunction.Itssyntaxis:
BOOLPlay(UINTnFrom,UINTnTo,UINTnRep)
ThenFromargumentspecifiestheindexnumberofthefirstframetoplay.Theframes
arestoredasazerobasedarray.Thefirstframeis0,thesecondis1,etc

ThenToargumentisthelastframetoplayfromthelistofframes.Ifyouwanttoplay
thevideototheend,passthisargumentwithavalueof1
ThenRepisthenumberoftimesthevideoshouldbeplayedbeforestopping.Ifyou
wantthevideotoplayuntilyouexplicitlydecidetostopit,passthisargumentas1
Suppose you have a long video or one made of various special pictures, if you want to
display just one particular frame of the video, you can call the CAnimateCtrl::Seek()
memberfunctionwhosesyntaxis:
BOOLSeek(UINTnTo)
ThismemberfunctionallowstheanimationtojuststraighttothenToframenumber.
At any time, you can stop the video playing by calling theCAnimateCtrl::Stop()member
function.Itssyntaxis:
BOOLStop()
Thismemberfunctionsimplystopstheanimation.
If you had added your Animator control at design time to the dialog box or form or other
parentwindow,whentheparentgoesoutofscope,ittakestheAnimatorcontrolwithit.If
you dynamically created the control, you should make sure that the control is destroyed
whenitsparentalsois.Thisisusuallytakencareofwiththedeleteoperatorasdoneabove.
Furthermore, when it comes to the Animator control, after using it, to free the memory
spaceitspace,youshouldcalltheCAnimateCtrl::Close()memberfunction.Itssyntaxis:
BOOLClose()

PracticalLearning:PlayingaVideoFile
1. Fromtheresourcesthataccompanytheselessons,copythebasketball.avifileandpaste
itinthevideo1subfolderofthecurrentproject

2. IntheSolutionExplorer,doubleclickVideo1Dlg.cpp
3. IntheOnInitDialog()event,loadthevideowiththefollowinglineofcode:
BOOLCVideo1Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
m_Animator.Open(L"basketball.avi")
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}
4. Displaythedialogbox
5. Onthemainmenu,clickProject>ClassWizard...
6. IntheClassNamecombobox,selectCVideo1Dlg
7. ClicktheMessagestaband,intheMessageslist,doubleclickWM_CLOSE
8. ClickEditCode
9. Tocloseanddestroytheanimationwhentheusercloses,implementtheeventas
follows:
voidCVideo1Dlg::OnClose()
{

//TODO:Addyourmessagehandlercodehereand/orcalldefault
m_Animator.Stop()
m_Animator.Close()

CDialogEx::OnClose()

10. Totesttheapplication,pressF5
11. Returntoyourprogrammingenvironment
12. Changethedesignofthedialogboxasfollows:

Button:ID

Caption

IDC_START

Start

IDC_STOP

Stop

13. DoubleclicktheStartbutton
14. Togivetheusertheabilitytostarttheanimation,implementtheeventasfollows:
voidCVideo1Dlg::OnBnClickedStart()
{
m_Animator.Play(0,1,1)
}
15. ReturntothedialogboxanddoubleclicktheStopbutton
16. Toallowtheusertoresumeplayingthevideo,implementtheeventasfollows:
voidCVideo1Dlg::OnBnClickedStop()
{
m_Animator.Stop()
}
17. Totesttheapplication,pressF5

18. Closethedialogboxandreturntoyourprogrammingenvironment

WindowsControls:TheDatePicker

IntroductiontotheDate/TimePicker

Description

VisualC++
C++MFC
C++Example

Thedateandtimepickerisacontrolthatallowstheuserto
select either a date or a time value. This control provides
twoobjectsinone:

PracticalLearning:IntroducingtheDatePicker
1. StartMicrosoftVisualStudio
2. Tostartanewapplication,onthemainmenu,clickFile>NewProject...
3. Inthemiddlelist,clickMFCApplicationandchangetheNameto
SimpleInterest1
4. Inthefirstpageofthewizard,clickNext
5. Inthesecondpageofthewizard,clickDialogBasedandclickNext
6. ClickFinish

CreatingaDate/TimePicker
To create a Date or Time Picker control, add a date/time picker to a dialog box or a
form.Thedate/timepickerisimplementedbyaclassnamedCDateTimeCtrl,which
is derived from CWnd. To programmatically create a date/time picker, declare
CDateTimeCtrl variable and use its Create() member function to initialize it. The
syntaxofthismemberfunctionis:
virtualBOOLCreate(DWORDdwStyle,

constRECT&rect,

CWnd*pParentWnd,

UINTnID)
Hereisanexampleofcallingit:

BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
CDateTimeCtrl*ctrlDateHired=newCDateTimeCtrl
ctrlDateHired>Create(WS_CHILD|WS_VISIBLE,

CRect(10,10,200,35),

this,

IDC_DATE_HIRED)
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}
Thiswouldproduce:

IntroductiontotheDatePickerControl
Afteraddingadate/timepickertoadialogbox,thedefaultbehavioristhatitbecomes
adatepicker.Theusercanclickthearrowbuttontodisplayscalendar:

PracticalLearning:AddingDatePickerControls
1. Designthedialogboxasfollows:

Control

Caption

ID

AlignText

GroupBox

LoanPreparation

StaticText

&Principal:

EditBox

IDC_PRINCIPAL

Right

StaticText

Interest&Rate:

EditBox

IDC_INTEREST_RATE

Right

StaticText

StaticText

Loan&StartDate:

DateTimePicker

IDC_LOAN_START_DATE

StaticText

Loan&EndDate:

DateTimePicker

IDC_LOAN_END_DATE

StaticText

P&riods:

EditBox

IDC_PERIODS

Right

StaticText

days

Button

C&alculate

IDC_CALCULATE

GroupBox

Results

StaticText

InterestEar&ned:

EditBox

IDC_INTERERST_EARNED Right

Button

Reset

IDC_RESET

StaticText

&FutureValue:

EditBox

IDC_FUTURE_VALUE

Right

Button

&Close

IDCANCEL

2. Rightclickeachoftheeditcontrolsanddatetimepicker,andclickAddVariable...
3. Createthevariablesasfollows:

ID

Category Type

Name

IDC_PRINCIPAL

Value

double

m_Principal

IDC_INTEREST_RATE

Value

double

m_InterestRate

IDC_LOAN_START_DATE

Control

CDateTimeCtrl m_LoanStartDate

IDC_LOAN_END_DATE

Control

CDateTimeCtrl m_LoanEndDate

IDC_PERIODS

Value

double

m_Periods

IDC_INTERERST_EARNED

Value

double

m_InterestEarned

IDC_FUTURE_VALUE

Value

double

m_FutureValue

4. Toexecuteandpreviewthedialogbox,pressF5
5. Closethedialogboxandreturntoyourprogrammingenvironment

CharacteristicsoftheDatePickerControl

TheShortDateFormat
InUSEnglish,adatecanbedisplayedasashortdateoralongdate,asspecifiedintheControlPanel.To
visually make a date picker display in short date, in the Properties window, set the Format field to Short
Date. To programmatically set the short date option, add the DTS_SHORTDATEFORMAT style. This type
displaysthenumericmonth,followedbythenumericday,andfollowedbytheyear.

TheLongDateFormat
If you prefer a date that includes the names of the month and the weekday, in the Properties window, set
theFormatfieldtoLongDate.Tosetthisoptionprogrammatically,addtheDTS_LONGDATEFORMATstyle.

PracticalLearning:SettingaLongDateFormat
1. Onthedialogbox,rightclickthetopdatepickerandclickProperties
2. InthePropertieswindow,clickFormatandchangeitsvaluetoLongDate
3. Onthedialogbox,clicktheotherdatepicker
4. InthePropertieswindow,clickFormatandchangeitsvaluetoLongDate

TheMonthCalendaroftheDatePicker
Unlikethedatepickerisinfacttwocontrols,combiningacomboboxandacalendar.Becausethecalendar
part enjoys all the functionality of the month calendar control, you have the ability to manipulate,
separately, any of its characteristics, as they are related to themonthcalendarcontrol.Tomanipulatethis
calendarasacontrol,youwouldneedtoaccessitfirstbyitshandle.Togetahandletothecalendarofthe
datepicker,calltheGetMonthCalCtrl()memberfunction.Itssyntaxis:
CMonthCalCtrl*GetMonthCalCtrl()const
Thiswouldbedoneasfollows:
BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
CDateTimeCtrl*ctrlDateHired=newCDateTimeCtrl
ctrlDateHired>Create(WS_CHILD|WS_VISIBLE,

CRect(10,10,200,35),

this,

IDC_DATE_HIRED)
CMonthCalCtrl*mc=ctrlDateHired>GetMonthCalCtrl()
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}

PracticalLearning:ConfiguringtheCalendar
1. IntheClassView,expandtheprojectand,inthetopsection,clickCSimpleInterestDlg
2. InthelowersectionoftheClassView,doubleclickOnInitDialog
3. Changetheappearancesofthecalendarsofthedatepickersasfollows:
BOOLCSimpleInterest1Dlg::OnInitDialog()
{

CDialogEx::OnInitDialog()

//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon

//TODO:Addextrainitializationhere
m_LoanStartDate.SetMonthCalColor(MCSC_TITLEBK,RGB(0,0,128))
m_LoanStartDate.SetMonthCalColor(MCSC_MONTHBK,RGB(70,170,255))
m_LoanStartDate.SetMonthCalColor(MCSC_TEXT,RGB(250,240,50))
m_LoanStartDate.SetMonthCalColor(MCSC_TITLETEXT,RGB(255,255,0))
m_LoanStartDate.SetMonthCalColor(MCSC_BACKGROUND,RGB(190,225,240))
m_LoanStartDate.SetMonthCalColor(MCSC_TRAILINGTEXT,RGB(150,200,255))

returnTRUE//returnTRUEunlessyousetthefocustoacontrol

m_LoanEndDate.SetMonthCalColor(MCSC_TITLEBK,RGB(170,120,5))
m_LoanEndDate.SetMonthCalColor(MCSC_MONTHBK,RGB(220,190,125))
m_LoanEndDate.SetMonthCalColor(MCSC_TEXT,RGB(128,0,0))
m_LoanEndDate.SetMonthCalColor(MCSC_TITLETEXT,RGB(220,190,125))
m_LoanEndDate.SetMonthCalColor(MCSC_BACKGROUND,RGB(250,175,10))
m_LoanEndDate.SetMonthCalColor(MCSC_TRAILINGTEXT,RGB(255,255,255))

4. Executetheapplicationtoseetheresult

5. Closethedialogboxandreturntoyourprogrammingenvironment

TheUpDownControlofaDatePicker
Bydefault,thedatepickercontroldisplaysacombobox.Ifyoudon'tlikethecombobox,youcandisplaya
spinbuttoninstead.Tosetthisoptionatdesigntime,changethevalueoftheUseSpinControlpropertyfrom
False(thedefault)toTrue.Toprogrammaticallysetthisoption,addtheDTS_UPDOWNstyle.Thiswouldbe
doneasfollows:
BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
CDateTimeCtrl*ctrlDateHired=newCDateTimeCtrl
ctrlDateHired>Create(WS_CHILD|WS_VISIBLE|DTS_UPDOWN,

CRect(10,10,200,35),

this,

IDC_DATE_HIRED)

returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}
When the control has the Use Spin Control property set to False and if the user clicks the arrow of the
control, a calendar displays to the bottomleft or the bottomright side of the combo box. To control this
alignment,changethevalueoftheRightAlignfieldinthePropertieswindow.ItsdefaultvalueissettoTrue,
whichmeansthatthecalendarwouldbealignedtotheright.Toprogrammaticallysetthisproperty,addthe
DTS_RIGHTALIGNproperty.
Thedisplayedmonthcalendarobjectallowstheusertoselectadateusingthesametechniquesofthemonth
calendar control. The month calendar of the date picker control displays using the same colors and other
properties of the month calendar control. After the user has selected a date, the date value displays in the
editcontrolofthecomboboxandthecalendardisappears.
If the control displays a spin button, the object is divided in different sections that can each be changed
individually:

Tochangeeithertheday,themonth,ortheyear,theusermustclickthedesiredsectionanduseeitherthe
arrowsofthebuttonorthearrowkeysonthekeyboardtoincreaseordecreasetheselectedvalue.

TheRangeofDates
Ifyouwanttocontroltherangeofdatestheusercanselect,calltheCDateTimeCtrl::SetRange()member
function.Itisoverloadedintwoversionswhosesyntaxesare:
BOOLSetRange(constCOleDateTime*pMinRange,

constCOleDateTime*pMaxRange)
BOOLSetRange(constCTime*pMinRange,

constCTime*pMaxRange)
This member function takes two arguments. The first is the lowest date that the user can navigate to. The
secondisthehighestdatethattheusercannavigateto.
Toknowtherangeofvaluesthattheuserisallowedtonavigateto,calltheCDateTimeCtrl::GetRange()
memberfunction.Itisoverloadedintwoversionswhosesyntaxesare:
DWORDGetRange(COleDateTime*pMinRange,

COleDateTime*pMaxRange)
DWORDGetRange(CTime*pMinRange,

CTime*pMaxRange)

SettingaDate
WhenyouaddtheDateTimePickercontroltoyourformorcontainer,itdisplaysthedateofthecomputerat
the time the control was added. If you want the control to display a different date, set the desired value
usingtheSetTime()memberfunction.Thisfunctionisprovidedinthreeversionswhosesyntaxesare:
BOOLSetTime(constCOleDateTime&timeNew)
BOOLSetTime(constCTime*pTimeNew)
BOOLSetTime(LPSYSTEMTIMEpTimeNew=NULL)

GettingaDate
At any time, you can find out what value the Date Picker has by retrieving the value of the GetTime()
memberfunctionoftheTDateTimeCtrlclass.Thisfunctioncomesinthreeversionswhosesyntaxesare:
BOOLGetTime(COleDateTime&timeDest)const
DWORDGetTime(CTime&timeDest)const
DWORDGetTime(LPSYSTEMTIMEpTimeDest)const

PracticalLearning:GettingaDate
1. Onthedialogbox,doubleclickthebottomdatepicker
2. Implementitseventasfollows:
voidCSimpleInterest1Dlg::OnDtnDatetimechangeLoanEndDate(NMHDR*pNMHDR,LRESULT*pResult)
{
LPNMDATETIMECHANGEpDTChange=reinterpret_cast<LPNMDATETIMECHANGE>(pNMHDR)
//TODO:Addyourcontrolnotificationhandlercodehere
*pResult=0
CTimeSpantsPeriods
CTimetmLoanStartDate,tmLoanEndDate

UpdateData()
if(tmLoanEndDate<tmLoanStartDate)
{

AfxMessageBox(L"InvalidateDateSequence:"
L"theenddatemustoccurafterthestartdate")

return
}
m_LoanStartDate.GetTime(tmLoanStartDate)

m_LoanEndDate.GetTime(tmLoanEndDate)
tsPeriods=tmLoanEndDatetmLoanStartDate
m_Periods=tsPeriods.GetDays()
UpdateData(FALSE)
}
3. ReturntothedialogboxanddoubleclicktheCalculatebutton
4. Implementitseventasfollows:
voidCSimpleInterest1Dlg::OnBnClickedCalculate()
{
//TODO:Addyourcontrolnotificationhandlercodehere
CTimeSpantsPeriods
CTimetmLoanStartDate,tmLoanEndDate
doubleinterestRate,interestEarned,principal

UpdateData()
m_LoanStartDate.GetTime(tmLoanStartDate)
m_LoanEndDate.GetTime(tmLoanEndDate)
if(tmLoanEndDate<tmLoanStartDate)
{

AfxMessageBox(L"InvalidateDateSequence:"
L"theenddatemustoccurafterthestartdate")

return
}
m_InterestEarned=m_Principal*(m_InterestRate/100)*(m_Periods/365)
m_FutureValue=m_Principal+m_InterestEarned
UpdateData(FALSE)
}
5. Executetheapplicationandtestit
6. Enteranamountasprincipal,aninterestrate,andselectthedatesonbothtimepickers
7. ClicktheCalculatebutton.Hereisanexample:

8. Closethedialogboxandreturntoyourprogrammingenvironment

TheFormatoftheDisplayedDate
Bydefault,thedatepickerdisplaysusingeithertheShortDateortheLongDateformatsofControlPanel.If
you want to customize the way the date is displayed, call the CDateTimeCtrl::SetFormat() member
function.Itssyntaxis:
BOOLSetFormat(LPCTSTRpstrFormat)
Thisfunctiontakesoneargumentthatusesacombinationofspecificlettersandsymbols.Thelettersusedto
createaformatareasfollows:
Format

UsedFor Description

Days

Displaysthedayasanumberfrom1to31

dd

Days

Displaysthedayasanumberwithaleading0ifthenumberis
lessthan10

ddd
dddd

Weekdays Displaysaweekdaynamewith3lettersasMon,Tue,etc
Weekdays DisplaysthecompletenameofaweekdayasMonday,etc

Months

Displaysthenumericmonthfrom1to12

MM

Months

Displaysthenumericmonthwithaleading0ifthenumberis
lessthan10

MMM

Months

DisplaystheshortnameofthemonthasJan,Feb,Mar,etc

MMMM

Months

DisplaysthecompletenameofthemonthasJanuary,etc

yy

Years

Displaystwodigitsfortheyearas00for2000or03for2003

yyyy

Years

Displaysthenumericyearwith4digits

Hereisanexample:

BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
CDateTimeCtrl*ctrlDateHired=newCDateTimeCtrl
ctrlDateHired>Create(WS_CHILD|WS_VISIBLE|DTS_UPDOWN,

CRect(10,10,200,35),

this,

IDC_DATE_HIRED)
ctrlDateHired>SetFormat(_T("dddd,ddMMMM,yyyy"))

returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}
Thiswouldproduce:

Toretrievethecurrentformatusedonthecontrol,youcancallitsGetFormat()memberfunction.

ManuallyEditingtheDate
Theusermaywanttoeditthedatevalueofthecontrol,includingtypingthemonth,day,year,thenameof
themonthorthenameoftheweekday.Thedatepickerobjectisequippedtocontrolthetypesofvaluesthat
can be entered. For example, the user cannot type the name of a month, only a number, and the control
would display the corresponding name of the month. This is the default scenario where you let this object
helpyoucontrolthevaluesthattheusercantype.Ifyouwanttotakemattersintoyourownhands,thatis,
ifyouwanttoallowtheusertotypethevalueofthedateortimeofthecontrol,atdesigntimesettheAllow
Edit Boolean property to True (its default value is False). To set this option programmatically, add the
DTS_APPCANPARSEstyle.
If you allow the user to manually enter the date value, if the value is incorrect, when the control looses
focus,thecompilerwouldmakeanattempttoconvertthedateenteredintoavalidandtruedate.Iftheuser
enters an invalid value, the compiler would throw an error. This means that you should be reluctant to let
theuserstypewhatevertheywant.Thelesstheytype,thelesscheckingyouneedtodo.

Home

Copyright20102011FunctionX,Inc.

WindowsControls:MaskedEdit
Control

IntroductiontotheMaskedEditControl

Description

By default, the edit control allows (almost) any type of


character, including readable and nonreadable characters.
IntheWin32andtheMFClibraries,itcanbemadetoaccept
only digits. It still lacks some of the customizations that
would consist of accepting only some symbols and rejecting
others.Insteadofwritinglongcodethatwouldtakehaveto
analyze complex expressions, the MFC library provides the
maskededitcontrol.

Windows7
MFC
Controls

The masked edit control is a custom editor that can be made to accept only some
characters and to reject some others. It makes it possible to let the user enter only
some specific items like a social security number, a telephone number, a date, or a
time,etc.

CreatingaMaskedEditControl
To visually create a masked edit control, in the Toolbox, click the MFC MaskedEdit
Control
and click the dialog box. The masked edit control is implemented by a
classnamedCMFCMaskedEdit,whichisderivedfromCEdit.
As done for all MFC controls, after visually adding a masked edit control, you should
addamembervariableforit.

CharacteristicsofaMaskedEditControl

CreatingaMask
Themostimportantcharacteristicofamaskededitcontrolisthewayitallowssome
characters and rejects some others. This scheme is referred to as its mask. To
visuallycreatethemask,youusetwostepsinthePropertieswindow.TheMaskfield
is used to specify whether to allow letters or digits. The mask uses one or a
combinationofthefollowingcharacters:
Character

Description

Analphabeticlettermustbeentered

Adigit(0,1,2,3,4,5,6,7,8,or9)mustbeentered

Aletteroradigitcanbeentered

Aprintablesymbol(letter,digit,#,$,@,etc)canbeentered

Alettercanbeenteredorthespacecanbeleftempty

Adigitcanbeenteredorthespacecanbeleftempty

Aletteroradigitcanbeentered,orthespacecanbeleftempty

A+ormustbeentered

TheInputPlaceholders
Amaskededitcontrolmustindicatewherethecharactersmustbeenteredandwhere
empty spaces can be left. To visually created them, in the Properties window click
InputTemplateandtypethecharacters:
Character Name

Description

Underscore Thisisusedasaplaceholder

Dash

Thisisusedastheseparatorbetweentwosections

Default
Char

Thisisusedwherenocharacterfromthemaskwouldbe
used.Thedefaultisanemptyspace

Besides the underscore, the dash, or an empty space, you can enter any character
otherthanA,a,C,c,D,d,*,or+.Anycharacterwouldbekept"asis".

PHP code
generator
Generate PHP code for any
local or remote database.

To actually visually create a mask, you use a combination of the Mask and the Input
TemplatefieldsinthePropertieswindow.Hereisanexample:

Examplesofmasksare:
InputTemplate Mask

Description

(___)_______ dddddddddd U.S.andCanadatelephonenumber


__________

dddddddddd U.S.andCanadatelephonenumber

_________

ddddddddd

U.S.SocialSecurityNumber

ProgrammaticallyCreatingaMask
To let you programmatically create a mask and its placeholders, the
CMFCMaskedEdit class is equipped with the EnableMask() member function. Its
syntaxis:
voidEnableMask(
LPCTSTRlpszMask,
LPCTSTRlpszInputTemplate,
TCHARchMaskInputTemplate=_T('_'),
LPCTSTRlpszValid=NULL
)
This member function takes 4 arguments with the first two being required. The first
argumentisthemaskofthecontrol.Thesecondargumentcreatestheplaceholder(s).
BothargumentsplaythesamerolesastheMaskandtheInputTemplatefieldsofthe
Propertieswindow.
Aftervisuallyorprogrammaticallycreatingamask,thecontrolwouldimposeitsrules
totheuser.Ifyouwanttoignorethemaskandmakethemaskededitcontrolbehave
like a regular edit box, call the DisableMask() member function of the
CMFCMaskedEditclass.Itssyntaxis:
voidDisableMask()

SettingaDefaultStringtoaMaskedEditControl
Whenamaskededitcontroldisplays,theusermaynotknowwhattypesofvaluesto
enter.Onewayyoucanaddressthisissueistopresentadefaultvalueinthecontrol.
To do this, call the SetWindowText() member function of the CMFCMaskedEdit
class.Itssyntaxis:
voidSetWindowText(LPCTSTRlpszString)
Hereisanexampleofcallingit:
BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
m_TelephoneNumber.SetWindowTextW(L"(000)0000000")
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}

GettingtheCharactersofaMaskedEditControl
Aftertheuserhastypedavalueinthemaskededitcontrol,togetthatvalue,youcan
calltheCMFCMaskedEdit::GetWindowTex()memberfunction.Itisprovidedintwo
versionswhosesyntaxesare:
intGetWindowText(LPTSTRlpszStringBuf,intnMaxCount)const
voidGetWindowText(CString&rstrString)const
Thefirstversiontakesanarrayofcharactersanditslengthasarguments.Thesecond
versiontakesaCStringasargument.Hereisanexample:
voidCExerciseDlg::OnBnClickedGetValue()
{

//TODO:Addyourcontrolnotificationhandlercodehere

CStringstrValue

m_ShelfNumber.GetWindowText(strValue)
m_Value=strValue
UpdateData(FALSE)

GettingtheWholeValueofaMaskedEditControl
By default, the CMFCMaskedEdit::GetWindowText() member function produces
onlythecharactersthatauserenteredinthecontrol,leavingouttheinputsymbolsof
the mask. If you want to include those symbols in the result, call the
EnableGetMaskedCharsOnly()memberfunction.Itssyntaxis:
voidEnableGetMaskedCharsOnly(BOOLbEnable=TRUE)
ThisfunctiontakesasargumentaBooleanvaluethatdetermineswhethertoconsider
orignorethesymbolsofthemask.ThedefaultvalueoftheargumentisTRUE,which
meansthemasksymbolswouldnotbeincludedintheresultingstring.Ifyouwantto
include those symbols, call this member function before calling GetWindowText()
andpasstheargumentasFALSE.Hereisanexample:
voidCExerciseDlg::OnBnClickedGetValue()
{

//TODO:Addyourcontrolnotificationhandlercodehere

CStringstrValue

m_ShelfNumber.EnableGetMaskedCharsOnly(FALSE)

m_ShelfNumber.GetWindowText(strValue)
m_Value=strValue
UpdateData(FALSE)

WindowsControls:TheTimePicker

IntroductiontotheDate/TimePicker

Description
MFC
Controls
C#SourceCode

Thedateandtimepickerisacontrolthatallowstheusertoselecteitheradateoratime
value.Thiscontrolprovidestwoobjectsinone:

PracticalLearning:IntroducingtheDatePicker
1. StartMicrosoftVisualStudio
2. Tostartanewapplication,onthemainmenu,clickFile>NewProject...
3. Inthemiddlelist,clickMFCApplicationandchangetheNametoSimpleInterest1
4. Inthefirstpageofthewizard,clickNext
5. Inthesecondpageofthewizard,clickDialogBasedandclickNext
6. ClickFinish

CreatingaDate/TimePicker
TocreateaDateorTimePickercontrol,addadate/timepickertoadialogboxoraform.Thedate/timepickeris
implemented by a class named CDateTimeCtrl, which is derived from CWnd. To programmatically create a
date/timepicker,declareCDateTimeCtrlvariableanduseitsCreate()memberfunctiontoinitializeit.Thesyntax
ofthismemberfunctionis:
virtualBOOLCreate(DWORDdwStyle,

constRECT&rect,

CWnd*pParentWnd,

UINTnID)
Hereisanexampleofcallingit:

BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
CDateTimeCtrl*ctrlDateHired=newCDateTimeCtrl
ctrlDateHired>Create(WS_CHILD|WS_VISIBLE,

CRect(10,10,200,35),

this,

IDC_DATE_HIRED)
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}
Thiswouldproduce:

IntroductiontotheTimePicker

Description
Afteraddingadate/timepickertoadialogbox,tovisuallymakeitatimerpickercontrol,inthePropertieswindow,
changeitsFormatfieldtoTime.Thischangesthecontrolintoaspincontrol:

ToprogrammaticallychangeaCDateTimeCtrlobject into a time picker, add the DTS_TIMEFORMATstyle.Here


isanexample:
BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
CDateTimeCtrl*ctrlStartTime=newCDateTimeCtrl
ctrlStartTime>Create(WS_CHILD|WS_VISIBLE|DTS_TIMEFORMAT,
CRect(15,15,100,35),

this,

IDC_START_TIME)
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}

PracticalLearning:CreatingaTimePickerApplication
1. StartMicrosoftVisualStudio
2. Tostartanewapplication,onthemainmenu,clickFile>NewProject...
3. Inthemiddlelist,clickMFCApplicationandchangetheNametoGeorgetownDryCleaningServices1
4. Inthefirstpageofthewizard,clickNext
5. Inthesecondpageofthewizard,clickDialogBasedandclickNext
6. ClickFinish
7. Designthedialogboxasfollows:

Control

Caption

ID

AdditionalProperties

GroupBox

Order
Identification

StaticText

C&ustomer
Name:

EditBox

IDC_CUSTOMER_NAME

StaticText

Customer
&Phone:

EditBox

IDC_CUSTOMER_PHONE

StaticText

&DateLeft:

DateTime
Picker

IDC_DATE_LEFT

StaticText

&TimeLeft:

DateTime
Picker

IDC_TIME_LEFT

Format:Time

StaticText

DateExpected

DateTime
Picker

StaticText

TimeExpected

DateTime
Picker

Format:Time

StaticText

DatePickedUp

DateTime
Picker

IDC_DATE_PICKED_UP

StaticText

TimePicke&d
Up:

DateTime
Picker

IDC_TIME_PICKED_UP

Format:Time

GroupBox

Order
Processing

StaticText

ItemType

StaticText

UnitPrice

StaticText

Qty

StaticText

SubTotal

StaticText

Shirts

EditBox

IDC_UNITPRICE_SHIRTS

EditBox

IDC_QUANTITY_SHIRTS

EditBox

IDC_SUBTOTAL_SHIRTS

StaticText

Pants

EditBox

IDC_UNITPRICE_PANTS

EditBox

IDC_QUANTITY_PANTS

EditBox

IDC_SUBTOTAL_PANTS

IDC_DATE_EXPECTED

IDC_TIME_EXPECTED

Combo
Box

IDC_ITEM1

Data:
NoneTieCoatDressOther
JacketSwedeSilkShirt
SweaterComforter
WomenSuitRegularSkirt
Men'sSuit2Pc
Men'sSuit3PcSkirtWith
Hook

EditBox

IDC_UNITPRICE_ITEM1

EditBox

IDC_QUANTITY_ITEM1

EditBox

IDC_SUBTOTAL_ITEM1

Combo
Box

IDC_ITEM2

Data:
NoneTieCoatDressOther
JacketSwedeSilkShirt
SweaterComforter
WomenSuitRegularSkirt
Men'sSuit2Pc
Men'sSuit3PcSkirtWith
Hook

EditBox

IDC_UNITPRICE_ITEM2

EditBox

IDC_QUANTITY_ITEM2

EditBox

IDC_SUBTOTAL_ITEM2

Combo
Box

IDC_ITEM3

Data:
NoneTieCoatDressOther
JacketSwedeSilkShirt
SweaterComforter
WomenSuitRegularSkirt
Men'sSuit2Pc
Men'sSuit3PcSkirtWith
Hook

EditBox

IDC_UNITPRICE_ITEM3

PHP code
generator
Generate
PHP code
for any local
or remote
database.

EditBox

IDC_QUANTITY_ITEM3

EditBox

IDC_SUBTOTAL_ITEM3

Combo
Box

IDC_ITEM4

Data:
NoneTieCoatDressOther
JacketSwedeSilkShirt
SweaterComforter
WomenSuitRegularSkirt
Men'sSuit2Pc
Men'sSuit3PcSkirtWith
Hook

EditBox

IDC_UNITPRICE_ITEM4

EditBox

IDC_QUANTITY_ITEM4

EditBox

IDC_SUBTOTAL_ITEM4

GroupBox

Order
Summary

Button

C&alculate

IDC_CALCULATE

StaticText

CleaningTotal:

EditBox

IDC_CLEANING_TOTAL

AlignText:Right

StaticText

TaxRate:

EditBox

IDC_TAX_RATE

AlignText:Right

StaticText

StaticText

TaxAmount

EditBox

IDC_TAX_AMOUNT

AlignText:Right

StaticText

NetPrice:

EditBox

IDC_NET_PRICE

AlignText:Right

Button

&Close

IDCANCEL

8. Rightclickeachoftheeditcontrolsanddatetimepicker,andclickAddVariable...
9. Createthevariablesasfollows:

ID

Category

Type

Name

IDC_CUSTOMER_NAME

Value

CString

m_CustomerName

IDC_CUSTOMER_PHONE

Value

CString

m_CustomerPhone

IDC_DATE_LEFT

Value

CTime

m_DateLeft

IDC_TIME_LEFT

Value

CTime

m_TimeLeft

IDC_DATE_EXPECTED

Value

CTime

m_DateExpected

IDC_TIME_EXPECTED

Value

CTime

m_TimeExpected

IDC_DATE_PICKED_UP

Value

CTime

m_DatePickedUp

IDC_TIME_PICKED_UP

Value

CTime

m_TimePickedUp

IDC_UNITPRICE_SHIRTS

Value

double

m_UnitPriceShirts

IDC_QUANTITY_SHIRTS

Value

int

m_QuantityShirts

IDC_SUBTOTAL_SHIRTS

Value

double

m_SubTotalShirts

IDC_UNITPRICE_PANTS

Value

double

m_UnitPricePants

IDC_QUANTITY_PANTS

Value

int

m_QuantityPants

IDC_SUBTOTAL_PANTS

Value

double

m_SubTotalPants

IDC_ITEM1

Value

CString

m_Item1

IDC_UNITPRICE_ITEM1

Value

double

m_UnitPriceItem1

IDC_QUANTITY_ITEM1

Value

int

m_QuantityItem1

IDC_SUBTOTAL_ITEM1

Value

double

m_SubTotalItem1

IDC_ITEM2

Value

CString

m_Item2

IDC_UNITPRICE_ITEM2

Value

double

m_UnitPriceItem2

IDC_QUANTITY_ITEM2

Value

int

m_QuantityItem2

IDC_SUBTOTAL_ITEM2

Value

double

m_SubTotalItem2

IDC_ITEM3

Value

CString

m_Item3

IDC_UNITPRICE_ITEM3

Value

double

m_UnitPriceItem3

IDC_QUANTITY_ITEM3

Value

int

m_QuantityItem3

IDC_SUBTOTAL_ITEM3

Value

double

m_SubTotalItem3

IDC_ITEM4

Value

CString

m_Item4

IDC_UNITPRICE_ITEM4

Value

double

m_UnitPriceItem4

IDC_QUANTITY_ITEM4

Value

int

m_QuantityItem4

IDC_SUBTOTAL_ITEM4

Value

double

m_SubTotalItem4

IDC_CLEANING_TOTAL

Value

double

m_CleaningTotal

IDC_TAX_RATE

Value

double

m_TaxRate

IDC_TAX_AMOUNT

Value

double

m_TaxAmount

IDC_NET_PRICE

Value

double

m_NetPrice

10. Accessthesourcecodeofthedialogboxandinitializesomecontrolsasfollows:
CGeorgetownDryCleaningServices1Dlg::CGeorgetownDryCleaningServices1Dlg(CWnd*pParent/*=NULL*/)

:CDialogEx(CGeorgetownDryCleaningServices1Dlg::IDD,pParent)

,m_CustomerName(_T(""))

,m_CustomerPhone(_T(""))

,m_DateLeft(0)

,m_TimeLeft(0)

,m_DateExpected(0)

,m_TimeExpected(0)

,m_DatePickedUp(0)

,m_TimePickedUp(0)

,m_UnitPriceShirts(1.25)

,m_QuantityShirts(0)

,m_SubTotalShirts(0)

,m_UnitPricePants(1.95)

,m_QuantityPants(0)

,m_SubTotalPants(0)

,m_Item1(_T(""))

,m_UnitPriceItem1(0)

,m_QuantityItem1(0)

,m_SubTotalItem1(0)

,m_Item2(_T(""))

,m_UnitPriceItem2(0)

,m_QuantityItem2(0)

,m_SubTotalItem2(0)

,m_Item3(_T(""))

,m_UnitPriceItem3(0)

,m_QuantityItem3(0)

,m_SubTotalItem3(0)

,m_Item4(_T(""))

,m_UnitPriceItem4(0)

,m_QuantityItem4(0)

,m_SubTotalItem4(0)

,m_CleaningTotal(0)

,m_TaxRate(7.75)

,m_TaxAmount(0)

,m_NetPrice(0)
{

m_hIcon=AfxGetApp()>LoadIcon(IDR_MAINFRAME)
}
11. ReturntothedialogboxanddoubleclicktheCalculatebutton
12. Implementtheeventasfollows:
voidCGeorgetownDryCleaningServices1Dlg::OnBnClickedCalculate()
{

//TODO:Addyourcontrolnotificationhandlercodehere

UpdateData()

m_SubTotalShirts=m_UnitPriceShirts*m_QuantityShirts

m_SubTotalPants=m_UnitPricePants*m_QuantityPants

m_SubTotalItem1=m_UnitPriceItem1*m_QuantityItem1

m_SubTotalItem2=m_UnitPriceItem2*m_QuantityItem2

m_SubTotalItem3=m_UnitPriceItem3*m_QuantityItem3

m_SubTotalItem4=m_UnitPriceItem4*m_QuantityItem4

m_CleaningTotal=m_SubTotalShirts+m_SubTotalPants+

m_SubTotalItem1+m_SubTotalItem2+

m_SubTotalItem3+m_SubTotalItem4
m_TaxAmount=m_CleaningTotal*m_TaxRate
m_NetPrice=m_CleaningTotal+m_TaxAmount

UpdateData(FALSE)

13. Toexecuteandpreviewthedialogbox,pressF5
14. Closethedialogboxandreturntoyourprogrammingenvironment

CharacteristicsoftheTimePickerControl

Introduction
The time picker control is a spin button made of different sections: the hours value,
the minutes value, the optional seconds value, and the optional AM/PM string. To
changethetime,theuserclicksasectionanduseseitherthemouseorthekeyboard
toincreaseordecreasethatparticularvalue.Tochangeanothervalue,theusermust
firstclickitandthenusethespinbutton.
Tousethetimepicker,theusermustfirstgiveitfocus.Thisisdonebyclickingeither
oneofthesectionsofthecontrolorbydirectlyclickingoneofthearrowsofthespin
buttonportion.Youalsocanprogrammaticallygivefocustothecontrolbysendingan
NM_SETFOCUSmessage.
Once the control has focus, it is primarily meant to let the user set a time (on the
control). To support this, it allows the user to manually edit the time of the control
suchastypingthehour,theminute,thesecond,orAM/PM.Thetimepickercontrolis
equippedtonativelyallowordisallowsomevalues.Forexample,theusercannottype
anythingelsethanadigitforthehours,minutes,orsecondportionsandshecantype
onlya,A,p,orPfortheAM/PMsection.Thisisthedefaultscenariowhereyouletthis
object help you control the values that the user can type. To perform these
operations, the user can click the portion to change and then click the arrows of the
spin button. When the user changes the value of the control, the time picker fires a

DTN_DATETIMECHANGEmessage.
Instead of using the mouse to change the time, the user can click a portion of the
control and press the arrow keys to change the value of that portion. Whenever the
user presses one of the arrow keys, the control fires a DTN_WMKEYDOWN
message.
After using the time picker control, the user can click somewhereelse,whichcauses
the control to loose focus. To programmatically change focus from the control, you
cansendanNM_KILLFOCUSmessage.

TheTimeFormat

By default, the time displays using the H:MM:SS AM/PM format. This means that the
timeusesonedigitforthehoursfrom0to9,twodigitsfortheminutesfrom00to59,
twodigitsforthesecondsfrom00to59andtheAMorPMformorningorafternoon.
To control how the time displays, call the CDateTimeCtrl::SetFormat() member
functionwhosesyntaxis:
BOOLSetFormat(LPCTSTRpstrFormat)
Thelettersusedtosettheformatforatimevalueare:
Format

UsedFor Description

Hour

For12hourbasis:Usedtodisplaythehourwithonedigitifthe
valueislessthan10

hh

Hour

For12hourbasis:Usedtodisplaythehourwithaleading0if
thevalueislessthan10

Hour

For24hourbasisUsedtodisplaythehourwithonedigitifthe
valueislessthan10

HH

Hour

For24hourbasis:Usedtodisplaythehourwithaleading0if
thevalueislessthan10

Minute

Usedtodisplaytheminutewithonedigitifthevalueislessthan
10

mm

Minute

Usedtodisplaytheminutewithaleading0ifthevalueisless
than10

AM/PM

DisplaystheletterAorPfortheAMorPMsection

tt

AM/PM

DisplaysthelettersAMorPMforthelastsection

TheTimeoftheControl
Bydefault,afteraddingthecontroltothedialogboxorcontainer,itassumesthetime
ofthecomputerwhenthecontrolwasadded.Ifyouwanttosetadifferenttime,call
the CDateTimeCtrl::SetTime() member function. It is overloaded with three
versionswhosesyntaxesare:
BOOLSetTime(constCOleDateTime&timeNew)
BOOLSetTime(constCTime*pTimeNew)
BOOLSetTime(LPSYSTEMTIMEpTimeNew=NULL)
To retrieve the time value on the control, you can call the
CDateTimeCtrl::GetTime() member function. It also is overloaded with three
versionsandtheirsyntaxesare:
BOOLGetTime(COleDateTime&timeDest)const
DWORDGetTime(CTime&timeDest)const
DWORDGetTime(LPSYSTEMTIMEpTimeDest)const

FASTREPORT

VCL

for Delphi/CB 5-XE6 Fast. Compact. Feature-rich.

Home

Copyright20102011FunctionX,Inc.

BitmapButtons

Overview
Abitmapbuttonisabuttonthatdisplayapicture
or a picture and text on its face. This is usually
used the button a little explicit. There are two
ways you can create a bitmap button: with or
withoutanexistingresourceidentifier.
A bitmap button is created using the
CBitmapButton class, which is a child of
CButton, which in turn is a descendent of the
CWndclass.Thismeansthatitcanusemanyof
themethodofCWnd.
Because the bitmap button is in fact a
customized version of a button, you must first
declareavariableorpointerofit:
CBitmapButton*btnMap=newCBitmapButton
Using the variable or pointer, you can call the Create() method to formally create the button.
Hereisanexample:
BOOLCDialog6Dlg::OnInitDialog()
{

CDialog::OnInitDialog()

...

btnMap>Create(NULL,WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,

CRect(10,10,100,100),this,IDC_BTN_NEW)

returnTRUE//returnTRUEunlessyousetthefocustoacontrol

//TODO:Addextrainitializationhere
CBitmapButton*btnMap=newCBitmapButton

BitmapButtonImplementation
Creatingabitmapbuttonwithoutanidentifierisconsideredcreatingitfromscratch.Creatinga
bitmapbuttonismorepracticalbecauseyoucaneasilyusethemessagesofsuchabuttonand
refertoitincode.Therefore,beforecreatingabitmapbutton,youcanfirstaddabuttontoa
dialog box and specify its identifier. For a button to display a picture, it must have the
BS_OWNERDRAW style. This means that you should check or set to True the Owner Draw
option.
Visually,themostappealingaspectofabitmapbuttonisthepictureitdisplays.Thebitmapcan
bedesignedfollowingthesametoolsandinstructionswereviewedfortheicons.Togivea3D
or realistic appearance to the button, you should mimic the focus effect when designing the
bitmaps.
Therefore,youshouldcreateonetofourbitmapsforthecontrol.Hereishowtheywouldwork:
Ifyoucreateonebitmap,itwouldbeusedforallclicksofthebutton.Sincethebutton
wouldalwaysappearthesame,youshouldavoidusingonlyonepicture
Ifyoucreatetwobitmaps,thefirstwoulddisplayastheregularpictureforthebutton,that
is,whenthebuttonisnotbeingclicked.Thesecondwouldbeusedwhenthebuttonis
clickedandthemouseisdownonthebutton
Ifyoucreatethreebitmaps,thefirstwoulddisplaywhenthebuttonisnotbeingaccessed
andanothercontrolhasfocus.Thesecondpicturewoulddisplaywhentheuserisclicking
thebuttonandaslongasthemouseisdownonthebutton.Thethirdwouldbeusedwhen
thebuttonhasfocusbutitisnotbeingused
Ifyoucreatethreebitmaps,thefirstwoulddisplaywhenthebuttonisnotbeingaccessed
andanothercontrolhasfocus.Thesecondpicturewoulddisplaywhentheuserisclicking
thebuttonandaslongasthemouseisdownonthebutton.Thethirdwouldbeusedwhen
thebuttonhasfocusbutitisnotbeingused.Thefourthwouldbeusedwhenthebuttonis
disabled

Since these options, to use a bitmap button to its fullest, you should strive to provide four
bitmaps.Aftercreatingthebitmaps,youcanloadthemintothebutton.Thisisdoneusingthe
LoadBitmaps()method.Itcomesintwoversionsasfollows:
BOOLLoadBitmaps(LPCTSTRlpszBitmapResource,

LPCTSTRlpszBitmapResourceSel=NULL,
LPCTSTRlpszBitmapResourceFocus=NULL,

LPCTSTRlpszBitmapResourceDisabled=NULL)
BOOLLoadBitmaps(UINTnIDBitmapResource,

UINTnIDBitmapResourceSel=0,

UINTnIDBitmapResourceFocus=0,

UINTnIDBitmapResourceDisabled=0)
Eachversiontakesfourarguments.Thefirstversionusesthebitmapsasstringresourceswhile
thesecondversionusesresourceidentifiers.
As stated above, you can one to four bitmaps. As seen on these functions, the first bitmap is
required. The first argument must specify the first or default bitmap and is required. The
secondargumentisthenameoridentifierofthebitmapthatwouldbeusedwhenthebuttonis
selected.Thethirdisusedwhenthebuttonhasfocus.Thelastbitmapisusedwhenthebutton
isdisabled.Hereisanexample:

BOOLCDialog6Dlg::OnInitDialog()
{

CDialog::OnInitDialog()

...

btnMap>Create(NULL,WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,

CRect(10,10,100,100),this,IDC_BTN_NEW)
btnMap>LoadBitmaps(IDB_BMP_BTN1,IDB_BMP_BTN2,IDB_BMP_BTN3,IDB_BMP_BTN4)

returnTRUE//returnTRUEunlessyousetthefocustoacontrol

//TODO:Addextrainitializationhere
CBitmapButton*btnMap=newCBitmapButton

Itisverylikelythatyoumaynotbeabletodesignthebuttonononehandandthebitmapson
the other hand at exactly the same dimensions. To adjust these measures, the
CBitmapButtonclassisequippedwiththeSizeToContent()method.Itssyntaxis:
voidSizeToContent()
Whenthismethodiscalledonthebutton,itresizesittothesizeofthebitmaps.Ifonebitmap
is larger and/or taller than the others, if you had loaded more than one, this method would
resizethebuttontothelargerandtallerbitmap.Forthisreason,alwaysmakesurethatyou
designbitmapsthathavethesamedimension.Hereisanexampleofusingthismethod:
BOOLCDialog6Dlg::OnInitDialog()
{

CDialog::OnInitDialog()

...

btnMap>Create(NULL,WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,

CRect(10,10,100,100),this,IDC_BTN_NEW)
btnMap>LoadBitmaps(IDB_BMP_BTN1,IDB_BMP_BTN2,IDB_BMP_BTN3,IDB_BMP_BTN4)
btnMap>SizeToContent()

returnTRUE//returnTRUEunlessyousetthefocustoacontrol

//TODO:Addextrainitializationhere
CBitmapButton*btnMap=newCBitmapButton

}
As you may realize if you create a bitmap button strictly using this approach, it would not
work. The suggestion is to "subclass" your button class so the messages sent to the bitmap
button would be applied effectively. The function used to do this is the
CWnd::SubclassDlgItem()methodanditssyntaxis:
BOOLSubclassDlgItem(UINTnID,CWnd*pParent)
The first argument is the resource ID of the existing button. The second argument is the
control that is hosting the button this is usually the dialog box but it can be another control
container.
1. OpentheGeometry1application
2. Onthemainmenu,clickInsert>Resource...ClickBitmapandclickNew
3. UsingtheProeprtieswindow,changethebitmapsIDtoIDB_CANCEL_DISABLEDandchangeits
sizetoWidth=75,Height=23
4. Designitasfollows:

5. Inthesamewayaddnewbitmaps.ChangetheirIDsanddesignthemasfollows:

IDB_CANCEL_FOCUS

IDB_CANCEL_NRM

IDB_CANCEL_SELECTED

IDB_HELP_DISABLED


IDB_HELP_FOCUS

IDB_HELP_NORMAL

IDB_HELP_SELECTED

IDB_OK_DEFAULT

IDB_OK_DISABLED

IDB_OK_FOCUS

IDB_OK_SELECTED

6. IntheheaderoftheCGeomeSheetclass,declarethreeCBitmapButtonvariablesasfollows:

private:

CBitmapButtonbtnBmpOK,btnBmpCancel,btnBmpHelp
}
7. Usetheconstructortoloadthebitmapsofeachbutton:

CGeomeSheet::CGeomeSheet(LPCTSTRpszCaption,CWnd*pParentWnd,UINTiSelectPage)

:CPropertySheet(pszCaption,pParentWnd,iSelectPage)
{

m_psh.dwFlags|=PSH_NOAPPLYNOW

AddPage(&Quad)
AddPage(&Circ)
AddPage(&G3D)

btnBmpOK.LoadBitmaps(IDB_OK_DEFAULT,IDB_OK_SELECTED,

IDB_OK_FOCUS,IDB_OK_DISABLED)

btnBmpCancel.LoadBitmaps(IDB_CANCEL_NORMAL,IDB_CANCEL_SELECTED,
IDB_CANCEL_FOCUS,IDB_CANCEL_DISABLED)

btnBmpHelp.LoadBitmaps(IDB_HELP_NORMAL,IDB_HELP_SELECTED,
IDB_HELP_FOCUS,IDB_HELP_DISABLED)
}
8. Tocustomizetheexistingbuttons,implementtheOnInitDialogeventoftheCGeomeSheetclass
asfollows(mostofthecodeisusedbecausethebuttonswerealreadycreatedbydefaultthis
meansthatwehavetomanuallychangetheirstyle):

BOOLCGeomeSheet::OnInitDialog()
{

BOOLbResult=CPropertySheet::OnInitDialog()

//TODO:Addyourspecializedcodehere
//Weneedahandletoeach
CButton*btnOK,*btnCancel,*btnHelp

//Getahandletoeachoftheexistingbuttons
btnOK=reinterpret_cast<CButton*>(GetDlgItem(IDOK))
btnCancel=reinterpret_cast<CButton*>(GetDlgItem(IDCANCEL))
btnHelp=reinterpret_cast<CButton*>(GetDlgItem(IDHELP))

//Getthestyleofthebutton(s)
LONGGWLOK=GetWindowLong(btnOK>m_hWnd,GWL_STYLE)
LONGGWLCancel=GetWindowLong(btnCancel>m_hWnd,GWL_STYLE)
LONGGWLHelp=GetWindowLong(btnHelp>m_hWnd,GWL_STYLE)

//Changethebutton'sstyletoBS_OWNERDRAW
SetWindowLong(btnOK>m_hWnd,GWL_STYLE,GWLOK|BS_OWNERDRAW)
SetWindowLong(btnCancel>m_hWnd,GWL_STYLE,GWLCancel|BS_OWNERDRAW)
SetWindowLong(btnHelp>m_hWnd,GWL_STYLE,GWLHelp|BS_OWNERDRAW)

//Subclasseachbutton
btnBmpOK.SubclassDlgItem(IDOK,this)
btnBmpCancel.SubclassDlgItem(IDCANCEL,this)
btnBmpHelp.SubclassDlgItem(IDHELP,this)

returnbResult

9. Testtheapplication:

10. Afterusingit,closeitandreturntoMSVC

Copyright20032010FunctionX,Inc.

WindowsControls:TheMFCButton

IntroductiontotheMFCButton

Description
MFC
Example
WindowsVC++

TheMFClibraryprovidesanotherenhancedversionoftheregular
Win32button.Ithasallthefeaturesofanormalbuttonplusthe
characteristics of the bitmap button. For example, it makes it
easy to show a picture on a button, to specify a cursor, and to
useatooltip.

CreatinganMFCButton
To visually create an MFC button, on the Toolbox, click MFC Button Control
thedialogboxyouaredesigning.

andclick

TheMFCbuttonusesaclassnamedCMFCButtonandthatisbasedontheCButtonclass.
Based on this, to programmatically get an MFC button, create a pointer to CMFCButton
and initialize it using the new operator. The CMFCButton class doesn't override the
Create()member function of its parent. Therefore, to specify the primary characteristics
of an MFC button, call the Create() member function of the CButton class. Here is an
example:
BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
CMFCButton*btnSubmit=newCMFCButton
CRectrctButton(10,12,125,44)
btnSubmit>Create(_T("Submit"),

WS_CHILD|WS_VISIBLE|BS_ICON,

rctButton,

this,

12004)
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}

CharacteristicsoftheMFCButton

Introduction
The MFC button is primarily a regular button. This means that, when or after creating it,
youcanconfigureorchangeitsstyletomakeitanormalbutton,aradionbutton,acheck
box, or a command button. Still, the reason you may want to use this button is for its
enhancedcharacteristics.
Likeanormalbutton,theMFCbuttondisplaysacaptionandhasanID.Aftercreatingthe
button, you should add a control variable so you can programmatically configure its
characteristics.

TheFlatStyleofanMFCButton
TheMFCbuttonsupportsvarioustypesofborders,referredtoasitsflatstyles.Tospecify
themduringdesign,clickthebutton on the dialog box and, in the Properties window, use
thevaluesoftheStylefield:

PHP code
generator
Generate PHP code
for any database.
AJAX,charts,dynamic
forms and more

Toletyouprogrammaticallyspecifytheflatstyle,theCMFCButtonclassisequippedwith
a property named m_nFlatStyle. To specify the flat style, access its value from
CMFCButton. The possible values are BUTTONSTYLE_3D, BUTTONSTYLE_FLAT,
BUTTONSTYLE_SEMIFLAT,andBUTTONSTYLE_NOBORDERS.Hereisanexample:
BOOLCExerciseDlg::OnInitDialog()
{

CDialogEx::OnInitDialog()

//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon

//TODO:Addextrainitializationhere
m_Calculate.m_nFlatStyle=CMFCButton::BUTTONSTYLE_FLAT

returnTRUE//returnTRUEunlessyousetthefocustoacontrol

UsingaCursor
By default, the MFC button displays the normal cursor when the mouse is positioned on it. The
MFC button gives you the option to use a different cursor. At design time, to specify that the
button will use a hand cursor, in the Properties window, click Cursor Type and select Hand. To
programmatically set the cursor to a hand, you can call the SetMouseCursorHand()member
function.Itssyntaxis:
voidSetMouseCursorHand()
To let you programmatically specify the cursor, the CMFCButton class provides the
SetMouseCursor()memberfunctionwhosesyntaxis:
voidSetMouseCursor(HCURSORhcursor)
Before calling this member function, you can first import a cursor file to your project. Call the
LoadCursor() function and pass its returned value to the CMFCButton::SetMouseCursor()
memberfunction.Hereisanexample:
BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
m_Calculate.SetMouseCursor(LoadCursor(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDC_CURSOR1)))
returnTRUE
}

UsingaToolTip

To provide more information about a button, you can display a tool tip when the mouse is
positioned on top of it. To do this visually, in the Properties window, click Tooltip and type the
desiredstring.Toletyouprogrammaticallycreateatooltip,theCMFCButtonclassisequipped
withtheSetTooltip()memberfunction.Itssyntaxis:
voidSetTooltip(LPCTSTRlpszToolTipText)
Hereisanexampleofcallingthisfunction:
BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
m_Calculate.SetTooltip(_T("Clickthisbuttontoperformthecalculation"))

returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}

DisplayinganIcon
To enhance the appearance of an MFC button, you can display an icon on its face. To support
this,theclassisequippedwithamemberfunctionnamedSetImageandthatisoverloadedwith
threeversions.Theversionforaniconusesthefollowingsyntax:
voidSetImage(HICONhIcon,

BOOLbAutoDestroy=TRUE,

HICONhIconHot=NULL,

HICONhIconDisabled=NULL,

BOOLbAlphaBlend=FALSE
)
Only the first argument is required. Before using it, you can first import an icon file to your
projectandgivethaticonanID.CalltheLoadIcon()functionandpassitsreturnedvaluetothe
CMFCButton::SetImage()memberfunction.Hereisanexample:
BOOLCExerciseDlg::OnInitDialog()
{

CDialogEx::OnInitDialog()

//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon

//TODO:Addextrainitializationhere

m_Calculate.SetImage(LoadIcon(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_ARROW)))

returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}
It is important to know that icons usually have a 16x16 or a 32x32 pixels size. If you call the
SetImage()memberfunction,the32x32pixelsizewouldbeused.Ifyou'dratherusethe16x16
size,youmayhavetocalltheLoadIcon()memberfunctionoftheCButtonclass.

DisplayingaPicture
If you don't want to deal with the size limits of an icon, you can call one of the other two
versionsoftheCMFCButton::SetItmage()memberfunctions.Theirsyntaxesare:
voidSetImage(HBITMAPhBitmap,

BOOLbAutoDestroy=TRUE,

HBITMAPhBitmapHot=NULL,

BOOLbMap3dColors=TRUE,

HBITMAPhBitmapDisabled=NULL)
voidSetImage(UINTuiBmpResId,

UINTuiBmpHotResId=0,

UINTuiBmpDsblResID=0)
Before using one of these versions, you should first import or design 1 to 4 bitmaps and give
them IDs. When you call this member function, you can pass the ID(s) of the bitmap(s) as
argument(s):
Ifyoupassonlythefirstargument,itwoulddisplayallthetime.Hereisanexample:
BOOLCExerciseDlg::OnInitDialog()
{

CDialogEx::OnInitDialog()

//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon

//TODO:Addextrainitializationhere
m_Calculate.SetImage(IDB_CALCULATE1)
returnTRUE//returnTRUEunlessyousetthefocustoacontrol

IfyoupasstwoIDswiththesecondIDasthehBitmapHotortheuiBmpHotResIdarguments,
thebitmapofthefirstwoulddisplaywhenthemouseisnotontopofthebutton.Thesecond
bitmapwoulddisplaywhenthemouseispositionedon,orpassesoverthebutton.Hereisan

example:
BOOLCExerciseDlg::OnInitDialog()
{

CDialogEx::OnInitDialog()

//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon

//TODO:Addextrainitializationhere
m_Calculate.SetImage(IDB_CALCULATE1,IDB_CALCULATE2)
returnTRUE//returnTRUEunlessyousetthefocustoacontrol

IfyoupassthreeIDswiththethirdargumentashBitmapDisabledoruiBmpDsblResIDofthe
memberfunction,thebitmapofthethirdIDwouldbeusedwhenthebuttonisdisabled.Here
isanexample:
BOOLCExerciseDlg::OnInitDialog()
{

CDialogEx::OnInitDialog()

//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon

//TODO:Addextrainitializationhere
m_Calculate.SetImage(IDB_CALCULATE1,IDB_CALCULATE2,IDB_CALCULATE3)
returnTRUE//returnTRUEunlessyousetthefocustoacontrol

PaintingtheBodyofaButtonWithaColor
To paint an MFC button with a color of your choice, you can call the SetFaceColor()member
function.Itssyntaxis:
voidSetFaceColor(COLORREFcrFace,BOOLbRedraw=TRUE)
Hereisanexample:
BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
m_Calculate.SetFaceColor(2252835)
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}

TheColorofTextonaButton
To specify the color used on the caption of an MFC button, you can call the SetTextColor()
memberfunctionwhosesyntaxis:
voidSetTextColor(COLORREFclrText)
Hereisanexample:
BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
m_Calculate.SetFaceColor(2252835)
m_Calculate.SetTextColor(RGB(255,255,205))
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}
You can also specify what color the caption should use when the mouse is positioned on the
button.ThisisdonebycallingtheSetTextHotColor()memberfunction.Itssyntaxis:
voidSetTextHotColor(COLORREFclrTextHot)
Hereisanexample:
BOOLCExerciseDlg::OnInitDialog()
{

CDialogEx::OnInitDialog()

//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon

SetIcon(m_hIcon,FALSE)

//Setsmallicon

//TODO:Addextrainitializationhere
m_Calculate.SetTextColor(RGB(255,255,205))
m_Calculate.SetTextHotColor(8468360)

returnTRUE//returnTRUEunlessyousetthefocustoacontrol

Home

Copyright20102011FunctionX,Inc.

WindowsControls:TheImageEditor

Introduction

C++Example
Controls
EditPicture

Animageeditorisadialogboxusedtochangethedesign
of a small picture (bitmap). The picture is usually the
type used on a button or on an object of that size. The
imageeditorisdividedinfoursections:

Thetopleftsectiondisplaysthepicturethatisbeingmodified.Itismadeofsmall
squares where each represents a pixel. The lowerleft section shows the current
preview of the bitmap. The topright sectioon allows the user to select one of 20
presetcolors.Itthe user wants a color that is not currently there, he or she can
clicktheOtherbutton.ThiswoulddisplaytheMFCColorsdialogboxwheretheuser
canselectacolorandclickOK.Thelowerrightsectionpresentsthetoolstheuser
canusetodesignthepicture.Aftermodifyingthepicture,tokeepthenewdesign,
theusercanclickOK.IftheuserclicksCancel,anychangethatwasmadeonthe
picturewouldbedismissed.

CreatinganImageEditor
A image editor is based on the CMFCImageEditorDialog class. This class is
derivedfromCDialogEx. To prepare the image editor, declare a variable of type
CMFCImageEditorDialog. The class is equipped with one constructor whose
syntaxis:
CMFCImageEditorDialog(
CBitmap*pBitmap,
CWnd*pParent=NULL,
intnBitsPixel=1
)
Thisconstructortakesthreeargumentsbutonlythefirstisrequired.Theminimum
pieceofinformationtoanimageeditoristhebitmapthatwoulddisplayonthetop
left side of the dialog box. The picture should have a size of 16x16 pixels or
less.Youcanfirstimportthepictureasaresource:

YoucandeclareavariableoftypeCBitmap,callitsLoadBitmap()memberandpass
the ID of the bitmap to it, then pass that CBitmap variable to the
CMFCImageEditorDialogconstructor.
SincetheCMFCImageEditorDialogclassisderivedfromCDialogEx,todisplayit
totheuser,callitsDoModal()memberfunction.Hereisanexample:
voidCExerciseDlg::OnBnClickedImageEditor()
{

//TODO:Addyourcontrolnotificationhandlercodehere

CBitmapbmpExercise

bmpExercise.LoadBitmapW(IDB_EXERCISE)

CMFCImageEditorDialogdlg(&bmpExercise)

dlg.DoModal()

PHP code
generator
Generate
PHP code
for any local
or remote
database.

DELPHI

DATA

ACCESS

Powerful Tool For Developing Cross- Database Client/Server Applications

Home

Copyright20102011FunctionX,Inc.

WindowsControls:TheCommand
Button

IntroductiontotheCommandButton

Description
MFC
Example
WindowsVC++

Acommandbuttonisanenhancedversionoftheregularbutton.
Itdisplaysagreenarrowiconontheleft,followedbyacaption
inregular size. Under the main caption, it can display another
smallercaptionthatservesashinttoprovidemoreinformation.
HerearetwoexamplesfromtheAddPrinterdialogbox:

CreatingaCommandButton
Tocreateacommandbutton,ontheToolbox,clicktheCommandButtonobject
clickthedialogboxyouaredesigning.Hereisanexample:

and

Afteraddingit,youcanresizeittothedimensionsofyourchoice.
To programmatically create a command button, get a pointer to CButton and initialize it
with the new operator. Call its Create() member function to specify the initial
characteristics of the button. Among the styles of the control, you must add
BS_COMMANDLINK.Hereisanexample:
BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
CButton*btnSubmit=newCButton
CRectrctButton(10,12,250,64)
btnSubmit>Create(_T("Submit"),

WS_CHILD|WS_VISIBLE|BS_COMMANDLINK,

rctButton,

this,

12004)

returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}

CharacteristicsofaCommandButton

Introduction
A command button is primarily a Win32 button. It is based on the MFC's CButton class. As a
normalMFCcontrol,afteraddingacommandbuttontoadialogbox,youcanacceptorchangethe
ID of the control. After adding the command button, if necessary (most of the time, for a
command button), you should add a control variable to it so youcanprogrammaticallyconfigure
its characteristics. This is because many of its properties are not available in the Properties
window.
Likearegularbutton,acommandbuttoncandisplayacaption.Ofcourse,youcanvisuallyspecify
itusingtheCaptionfieldinthePropertieswindow.Hereisanexample:

The caption appears in bold characters on the right side of the picture. By Microsoft Windows
standards,youcannotchangethealignmentofthepicture.

ADefaultCommandButton
Ifyouwantyourcommandbuttontobethedefault,atdesigntime,setitsBooleanDefaultButton
fieldtoTrueinthePropertieswindow.Ifyouareprogrammaticallycreatingthebutton,addthe
BS_DEFCOMMANDLINKstyle.
When a command button is set as the default, after using the dialog box, if the user presses
Enter,theactionofthedefaultbuttonexecutes.

TheNoteofaCommandButton
Besidestheregularcaption,youcanaddasentenceunderit.Tosupportthis,theCButtonclass
isequippedwithamemberfunctionnamedSetNote.Itssyntaxis:
BOOLSetNote(LPCTSTRlpszNote)
To specify the note, call this member function and pass the desired string to it. Here is an
example:
BOOLCExerciseDlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
m_CommandButton.SetNote(_T("Findthetrigonometricvaluesofaknownconstant"))
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}
Thiswouldproduce:

Toknowthecurrentnoteofanexistingcommandbutton,calltheGetNote()memberfunctionof
theCButtonclass.Thatfunctionisoverloadedwithtwoversionswhosesyntaxesare:

CStringGetNote()const
BOOLGetNote(LPTSTRlpszNote,UINT*cchNote)const
Thefirstversiondoesn'ttakeanyargumentanditproducesthenote.Thesecondversiontakesan
arrayvariableasastringanditisthatargumentthatwillproducethenote.Thesizeargumentis
the size of the note. To get the actual length of the note, you can call the GetNoteLength()
memberfunction.Itssyntaxis:
UINTGetNoteLength()const

TheBordersofaCommandButton
Whenacommandhasfocus,itshowssomeborders.Thisisalsothecaseifthebuttonappearsby
itself in a dialog box. When a command button has been clicked, it becomes surrounded by a
blackrectangle:

Asanormalbutton,whenacommandbuttonhasfocus,itsbodyshowsadottedrectangle:

Whentherearemanybuttons,thebuttonthathasfocusshowssomebordersandtheotherbutton
doesnot.Whenthemousepassesoverthebuttonthatdoesn'thavefocus,itsbordersareraised:

Alternatively,ifyouwantthecommandbuttontopermanentlyshowborders,youcanvisuallyset
the Modal Frame field to True in the Properties window. Here is an example of what it would
produce:

YoucanalsouseacombinationoftheClientEdge,theStaticEdge,andtheModalFramefields.

ImagesLists

IntroductiontoImageLists

Description
MFC
VisualC++
ImagePictures

Animagelistisanarrayofpicturesofthesamesize.The
picturesarecreatedasaseriesoficons,asinglebitmap,
oragroupofbitmaps.Eachiconorbitmapcanbelocated
using its index. The array is zerobased, meansing that
the first picture has an index of 0. The second has an
indexof1,etc.

Animagelistisnotatraditionalcontrol.Itdoesnotdisplaytotheuserwhoinfact
is never aware of it. It is used to complement a control that needs a series of
picturesforitsownuse.

CreatinganImageList
InanMFCapplication,animagelistisbasedontheCImageListclass.Thisobject
is created in two main steps that do not necessarily follow each other. On one
hand, you must have the pictures that will make the list. On the other hand, you
musthaveaCImageListvariableorpointer.
The easiest way is probably to first create the picture. There are two kinds:
maskedornonmasked.Anonmaskedimagelistisdesignedasanarrayofpictures
whereallpictureshavethesamewidthandthesameheightbutthepicturesdonot
havetobesquare.Hereisanexample:

Amaskedimagelistcontainstwopicturesofthesamewithandheight.Unlikethe
unmasked image list, both pictures of the masked image normally represent the
sameillustration.Thefirstpictureisincolorandthesecondwouldbemonochrome
(blackandwhite).Hereisanexample:

Toactuallycreateanimagelist,declareaCImageListvariableorpointerandcall
one of its Create() member functions to initialize it. It is provided in various
versionsasfollows:
BOOLCreate(intcx,

intcy,

UINTnFlags,

intnInitial,

intnGrow)
BOOLCreate(UINTnBitmapID,

intcx,

intnGrow,

COLORREFcrMask)
BOOLCreate(LPCTSTRlpszBitmapID,

intcx,

intnGrow,

COLORREFcrMask)
BOOLCreate(CImageList&imagelist1,

intnImage1,

CImageList&imagelist2,

intnImage2,

intdx,

intdy)
BOOLCreate(CImageList*pImageList)
Thefirstversionofthismemberfunctionallowsyoutodescribethetypeofimage
list that will be created. This is done by specifying the width (cx) of each picture,
theheight(cy)ofeachpicture,andaflagforthetypeofimagelisttocreate.The
nInitial argument is the number of images that the image list will contain. The
nGrow argument represents the number of images by which the image list can

grow.
If you had designed an unmasked bitmap using the image editor and you want to
initializeit,callthesecondorthethirdversionsoftheCreate()memberfunction.
ThenBitmapIDargumentistheidentifierofthebitmap.Ifyouwanttoprovidethe
string that contains the identifiers of the images, pass it as the lpszBitmapID
argument. The cx value represents the width of each picture. The crMask is the
color used to mask the transparency of the picture. Each pixel of the picture that
matches this color will turn to black. Here is an example of using this Create()
memberfunction:
BOOLCAnimation1Dlg::OnInitDialog()
{
CDialog::OnInitDialog()
SetIcon(m_hIcon,TRUE)//Setbigicon
SetIcon(m_hIcon,FALSE)//Setsmallicon
//TODO:Addextrainitializationhere
CImageListImgList
ImgList.Create(IDB_IMGLIST,48,4,RGB(255,55,5))
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}

OperationsonanImageLists

AddinganItem
Besides, or instead of using, the Create() member function, you can call
CImageList::Add()toaddabitmaptotheCImageListvariable.Itssyntaxes
are:
intAdd(CBitmap*pbmImage,

CBitmap*pbmMask)
intAdd(CBitmap*pbmImage,

COLORREFcrMask)
intAdd(HICONhIcon)
ThepbmImageargumentrepresentsthebitmaptobeadded,unlessyouwant
to add an icon, in which case you would use the third version. The pbmMask
argumentisthebitmapthatwillbeusedtomasktheimagelist.Youcanusea
colorinstead,inwhichcaseyouwouldpassaCOLORREFvalueasthesecond
argumenttothesecondversion.

DeletinganItem

If you want to remove a picture from the image list, call the
CImageList::Remove()memberfunction.Itssyntax:
BOOLRemove(intnImage)
ThenImageargumentistheindexofthepicturetoberemoved.

ReplacinganItem
Instead of removing a picture, you can just replace it with another picture.
ThisisdoneusingtheCImageList::Replace()memberfunctionwhosesyntaxes
are:
BOOLReplace(intnImage,CBitmap*pbmImage,CBitmap*pbmMask)
intReplace(intnImage,HICONhIcon)

DrawinganItem
Onceanimagelistisready,youcanuseitdirectlyinanapplicationormakeit
availabletoacontrolthatcanuseit.Onewayyoucanuseanimagelististo
display one or more of its pictures on a dialog box, a form, or a view. To do
this,youwouldcalltheCImageList::Draw()memberfunction.Itssyntaxis:
BOOLDraw(CDC*pdc,intnImage,POINTpt,UINTnStyle)
The first argument, pdc, specifies the device context on which you are
drawing.ThenImage argument is the index of the picture you want to draw.
Thept argument is a POINTor a CPoint value that specifies the location of
thenewpicture. The nStyle argument is a flag that specifies how the picture
willbedrawn.

PHP

CODE

GENERATOR

Generate PHP code for any local or remote database.

Home

Copyright20102011FunctionX,Inc.

WindowsControls:TheTimer

IntroductiontoTimers

Description
WindowsTimer
MFC
EventTimer

A timer is a nonspatial object that uses recurring lapses of time


from a computer or from an application. To work, every lapse of
period, the control sends a message to the operating system. The
messageis something to the effect of "I have counted the number
oflapsesyouaskedmetocount".

As opposed to the time set on a computer, a timer is partly but greatly under your control.
Usersdonotseenoruseatimerasacontrol.Asaprogrammer,youdecideif,why,when,
andhowtousethiscontrol.

PracticalLearning:IntroducingtheTimerControl
1. StartMicrosoftVisualStudio
2. Tocreateanewapplication,onthemainmenu,clickFile>NewProject...
3. Inthemiddlelist,clickMFCApplicationandsetthenametoCurrentTime1
4. ClickOK
5. Inthefirstpageofthewizard,clickNext
6. Inthesecondpageofthewizard,clickDialogbasedandclickNext
7. Inthethirdpageofthewizard,clickFinish
8. Onthedialogbox,clicktheTODOlabel
9. InthePropertieswindow,changethefollowingcharacteristics:
Caption:00:00:00AM
ID:IDC_CURRENT_TIME
10. Clickanunoccupiedareaofthedialogbox
11. InthePropertieswindow,clickFont(Size)thenclickellipsisbutton
12. IntheFontbox,selectTimesNewRoman
13. IntheFontStyle,clickBold
14. IntheSizebox,click24
15. ClickOK

16. Rightclickthe00:00:00AMlabelandclickAddVariable...
17. SettheCategorytoValue
18. MakesurethetypeissettoCStringandsetthenametom_CurrentTime
19. ClickFinish

CreatingaTimer
Unlikemostothercontrols,theMFCtimerhasneitherabuttontorepresentitnoraclass.To
create a timer, you simply call the SetTimer() member function of the CWnd class. Its
syntaxis:
UINTSetTimer(UINTnIDEvent,UINTnElapse,
void(CALLBACKEXPORT*lpfnTimer)(HWND,UINT,UINT,DWORD))
Thisfunctioncallcreatesatimerforyourapplication.Liketheothercontrols,atimerusesan
identifier. This is passed as the nIDEvent argument. As mentioned already, when it is
accessed, a timer starts counting up to a set value. Once it reaches that value,itstopsand
starts counting again. The nElapse argument specifies the number of milliseconds that the

timermustcountbeforestartingagain.ThelpfnTimer argument is the name of a procedure


thathandlesthetimingeventofthecontrol.ThisargumentcanbesettoNULL,inwhichcase
thetimingeventwouldrestontheCWnd'sresponsibility.

PracticalLearning:UsingTimerControls
1. IntheClassView,expandtheCurrentTime1projectandclickCCurrentTime1Dlg
2. InthelowerpartoftheClassView,doubleclickOnInitDialog
3. Changetheeventasfollows:
BOOLCCurrentTime1Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog()
//Add"About..."menuitemtosystemmenu.

PHP code
generator
Generate
PHP code
for any local
or remote
database.

//IDM_ABOUTBOXmustbeinthesystemcommandrange.
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX)
ASSERT(IDM_ABOUTBOX<0xF000)
CMenu*pSysMenu=GetSystemMenu(FALSE)
if(pSysMenu!=NULL)
{

BOOLbNameValid

CStringstrAboutMenu

bNameValid=strAboutMenu.LoadString(IDS_ABOUTBOX)

ASSERT(bNameValid)

if(!strAboutMenu.IsEmpty())

pSysMenu>AppendMenu(MF_SEPARATOR)

pSysMenu>AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu)

}
}
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE)

//Setbigicon
SetIcon(m_hIcon,FALSE)

//Setsmallicon
//TODO:Addextrainitializationhere
SetTimer(1,200,0)
returnTRUE//returnTRUEunlessyousetthefocustoacontrol
}

CharacteristicsofaTimer

SettingtheTimer
Whenatimerisaccessedormadeavailable,itstartscounting.OncethenElapsevalueofthe
CWnd::SetTimer() member function is reached, its sends a WM_TIMER message to the
application.

StoppingtheTimer
WesawthatatimerisinitiatedwithacalltoSetTimer().Whenyoudonotneedthetimer
anymore,calltheCWnd::KillTimer()memberfunction.Itssyntaxis:
BOOLKillTimer(intnIDEvent)
The nIDEvent argument identifies the timer that was created with a previous call to
SetTimer().

PracticalLearning:UsingtheOnTimerEvent
1. TogeneratetheOnTimer()event,intheClassView,clickCCurrentTime1Dlg
2. InthePropertieswindow,clicktheMessagesbutton
3. ClicktheWM_TIMERfieldandclickthearrowofitsbox
4. Select<Add>OnTimerandimplementtheeventasfollows:
voidCCurrentTime1Dlg::OnTimer(UINT_PTRnIDEvent)
{
//TODO:Addyourmessagehandlercodehereand/orcalldefault
CTimeCurrentTime=CTime::GetCurrentTime()
intiHours=CurrentTime.GetHour()
intiMinutes=CurrentTime.GetMinute()
intiSeconds=CurrentTime.GetSecond()
CStringstrHours,strMinutes,strSeconds

if(iHours<10)

strHours.Format(_T("0%d"),iHours)
else

strHours.Format(_T("%d"),iHours)
if(iMinutes<10)

strMinutes.Format(_T("0%d"),iMinutes)
else

strMinutes.Format(_T("%d"),iMinutes)
if(iSeconds<10)

strSeconds.Format(_T("0%d"),iSeconds)
else

strSeconds.Format(_T("%d"),iSeconds)
m_CurrentTime.Format(_T("%s:%s:%s"),strHours,strMinutes,strSeconds)
UpdateData(FALSE)
CDialogEx::OnTimer(nIDEvent)
}
5. Totesttheapplication,pressF5

6. Closethedialogboxandreturntoyourprogrammingenvironment

FASTREPORT

VCL

for Delphi/CB 5-XE6 Fast. Compact. Feature-rich.

Home

Copyright20102011FunctionX,Inc.

Potrebbero piacerti anche